Lọc hình ảnh (làm mịn ảnh, làm cho mượt ảnh) là 1 trong bước rất đặc trưng trong xử lý ảnh. Lọc ảnh thực tế tất cả rất nhiều công dụng như loại trừ nhiễu, tra cứu biên đối tượng. Bài viết này sẽ trình làng nguyên tắc bình thường của lọc hình ảnh và một vài phép lọc ảnh cơ bản.
Bạn đang xem: Gaussian blur là gì
Bạn sẽ xem: Sự khác biệt Giữa Bokeh với Gaussian Blur Là Gì ? Gaussian Blur Là GìBạn vẫn xem: Gaussian blur là gì
A. Lý lẽ chung của thanh lọc ảnh
Nguyên tắc bình thường của các cách thức lọc là mang lại ma trận ảnh nhân với cùng một ma trận lọc (Kernel). Ma trận lọc lọc (Kernel) còn rất có thể được gọi là cửa ngõ số chập (trong phép nhân chập), cửa sổ lọc, khía cạnh nạ,… Trong bài viết này tôi sử dụng thuật ngữ ma trận thanh lọc (Kernel).
Việc nhân hình ảnh với ma trận lọc y hệt như việc trượt ma trận thanh lọc theo hàng trên hình ảnh và nhân cùng với từng vùng của ảnh, cộng các kết quả lại sản xuất thành tác dụng của điểm hình ảnh trung tâm.
Minh họa việc nhân ma trận ảnh. Hình ảnh được rước từ https://github.com/vdumoulin/conv_arithmetic
Ma trận đầu vào I được nhân với ma trận thanh lọc (phần xám sống hình trái) để chế tác thành ma trận đầu ra output O.
Trên thực tế, bọn họ sẽ thấy gồm 2 phép lọc hình ảnh là tương quan (correlation) cùng tích chập (convolution). Với phép tương quan, ma trận lọc sẽ đượt trượt đi cùng nhân cùng với từng vùng của hình ảnh như trên. Mặc dù với phép tích chập, ma trận lọc sẽ tiến hành xoay 180 độ (theo cả chiều ngang cùng dọc) trước khi triển khai nhân. 2 phép toán này là tương đương khi ma trận thanh lọc đối xứng.
Với từng phép lọc ta bao hàm ma trận lọc (Kernel) khác nhau, không tồn tại một quy định rõ ràng nào mang lại việc khẳng định M. Size ma trận M là một số lẻ. Ví dụ: 3x3, 5x5.
Khi nhân các phần tử tương ứng cùng nhau (giữa pixel, các điểm ở kề bên – những thành phần trong kernel), đối với các phần tử ở cạnh thì đã có một vài pixel bị khuyết, thời điểm này, có khá nhiều cách giải quyết như vứt qua, chèn thêm một (một số) hàng, cột với giá trị 0 hoặc bằng giá trị ngay sát nhất, hoặc tạo ra một đối xứng gương ngơi nghỉ cạnh ảnh.
Tổng Tpt những phẩn tử vào ma trận M thường xuyên là 1.
Tpt > 1: Ảnh sau khi thực hiện hoàn thành phép thanh lọc số ảnh (Idst) bao gồm độ sáng lớn hơn so với hình ảnh ban đầu (Isrc).**Tpt dst) bao gồm độ sáng nhỏ dại hơn so với ảnh ban đầu (Isrc).Ví dụ
$$M = eginbmatrix1/9 và 1/9 và 1/9 1/9 & 1/9 và 1/9 1/9 và 1/9 & 1/9 endbmatrix$$
B. Một số bộ lọc có tác dụng mịn ảnh
1. Thanh lọc trung bình (Normalized Box Filter)
Đây là bộ lọc đơn giản nhất. Nó được phát hành dựa trên ý tưởng tính quý giá một điểm ảnh bằng vừa phải cộng các điểm ảnh xung quanh nó.
Ma trận thanh lọc của lọc trung bình có dạng:
$$K = frac1K_width cdot K_heighteginbmatrix1 & 1 và 1 & ldots và 1 1 & 1 và 1 và ldots & 1 cdot và cdot và cdot & ldots và 1 1 và 1 và 1 và ldots và 1endbmatrix$$
Cách lọc này thường xuyên được vận dụng cho làm cho trơn ảnh vẫn mong muốn giữ lại biên không biến thành mờ.
Code cùng với Python - OpenCV: Đoạn code sau sẽ triển khai lọc ảnh với ma trận thanh lọc trung bình 5 x 5. Lưu giữ ý: toàn bộ mã nguồn và hình hình ảnh dùng trong bài viết có thể được mua về tại links trong mục Tham khảo.
$$K = frac125 eginbmatrix 1 & 1 và 1 & 1 & 1 1 & 1 & 1 và 1 và 1 1 và 1 và 1 & 1 & 1 1 & 1 và 1 và 1 & 1 1 và 1 & 1 và 1 & 1 endbmatrix$$
1import cv2 as cv 2import numpy as np 3from matplotlib import pyplot as plt 4 5# Load and blur image 6img = cv.imread('rose_gauss.jpg') 7img2 = cv.imread('rose_salt_and_pepper.jpg') 8blur = cv.blur(img,(5,5)) 9blur2 = cv.blur(img2,(5,5))1011# Convert màu sắc from bgr (OpenCV default) lớn rgb12img_rgb = cv.cvtColor(img, cv.COLOR_BGR2RGB)13blur_rgb = cv.cvtColor(blur, cv.COLOR_BGR2RGB)14img_rgb2 = cv.cvtColor(img2, cv.COLOR_BGR2RGB)15blur_rgb2 = cv.cvtColor(blur2, cv.COLOR_BGR2RGB)1617# Display18plt.subplot(221),plt.imshow(img_rgb),plt.title('Gauss Noise')19plt.xticks(), plt.yticks()20plt.subplot(222),plt.imshow(blur_rgb),plt.title('Gauss Noise - Blurred')21plt.xticks(), plt.yticks()22plt.subplot(223),plt.imshow(img_rgb2),plt.title('Salt&Pepper Noise')23plt.xticks(), plt.yticks()24plt.subplot(224),plt.imshow(blur_rgb2),plt.title('Salt&Pepper Noise - Blurred')25plt.xticks(), plt.yticks()26plt.show()Sau trên đây là hiệu quả sau lúc chạy đoạn code trên:
Chú ý: bạn cần cài gói matplotlib (dùng pip) và tkinter để thực hiện với Python. Cùng với Python 3.6, việc thiết đặt tkinter hoàn toàn có thể sử dụng:
Trên thực tế, gắng vì áp dụng hàm cv2.blur() thì cỗ lọc trung bình hoàn toàn có thể được sử dụng với hàm: cv2.filter2D() cùng với một tham số là ma trận lọc.kernel = np.ones((5,5),np.float32)/25blur = cv.filter2D(img,-1,kernel)Khi nạm ma trận thanh lọc trung bình bằng một ma trận khác, chúng ta cũng có thể có phần đông phép lọc khác ví như lọc thông phải chăng (low-pass filters(LPF)) hoặc lọc thông cao (high-pass filters(HPF) ).
2. Lọc Gauss (Gaussian Filter)
Bộ lọc Gauss được cho là bộ lọc bổ ích nhất, được thực hiện bằng phương pháp nhân chập ảnh đầu vào với một ma trận thanh lọc Gauss kế tiếp cộng chúng lại để tạo ra thành hình ảnh đầu ra.
Ý tưởng chung là giá trị mỗi điểm ảnh sẽ nhờ vào nhiều vào những điểm hình ảnh ở gần hơn là các điểm ảnh ở xa. Trọng số của sự phụ thuộc vào được mang theo hàm Gauss (cũng được thực hiện trong quy luật cung cấp chuẩn).
Dưới đó là biểu diễn ma trận lọc Gauss:
Giả sử hình ảnh là một chiều. Điểm ảnh ở trung tâm sẽ có được trọng số lớn nhất. Các điểm ảnh ở càng xa trung tâm sẽ có được trọng số giảm dần khi khoảng cách từ bọn chúng tới điểm nóng tăng lên. Vì thế điểm càng gần trung trung tâm sẽ càng đóng góp nhiều hơn thế nữa vào quý giá điểm trung tâm.
Chú ý: trên thực tế, vấn đề lọc hình ảnh dựa bên trên hàm Gauss 2 chiều (ngang với dọc). Phân phối chuẩn 2 chiều rất có thể biểu diễn dưới dạng:
$$G_0(x, y) = A e^ dfrac -(x - mu_x)^2 2sigma^2_x + dfrac -(y - mu_y)^2 2sigma^2_y $$
Trong kia $mu $ là mức độ vừa phải (đỉnh), $sigma^2$ là phương sai của những biến số $x$ với $y$.
Tham số $mu$ quyết định chức năng của cỗ lọc Gauss lên ảnh. Độ béo của ma trận thanh lọc (kernel) rất cần phải lựa chọn cho vừa khéo rộng.
Bạn cũng rất có thể tạo một ma trận lọc Gauss và sử dụng với hàm cv.filter2D() phía trên bằng cách sử dụng: cv.getGaussianKernel().3. Lọc trung vị
Phép lọc trung vị cũng được thực hiện tại với những ma trận lọc. Mặc dù nó tính trung vị tất cả các cực hiếm điểm hình ảnh trong vùng ma trận thanh lọc và thực hiện trung vị này mang đến giá trị điểm trung tâm. Một điều khá thú vị là với các cách lọc ở trên, quý giá điểm trung tâm được tính mới (có thể bằng hoặc khác với mức giá trị một điểm trong vùng ma trận lọc), còn với phép thanh lọc trung vị, giá trị điểm trung tâm luôn được thay bằng một cực hiếm điểm ảnh trong bức hình ảnh đầu vào. Vị vậy, cách thức lọc này có chức năng loại vứt nhiễu muối bột tiêu (salt-and-pepper noise ) hơi tốt.
Có một điểm cũng cần phải được chú ý là phép thanh lọc trung bình và lọc Gauss là phép lọc tuyến đường tính, mà lại phép thanh lọc trung vị không phải là 1 trong phép lọc con đường tính.
Để sử dụng lọc trung vị trong OpenCV, ta cần sử dụng hàm: cv.medianBlur().
Tương tự nhị ví dụ sinh hoạt trên, ta thay bước lọc thành:
Kết quả thực hiện lọc trung vị với một số trong những nhiễu:Có thể thấy rõ, với việc lọc trung vị, nhiễu muối hạt tiêu đang được đào thải tốt hơn những so với thanh lọc trung bình tốt lọc Gauss.
4. Cỗ lọc Bilateral (bộ lọc nhị chiều)
cv.bilateralFilter() là một trong những bộ lọc hiệu quả cao trong bài toán loạt vứt nhiễu cơ mà vẫn cất giữ được các đường viền (cạnh) vào ảnh.
Như bọn họ đã biết, cỗ lọc Gauss ra quyết định giá trị một điểm hình ảnh bằng giải pháp lấy mức độ vừa phải theo hàm Gauss những giá trị điểm hình ảnh xung quanh điểm đó. Hàm trọng số Gauss chỉ nhờ vào vào khoảng cách trong không khí so cùng với điểm hình ảnh trung tâm, không lưu ý đến sự đối sánh tương quan giữa nấc xám của tâm điểm với những điểm bao bọc đó. Nó cũng không thân thiện rằng điểm hình ảnh trung trọng tâm có nằm tại một đường biên trong ảnh không, chính vì như vậy làm nhòe luôn luôn các đường biên giới trong ảnh.
Bộ thanh lọc Bilateral cũng thực hiện một bộ lọc Gauss với khoảng cách đến điểm trung tâm, bảo đảm an toàn chỉ có các điểm ở ngay gần tham gia vào giá trị của điểm ảnh trung tâm. Mặc dù vậy nó thực hiện thêm một hàm Gauss mang lại mức xám, bảo vệ chỉ những điểm ảnh có mức xám tương đương với điểm hình ảnh trung vai trung phong tham gia vào quá trình làm mịn. Vì thế bộ thanh lọc Bilateral bảo toàn được những đường biên trong hình ảnh bởi vày điểm ảnh ở biên có sự chuyển đổi về mức xám rất rõ ràng ràng. Rộng nữa, cầm cố vì chuyển động trên những kênh màu sắc một bí quyết riêng rẽ như cỗ lọc vừa đủ hay bộ lọc Gauss, bộ lọc Bilateral thi hành việc đo đạc color có chủ đích trong không gian màu CIE-Lab , làm mượt màu và bảo toàn các biên theo hướng phù hợp hơn với dấn thức bé người.
Tuy vậy, cỗ lọc Bilateral cũng đều có nhược điểm là chậm chạp hơn các bộ lọc khác.
Sau đấy là cách áp dụng bộ thanh lọc Bilateral trong OpenCV:
Kết quả: Hình 1 áp dụng phép lọc Bilateral, hình 2 thực hiện phéo thanh lọc Gauss. Hãy thử chạy với những phép lọc khác nhé.Như chúng ta cũng có thể thấy, những texture được lọc rất tốt trong khi các đường biên trong hình ảnh vẫn được bảo toàn, không bị mờ đi.
Hình 1: Phép lọc Bilateral
Hình 2: Phép thanh lọc Gauss
Các bạn có thể đọc thêm về bộ lọc Bilateral tại: http://people.csail.mit.edu/sparis/bf_course/.
C. Một trong những bộ lọc search biên ảnh
Ngoài vấn đề làm mịn ảnh, một vài bộ thanh lọc còn có công dụng tìm biên của ảnh.
1. Contact giữa đạo hàm với biên ảnh
Xét vị dụ sau: Ta có một hình hình ảnh (1) với 2 biên đã được thiết kế mờ. Hình (2) cho thấy thêm mức xám tại con đường quét màu đỏ của ảnh. Tiện lợi nhận thấy những đường biên ảnh chính là 2 vùng có sự thay đổi đột ngột về mức xám. Để khẳng định những sự thay đổi này, ta thực hiện đạo hàm của dải nấc xám và tìm những cực trị (địa phương) trên đó. Hoàn toàn có thể thấy rõ mối liên hệ giữa những cực trị địa phương của đạo hàm với những biên vào ảnh.
Liên hệ thân đạo hàm và biên ảnh
2. Gradient của bức ảnh
Vậy là những biên của ảnh sẽ tất cả quan hệ cùng với đạo hàm theo chiều x cùng đạo hàm theo chiều y của mức xám. Gradient của ảnh là một đại lượng véc tơ sinh ra từ 2 đạo hàm này và sẽ tiến hành sử dụng nhằm lọc biên vào ảnh.
Công thức của Gradient là:
$$riangledown f = eginbmatrix fracpartial fpartial x , fracpartial fpartial y endbmatrix$$
3. Sobel với Scharr
Phép Sobel là sự phối kết hợp giữa làm mịn Gauss với phép vi phân, vì thế nó ít bị ảnh hưởng bởi nhiễu.
Việc phối hợp này chưa hẳn là việc lọc nhiễu bằng phép Gauss trước, rồi thực hiện Sobel nhằm tìm biên mà phép Gauss với Sobel đã được phối kết hợp để tạo nên một ma trân lọc (kernel) rồi sau đó nhân chập ma trận này cùng với ảnh. Hãy thuộc xem tại sao hoàn toàn có thể làm được như vậy:
Xét một hàm nút xám $f$ , ma trận lọc Gauss $h$, ta có công thức:
$$fracpartialpartial xleft( h * f ight) =left( fracpartialpartial x h ight) * f$$
Như vậy, vắt vì vận dụng bộ thanh lọc Gauss lên ảnh (kích thước tương đối lớn) rồi áp dụng lọc Sobel nhằm tìm biên, ta rất có thể áp dụng phép Sobel lên ma trận Gauss (kích thước nhỏ) rồi tiếp đến nhân chập ma trận thu được với hình ảnh để mang đến ra kết quả tương tự. Bài toán này sẽ giảm đáng kể chi phí tính toán.
Trong OpenCV, chúng ta cũng có thể chỉ định được hướng đạo hàm (theo chiều ngang xuất xắc chiều dọc). Bạn cũng có thể chỉ định size ma trận lọc với thông số ksize. Nếu ksize = -1, cỗ lọc Scharr 3x3 sẽ được sử dụng thay vị Sobel 3x3 nhằm có công dụng tốt hơn.
Xem thêm: Lý Thuyết Địa Lí 11 Bài 6 Tiết 2 Địa 11 Bài 6 Tiết 2: Kinh Tế
4. Laplacian
Laplacian được tính theo công thức:
$$Delta src = fracpartial ^2srcpartial x^2 + fracpartial ^2srcpartial y^2$$
Với ksize = 1, ma trận lọc sẽ được sử dụng là:
$$kernel = eginbmatrix 0 & 1 và 0 1 & -4 và 1 0 và 1 & 0 endbmatrix$$
Cài đặt Sobel với Laplace vào OpenCV:
1import numpy as np 2import cv2 as cv 3from matplotlib import pyplot as plt 4img = cv.imread('dave.jpg',0) 5laplacian = cv.Laplacian(img,cv.CV_64F) 6sobelx = cv.Sobel(img,cv.CV_64F,1,0,ksize=5) 7sobely = cv.Sobel(img,cv.CV_64F,0,1,ksize=5) 8plt.subplot(2,2,1),plt.imshow(img,cmap = 'gray') 9plt.title('Original'), plt.xticks(), plt.yticks()10plt.subplot(2,2,2),plt.imshow(laplacian,cmap = 'gray')11plt.title('Laplacian'), plt.xticks(), plt.yticks()12plt.subplot(2,2,3),plt.imshow(sobelx,cmap = 'gray')13plt.title('Sobel X'), plt.xticks(), plt.yticks()14plt.subplot(2,2,4),plt.imshow(sobely,cmap = 'gray')15plt.title('Sobel Y'), plt.xticks(), plt.yticks()16plt.show()Kết quả:
Vấn đề quan trọng khi thiết kế với Python - OpenCV:
Đoạn code dưới đây sẽ mô tả quá trình thực hiện. Ảnh đầu vào là một trong những hình chữ nhật white trên nền đen. Ta thực hiện việc kiếm tìm cạnh theo chiều ngang (lấy các cạnh dọc). Nếu sử dụng kiểu dữ liệu np.uint8, ở kề bên phải bị mất (do cạnh này được hình thành bởi vì sự chuyển dịch màu trắng -> đen). Để có cả hai cạnh, ta yêu cầu làm như giải pháp đã nêu trên.
1import numpy as np 2import cv2 as cv 3from matplotlib import pyplot as plt 4img = cv.imread('box.png',0) 5# đầu ra dtype = cv.CV_8U 6sobelx8u = cv.Sobel(img,cv.CV_8U,1,0,ksize=5) 7# output dtype = cv.CV_64F. Then take its absolute & convert to lớn cv.CV_8U 8sobelx64f = cv.Sobel(img,cv.CV_64F,1,0,ksize=5) 9abs_sobel64f = np.absolute(sobelx64f)10sobel_8u = np.uint8(abs_sobel64f)11plt.subplot(1,3,1),plt.imshow(img,cmap = 'gray')12plt.title('Original'), plt.xticks(), plt.yticks()13plt.subplot(1,3,2),plt.imshow(sobelx8u,cmap = 'gray')14plt.title('Sobel CV_8U'), plt.xticks(), plt.yticks()15plt.subplot(1,3,3),plt.imshow(sobel_8u,cmap = 'gray')16plt.title('Sobel abs(CV_64F)'), plt.xticks(), plt.yticks()17plt.show()Chuyên mục: Hỏi Đáp