使用自定義內核對圖像進行卷積。該功能將任意線性濾波器應用於圖像。支持就地操作。當光圈部分位於圖像外部時,該功能會根據指定的邊框模式插入異常像素值。
語法
函數原型:
dst=cv.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]])
參數:
參數 | 描述 |
src | 原圖像 |
dst | 目標圖像,與原圖像尺寸和通過數相同 |
ddepth | 目標圖像的所需深度 |
kernel | 卷積核(或相當於相關核),單通道浮點矩陣;如果要將不同的內核應用於不同的通道,請使用拆分將圖像拆分為單獨的顏色平面,然后單獨處理它們。 |
anchor | 內核的錨點,指示內核中過濾點的相對位置;錨應位於內核中;默認值(-1,-1)表示錨位於內核中心。 |
detal | 在將它們存儲在dst中之前,將可選值添加到已過濾的像素中。類似於偏置。 |
borderType | 像素外推法,參見BorderTypes |
該函數實際計算的是相關性,而不是卷積
$$\texttt{dst} (x,y) = \sum _{ \stackrel{0\leq x' < \texttt{kernel.cols},}{0\leq y' < \texttt{kernel.rows}} } \texttt{kernel} (x',y')* \texttt{src} (x+x'- \texttt{anchor.x} ,y+y'- \texttt{anchor.y} )$$
在內核足夠大(~11x11或者更大)的時候,該函數使用DFT算法,對於小內核則直接計算。
也可見,anchor相當於坐標軸平移。
其中ddepth表示目標圖像的所需深度,它包含有關圖像中存儲的數據類型的信息,可以是unsigned char(CV_8U),signed char(CV_8S),unsigned short(CV_16U)等等...
Input depth (src.depth()) | Output depth (ddepth) |
---|---|
CV_8U | -1/CV_16S/CV_32F/CV_64F |
CV_16U/CV_16S | -1/CV_32F/CV_64F |
CV_32F | -1/CV_32F/CV_64F |
CV_64F | -1/CV_64F |
Note:當ddepth=-1時,表示輸出圖像與原圖像有相同的深度。
例子
圖像內核是一個小矩陣,用於應用您可能在Photoshop或Gimp中找到的效果,例如模糊,銳化,輪廓或浮雕。它們還用於機器學習中的“特征提取”,這是一種用於確定圖像最重要部分的技術。在這種情況下,該過程更普遍地稱為“卷積”(參見:卷積神經網絡)。
有許多有趣的內核,下面一一介紹:
1、模糊(blur)
模糊內核消除了相鄰像素值之間的差異。內核如下:
0.0625 | 0.125 | 0.0625 |
0.125 | 0.25 | 0.125 |
0.0625 | 0.125 | 0.125 |
代碼:
import cv2 import numpy as np def solve(): src = cv2.imread("./Pictures/car001.jpg") if src is None: return -1 kernel = np.array(( [0.0625, 0.125, 0.0625], [0.125, 0.25, 0.125], [0.0625, 0.125, 0.0625]), dtype="float32") dst = cv2.filter2D(src, -1, kernel) htich = np.hstack((src, dst)) cv2.imwrite("./Pictures/car.jpg", htich) cv2.imshow('merged_img', htich) cv2.waitKey(0) return 0 if __name__ == "__main__": solve()
效果:
2、索貝爾(sobel)
sobel內核用於僅顯示特定方向上相鄰像素值的差異,分為left sobel、right sobel(檢測梯度的水平變化)、top sobel、buttom sobel(檢測梯度的垂直變化)。
例如,buttom sobel
-1 | -2 | -1 |
0 | 0 | 0 |
1 | 2 | 1 |
代碼與上面類似,只需修改krenel的值。
3、浮雕(emboss)
通過強調像素的差在給定方向的Givens深度的錯覺。在這種情況下,沿着從左上到右下的直線的方向。
-2 | -1 | 0 |
-1 | 1 | 1 |
0 | 1 | 2 |
效果:
4、大綱(outline)
一個輪廓內核(也稱為“邊緣”的內核)用於突出顯示的像素值大的差異。具有接近相同強度的相鄰像素旁邊的像素在新圖像中將顯示為黑色,而與強烈不同的相鄰像素相鄰的像素將顯示為白色。
-1 | -1 | -1 |
-1 | 8 | -1 |
-1 | -1 | -1 |
效果:
5、銳化(sharpen)
該銳化內核強調在相鄰的像素值的差異。這使圖像看起來更生動。
0 | -1 | 0 |
-1 | 5 | -1 |
0 | -1 | 0 |
效果:
6、拉普拉斯算子(laplacian operator)
拉普拉斯算子可以用於邊緣檢測,對於檢測圖像中的模糊也非常有用。
0 | 1 | 0 |
1 | -4 | 1 |
0 | 1 | 0 |
效果:
7、分身(identity)
這個非常簡單,就是原圖(不考慮邊界時),How boring!
0 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
拓展部分
正如您在本博文中所收集的那樣,我們必須 手動定義每個內核以應用各種操作,例如平滑,銳化和邊緣檢測。
如何定義內核達到你想要的效果,這並不是一件簡單的事情。
現在有一種神經網絡——CNN,通過應用卷積濾波器,非線性激活函數,匯集和反向傳播,CNN能夠學習過濾器(的權重),可以檢測網絡較低層中的邊緣和類似blob的結構 - 然后使用邊緣和結構作為構建塊,最終在網絡的更深層中檢測更高級別的對象(即,面部,貓,狗,杯等)。這樣就不必手動定義過濾器了。
參考鏈接:
1、Depth combination https://docs.opencv.org/master/d4/d86/group__imgproc__filter.html#filter_depths
2、cv2.filter2d()opencv中ddepth參數的解釋?https://stackoverflow.com/questions/43392956/explanation-for-ddepth-parameter-in-cv2-filter2d-opencv
3、Image-kernels Demo http://setosa.io/ev/image-kernels/