Các hàm trong opencv python
Trong bài này, chúng ta sẽ làm việc với các phần của chụp cắt lớp vi tính (CT) từ Kho lưu
trữ hình ảnh ung thư . CT sử dụng một ống tia X quay để tạo ra hình ảnh 3D trên vùng mục tiêu của cơ thể bệnh nhân. Hình ảnh thực tế phụ thuộc vào thiết bị được sử dụng: hình ảnh đo ánh sáng nhìn thấy, tia X và CT đo độ hấp thụ bức xạ, và máy quét MRI đo từ trường. Hãy sử dụng ImageIO:đọc
dữ liệu dưới dạng đối tượng +Nhân khẩu học của bệnh nhân: tên, tuổi, giới tính, thông tin lâm sàng. +Thông tin thu nhận: hình dạng hình ảnh, tỷ lệ lấy mẫu, loại dữ liệu, phương thức (chẳng hạn như X-Ray, CT hoặc MRI). Plot images: + + +Hình dạng, lấy mẫu và trường xem
(field of view). +Hình dạng hình ảnh (Image shape): số phần tử dọc theo mỗi trục. +Tốc độ lấy mẫu: không gian vật lý được bao phủ bởi từng phần tử. +Trường nhìn: không gian vật lý được bao phủ dọc theo mỗi trục. Các « ngăn xếp » (stacks) hình ảnh là một phương pháp hữu ích để hiểu
dữ liệu đa chiều. Mỗi chiều cao hơn là một chồng các mảng có chiều thấp hơn. Chúng ta sẽ sử dụng hàm Load volumes: Đối với ví dụ này, hãy đọc toàn bộ khối lượng dữ liệu não bộ từ thư mục « ./dataset/tcia-chest-ct-sample », chứa 5 hình ảnh DICOM. Field of view Khoảng không gian vật lý được bao phủ bởi một hình ảnh là trường nhìn của nó, được tính toán từ hai thuộc tính: +Hình dạng mảng, số phần tử dữ liệu trên mỗi trục. Có thể
được truy cập bằng thuộc tính +Độ phân giải lấy mẫu, lượng không gian vật lý được bao phủ bởi mỗi pixel. Đôi khi có sẵn trong siêu dữ liệu (ví dụ Để vẽ dữ liệu N chiều, hãy cắt nó! Chế độ xem không chuẩn +Trục (Plain) +Coronal (Hàng) +sagittal (Col) Tạo các ô phụ (cắt hình ảnh thành các ô):Bạn có thể tạo nhiều hình ảnh trong một hình để khám phá dữ liệu nhanh chóng. Sử dụng Ví dụ: fig, axes = plt.subplots(nrows=2, ncols=2) Để vẽ hình ảnh trên subplot, hãy gọi phương thức vẽ đồ thị trực tiếp từ đối tượng subplot chứ không phải thông qua PyPlot: fig, axes = plt.subplots(nrows=1, ncols=2) # Draw an images on each subplot axes[0].imshow(im1, cmap='gray'); axes[1].imshow(im2, cmap='gray'); # Remove ticks/labels and render axes[0].axis('off'); axes[1].axis('off'); Cắt hình ảnh 3D trong y tếCách đơn giản nhất để vẽ các hình ảnh 3D và 4D là làm bằng cách cắt chúng thành nhiều khung hình 2D. Việc vẽ nhiều lát một cách liên tiếp có thể tạo ra hiệu ứng « fly-through » giúp bạn hiểu toàn bộ hình ảnh. Để chọn khung 2D, hãy chọn khung cho trục đầu tiên và chọn tất cả dữ liệu từ hai khung còn lại: Ví dụ: fig, axes = plt.subplots(1, 5, figsize=(15, 10)) # Loop through subplots and draw image for ii in range(5): im = vol[ii, :, :] axes[ii].imshow(im, cmap='gray', vmin=-200, vmax=200) axes[ii].axis('off') Vẽ các chế độ xem khácBất kỳ hai kích thước nào của một mảng đều có thể tạo thành một hình ảnh và việc cắt dọc theo các trục khác nhau có thể cung cấp một góc nhìn hữu ích cho việc phân tích ảnh y tế. Tuy nhiên, tỷ lệ lấy mẫu không đồng đều có thể tạo ra hình ảnh bị méo. Thay đổi tỷ lệ khung hình có thể giải quyết vấn đề này bằng cách tăng chiều rộng của một trong các kích thước. Đối với ví dụ này, vẽ các hình ảnh cắt dọc theo chiều thứ hai và thứ ba của dữ liệu. Đặt tỷ lệ co (Explicitly set) một cách rõ ràng để tạo hình ảnh không bị biến dạng. im1 = vol[:, 256, :] im2 = vol[:, :, 256] # Compute aspect ratios d0, d1, d2 = vol.meta['sampling'] asp1 = d0 / d2 asp2 = d0 / d1 # Plot the images on a subplots array fig, axes = plt.subplots(2, 1, figsize=(15, 8)) axes[0].imshow(im1, cmap='gray', aspect=asp1); axes[1].imshow(im2, cmap='gray', aspect=asp2); Cắt hình ảnh để xử lý đến xương bằng cách biến đổi hình ảnh X quang. Bạn sẽ được hướng dẫn cách khai thác các mẫu với các cường độ khác nhau để chọn được các mảng con của một mảng và sẽ sử dụng các bộ lọc tích hợp để phát hiện các tính năng thú vị. Bạn cũng sẽ sử dụng mô-đun ndimage của SciPy, chứa một kho tàng các công cụ xử lý hình ảnh. import numpy as np import matplotlib.pyplot as plt import imageio plt.rcParams['figure.figsize'] = (10, 8) Pixels và voxels +Pixel: Yếu tố hình ảnh 2D +Voxel: Phần tử của ảnh 3D Biểu đồ (Histograms) +Đếm số lượng pixel ở mỗi giá trị cường độ (each intensity value) Cân bằng (Equalization) +Sự phân bố thường lệch về cường độ thấp (giá trị nền) tức low intensity (background values) +Phân bố lại các giá trị để tối ưu hóa toàn dải cường độ. Cường độ ảnh y tếTrong phần này, chúng ta sẽ làm việc với một bức ảnh chụp X quang tay từ một cuộc thi của Hiệp hội X quang Bắc Mỹ năm 2017 . Sự hấp thụ tia X cao nhất ở mô dày đặc như xương nên cường độ kết quả phải cao. Do đó, những hình ảnh như thế này có thể được sử dụng để dự đoán « tuổi xương » (« bone age ») ở trẻ em. Để bắt đầu, hãy tải hình ảnh lên Python và kiểm tra phạm vi cường độ của nó. Kiểu dữ liệu hình ảnh xác định phạm vi của các cường độ có thể có: ví dụ: số nguyên không dấu 8 bit ( def format_and_render_plot(): '''Custom function to simplify common formatting operations for exercises. Operations include: 1. Turning off axis grids. 2. Calling `plt.tight_layout` to improve subplot spacing. 3. Calling `plt.show()` to render plot.''' fig = plt.gcf() for ax in fig.axes: ax.axis('off') plt.tight_layout() plt.show() im = imageio.imread('./dataset/hand.png') im = im.astype('float64') print('Data type:', im.dtype) print('Min value:', im.min()) print('Max value:', im.max()) # Plot the grayscale image plt.imshow(im, cmap='gray', vmin=0, vmax=255); plt.colorbar(); Data type: float64 Min value: 3.0 Max value: 224.0 Histograms: Biểu đồ (Histograms) hiển thị sự phân bố các giá trị trong hình ảnh của bạn bằng cách phân loại từng phần tử theo cường độ của nó, sau đó đo kích thước của mỗi ngăn. Vùng dưới biểu đồ được gọi là hàm phân phối tích lũy (viết tắt là CDF-cumulative distribution function ). Nó đo tần suất xảy ra ở một phạm vi cường độ pixel nhất định. Đối với ví dụ này, chúng ta biểu diễn sự phân bố cường độ trong im bằng cách tính toán biểu đồ (Histograms) và hàm phân bố tích lũy và hiển thị chúng cùng nhau. def format_and_render_plot(): '''Custom function to simplify common formatting operations for exercises. Operations include: 1. Turning off axis grids. 2. Calling `plt.tight_layout` to improve subplot spacing. 3. Calling `plt.show()` to render plot.''' fig = plt.gcf() for ax in fig.axes: ax.legend(loc='center right') plt.show() import scipy.ndimage as ndi # Create a histogram, binned at each possible value hist = ndi.histogram(im, min=0, max=255, bins=256) # Create a cumulative distribution function cdf = hist.cumsum() / hist.sum() # Plot the histogram and CDF fig, axes = plt.subplots(2, 1, sharex=True) axes[0].plot(hist, label='Histogram'); axes[1].plot(cdf, label='CDF'); format_and_render_plot(); Bạn có thể thấy dữ liệu được tập hợp thành một số bản phân phối (separate distributions) riêng biệt, bao gồm sự nhiễu xung quanh, da, xương và artifacts. Đôi khi, chúng ta có thể tách biệt chúng với các ngưỡng toàn cục (tiền cảnh / hậu cảnh); sự phân bố chồng lên nhau khá nhiều (da / xương). Mặt nạ (Masks)Tạo mặt nạMặt nạ (Masks) là phương pháp chính để loại bỏ hoặc chọn các phần cụ thể của hình ảnh. Chúng là các mảng nhị phân cho biết liệu một giá trị có nên được đưa vào phân tích hay không. Thông thường, mặt nạ được tạo bằng cách áp dụng một hoặc nhiều phép toán logic ( logical operations) cho một hình ảnh. Đối với ví dụ này,chúng ta sẽ cố gắng sử dụng một ngưỡng cường độ đơn giản để phân biệt giữa da và xương trên phim chụp X quang bằng tay (the hand radiograph). def format_and_render_plot(): '''Custom function to simplify common formatting operations for exercises. Operations include: 1. Turning off axis grids. 2. Calling `plt.tight_layout` to improve subplot spacing. 3. Calling `plt.show()` to render plot.''' fig = plt.gcf() for ax in fig.axes: ax.axis('off') plt.tight_layout() plt.show() mask_bone = im >= 75 mask_skin = (im >= 35) & (im < 75) # Plot the skin (0) and bone (1) masks fig, axes = plt.subplots(1, 2) axes[0].imshow(mask_skin, cmap='gray') axes[1].imshow(mask_bone, cmap='gray') format_and_render_plot() ứng dụng của một mask: Mặc dù mặt nạ là nhị phân, chúng có thể được áp dụng vào hình ảnh để lọc ra các pixel ở các vị trí của mặt nạ
np.where(condition, x, y)
Hãy thử áp dụng mặt nạ bằng cách chọn các pixel giống như xương từ tia xquang bàn tay (the hand x-ray ) ( def format_and_render_plot(): '''Custom function to simplify common formatting operations for exercises. Operations include: 1. Turning off axis grids. 2. Calling `plt.tight_layout` to improve subplot spacing. 3. Calling `plt.show()` to render plot.''' fig = plt.gcf() fig.axes[0].axis('off') plt.tight_layout() plt.show() mask_bone = im >= 75 im_bone = np.where(mask_bone, im, 0) # Get the histogram of bone intensity hist = ndi.histogram(im_bone, min=1, max=255, bins=255) # Plot masked image and histogram fig, axes = plt.subplots(2, 1) axes[0].imshow(im_bone, cmap='gray') axes[1].plot(hist) format_and_render_plot() Chỉnh mặt nạ (Tune a mask):Mặt nạ không hoàn hảo có thể được điều chỉnh thông qua việc cộng và trừ các pixel. SciPy bao gồm một số tính năng hữu ích để thực hiện những mục tiêu này. Bao gồm các: + + + + Đối với ví dụ này,chúng ta hãy tạo một mặt nạ của xương sau đó điều chỉnh đểó bao gồm các pixel được bổ sung. mask_bone = im >= 75 mask_dilate = ndi.binary_dilation(mask_bone, iterations=5) mask_closed = ndi.binary_closing(mask_bone, iterations=5) # Plot masked images fig, axes = plt.subplots(1, 3) axes[0].imshow(mask_bone, cmap='gray') axes[1].imshow(mask_dilate, cmap='gray') axes[2].imshow(mask_closed, cmap='gray') format_and_render_plot() Bộ lọcChuyển đổi với bộ lọc làm sắc nét. Lọc biến (Filter convolutions):Bộ lọc là một công cụ thiết yếu trong xử lý ảnh. Chúng cho phép bạn chuyển đổi hình ảnh dựa trên các giá trị cường độ xung quanh một pixel, thay vì toàn bộ. Đối với ví dụ này, chúng ta hãy làm mịn ảnh X quang bàn chân. Đầu tiên, định rõ trọng số ( weights) sẽ được sử dụng. Chúng được gọi là « dấu chân » và « hạt nhân »(« footprints » and « kernels » ). Sau đó, xoay bộ lọc với im và vẽ biểu đồ kết quả. def format_and_render_plot(): '''Custom function to simplify common formatting operations for exercises. Operations include: 1. Turning off axis grids. 2. Calling `plt.tight_layout` to improve subplot spacing. 3. Calling `plt.show()` to render plot.''' fig = plt.gcf() for ax in fig.axes: ax.axis('off') plt.tight_layout() plt.show() weights = [[0.11, 0.11, 0.11], [0.11, 0.11, 0.11], [0.11, 0.11, 0.11]] # Convolve the image with the filter im_filt = ndi.convolve(im, weights) # Plot the images fig, axes = plt.subplots(1, 2) axes[0].imshow(im, cmap='gray') axes[1].imshow(im_filt, cmap='gray') format_and_render_plot() Làm mịn ảnh y tếLàm mịn có thể cải thiện tỷ lệ tín hiệu trên nhiễu (viết tắt là SNR) của hình ảnh của bạn bằng cách làm mờ về cường độ của các biến thể nhỏ . Bộ lọc Gaussian là một giải pháp tuyệt vời cho điều này. Độ rộng của sự phân bố được kiểm soát bởi đối số sigma, với các giá trị cao hơn dẫn đến hiệu ứng làm mịn lớn hơn. Đối với ví dụ này, chúng ta hãy kiểm tra tác động của việc áp dụng bộ lọc Gaussian vào phim chụp X-quang bàn chân trước khi tạo mặt nạ với xương. im_s1 = ndi.gaussian_filter(im, sigma=1) im_s3 = ndi.gaussian_filter(im, sigma=3) # Draw bone masks of each image fig, axes = plt.subplots(1, 3) axes[0].imshow(im >= 75, cmap='gray') axes[1].imshow(im_s1 >= 75, cmap='gray') axes[2].imshow(im_s3 >= 75, cmap='gray') format_and_render_plot() Dò tìm các tính năng của ảnhPhát hiện các cạnh (Detect edges) (1):Bộ lọc cũng có thể được sử dụng làm « máy dò »(« detectors »). Nếu một phần của hình ảnh phù hợp với mẫu trọng số, giá trị trả về sẽ rất cao (hoặc rất thấp).Trong trường hợp phát hiện cạnh, mẫu đó có sự thay đổi cường độ dọc theo một mặt phẳng. Bộ lọc giúp phát hiện các cạnh ngang có thể trông như thế này: weights = [[+1, +1, +1], [ 0, 0, 0], [-1, -1, -1]] Đối với ví dụ này,chúng ta hãy tạo một bộ dò dọc cạnh và xem nó hoạt động tốt như thế nào trên ảnh X-quang bàn tay (im). weights = [[1, 0, -1], [1, 0, -1], [1, 0, -1]] # Convolve "im" with filter weights edges = ndi.convolve(im, weights) # Draw the image in color plt.imshow(edges, cmap='seismic', vmin=-75, vmax=75); plt.colorbar(); format_and_render_plot(); Phát hiện các cạnh ảnh y tế (2): Việc phát hiện cạnh có thể được thực hiện dọc theo nhiều trục.Sau đó,chúng được kết hợp thành một giá trị với cạnh duy nhất. Đối với hình ảnh 2D, « bản đồ cạnh » (« edge maps » ) ngang và dọc có thể được kết hợp bằng cách sử dụng định lý Pitago: Một bộ dò cạnh phổ biến là bộ lọc Sobel . Bộ lọc Sobel cung cấp thêm các trọng số cho các pixel ở trung tâm của bộ dò tìm: weights = [[ 1, 2, 1], [ 0, 0, 0], [-1, -2, -1]] Đối với ví dụ này, chúng ta hãy cải thiện sự phát hiện trước đó bằng cách hợp nhất kết quả của hai hình ảnh được lọc Sobel thành một bản đồ cạnh tổng hợp (composite edge map). def format_and_render_plot(): '''Custom function to simplify common formatting operations for exercises. Operations include: 1. Turning off axis grids. 2. Calling `plt.tight_layout` to improve subplot spacing. 3. Calling `plt.show()` to render plot.''' fig = plt.gcf() fig.axes[0].axis('off') plt.show() sobel_ax0 = ndi.sobel(im, axis=0) sobel_ax1 = ndi.sobel(im, axis=1) # Calculate edge magnitude edges = np.sqrt(np.square(sobel_ax0) + np.square(sobel_ax1)) plt.imshow(edges, cmap='gray', vmax=75) format_and_render_plot() Nguồn tham khảo: godboychan Người viết và tổng hợp: +Fb: https://www.facebook.com/NguyenCongTrinh213/ +Instagram: https://www.instagram.com/nguyencongtrinh213/ |