OpenCV之影象處理(十六) 卷積運算元與自定義線性濾波
阿新 • • 發佈:2019-01-03
卷積概念 卷積是影象處理中一個操作,是kernel在影象的每個畫素上的操作。 Kernel本質上一個固定大小的矩陣陣列,其中心點稱為錨點(anchor point) 卷積如何工作 把kernel放到畫素陣列之上,求錨點周圍覆蓋的畫素乘積之和(包括錨點),用來替換錨點覆蓋下畫素點值稱為卷積處理。 Sum = 8x1+6x1+6x1+2x1+8x1+6x1+2x1+2x1+8x1 New pixel = sum / (m*n) 每個卷積和都要除以kernel的尺寸? 卷積的作用:模糊影象,提取邊緣,進行影象的銳化 卷積和常稱為(卷積)運算元,常見運算元: Robert運算元:┌ +1 0 ┐ ┌ 0 +1 ┐ 也可以用來尋找梯度,尋找邊緣 主對角線與副對角線上的梯度 └ 0 -1 ┘ └ -1 0 ┘ Sobel運算元 :┌ -1 0 1 ┐ ┌ -1 -2 -1 ┐ 也可以用來尋找梯度,尋找邊緣 水平與垂直方向的梯度 │ -2 0 2 │ │ 0 0 0 │ └ -1 0 1 ┘ └ 1 2 1 ┘ 拉普拉斯運算元: ┌ 0 -1 0 ┐ 用來尋找梯度,尋找邊緣 整個的梯度,整體輪廓 │ -1 4 -1 │ └ 0 -1 0 ┘
程式碼
#include "../common/common.hpp" static void customFilter(); void main(int argc, char** argv) { Mat src, dst1, dst2, dst3, dst4, dst5, dst6; src = imread(getCVImagesPath("images/test1_3.png"), IMREAD_COLOR); //影象在主對角線(x)方向的差異得到了明顯的體現,這些差異就像影象的邊緣一樣 Mat robertX = (Mat_<int>(2, 2) << 1, 0, 0, -1);//robert x方向 運算元 前兩個引數表示卷積的第一行 filter2D(src, dst1, -1, robertX, Point(-1, -1), 0.0);//計算卷積和,引數delta 表示計算出來的畫素+delta imshow("robertX", dst1); //影象在副對角線(y)方向的差異得到了明顯的體現,將這兩個x y方向的影象合起來,就能得到影象的輪廓 Mat robertY = (Mat_<int>(2, 2) << 0, 1, -1, 0);//robert y方向 運算元 filter2D(src, dst2, -1, robertY, Point(-1, -1), 0.0); imshow("robertY", dst2); //影象在左右(x)方向的差異得到了明顯的體現,由於是 -2 2 ,所以sobel比robert運算元差異體現的更大 Mat sobelX = (Mat_<int>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);//sobel x方向 運算元 filter2D(src, dst3, -1, sobelX, Point(-1, -1), 0.0); imshow("sobelX", dst3); //影象在上下(y)方向的差異得到了明顯的體現 Mat sobelY = (Mat_<int>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);//sobel y方向 運算元 filter2D(src, dst4, -1, sobelY, Point(-1, -1), 0.0); imshow("sobelY", dst4); //影象整體上的差異得到了明顯的體現 Mat lapulasi = (Mat_<int>(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0);//拉普拉斯 運算元 filter2D(src, dst5, -1, lapulasi, Point(-1, -1), 0.0); imshow("lapulasi", dst5); //影象銳化,僅僅只是將拉普拉斯運算元的中心點 由4改成5,卷積後的影象結果差距巨大。。 Mat ruihua = (Mat_<int>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);//銳化 運算元 (掩膜) filter2D(src, dst6, -1, ruihua, Point(-1, -1), 0.0); imshow("ruihua", dst6); customFilter(); waitKey(0); } void customFilter()//自定義線性濾波 { Mat src, dst; src = imread(getCVImagesPath("images/test1.png"), IMREAD_COLOR); int ksize = 0; int index = 0; while (true) { if (waitKey(500) == 27) break; // esc鍵 ksize = 4 + (index % 8) * 2 + 1; // Mat::ones 建立的矩陣值初始值為1 ,過載的運算子 / 表示將每個初始值再除以 ksize * ksize Mat kernel = Mat::ones(Size(ksize, ksize), CV_32F) / (float)(ksize * ksize); filter2D(src, dst, -1, kernel); index++; imshow("Custom Filter", dst); } }