opencv學習筆記8——形態學濾波
阿新 • • 發佈:2018-12-26
一、膨脹和腐蝕
二、開運算、閉運算、形態學梯度、頂帽、黑帽
示例程式碼:
#include<opencv2\core\core.hpp> #include<opencv2\highgui\highgui.hpp> #include<opencv2\imgproc\imgproc.hpp> #include<iostream> using namespace cv; using namespace std; Mat g_srcImage, g_dstImage; int g_nElementShape = MORPH_RECT; int g_nMaxIterationNum = 10; int g_nOpenCloseNum = 0; int g_nErodeDilateNum = 0; int g_nTopBlackHatNum = 0; static void on_OpenClose(int, void *) { int offset = g_nOpenCloseNum - g_nMaxIterationNum;//偏移量 int Absolute_offset = offset > 0 ? offset : -offset;//偏移量絕對值 Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset)); if (offset < 0) morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element); else morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element); imshow("<開/閉運算>", g_dstImage); } static void on_ErodeDilate(int, void *) { int offset = g_nOpenCloseNum - g_nMaxIterationNum;//偏移量 int Absolute_offset = offset > 0 ? offset : -offset;//偏移量絕對值 Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset)); if (offset < 0) erode(g_srcImage, g_dstImage,element); else dilate(g_srcImage, g_dstImage,element); imshow("<腐蝕/膨脹>", g_dstImage); } static void on_TopBlackHat(int, void*) { int offset = g_nTopBlackHatNum - g_nMaxIterationNum; int Absolute_offset = offset > 0 ? offset : -offset;//偏移量絕對值 Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset)); if (offset < 0) morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element); else morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element); imshow("<頂帽/黑帽>", g_dstImage); } int main() { g_srcImage = imread("lena.jpg"); if (!g_srcImage.data) { cout << "讀取圖片錯誤\n"; return false; } namedWindow("<原圖>"); imshow("<原圖>", g_srcImage); namedWindow("<開/閉運算>",1); namedWindow("<腐蝕/膨脹>", 1); namedWindow("<頂帽/黑帽>",1); g_nOpenCloseNum = 9; g_nErodeDilateNum = 9; g_nTopBlackHatNum = 2; createTrackbar("迭代值", "<開/閉運算>", &g_nOpenCloseNum, g_nMaxIterationNum * 2 + 1, on_OpenClose); createTrackbar("迭代值", "<腐蝕/膨脹>", &g_nOpenCloseNum, 2 * g_nMaxIterationNum + 1, on_ErodeDilate); createTrackbar("迭代值", "<頂帽/黑帽>", &g_nTopBlackHatNum, g_nMaxIterationNum * 2 + 1, on_TopBlackHat); while (1) { int c; on_OpenClose(g_nOpenCloseNum, 0); on_ErodeDilate(g_nErodeDilateNum, 0); on_TopBlackHat(g_nTopBlackHatNum, 0); c = waitKey(0); //按q或esc退出 if ((char)c == 'q' || (char)c == 27) break; //按1,橢圓 if ((char)c == 49) g_nElementShape = MORPH_ELLIPSE; //按2,矩形 if ((char)c == 50) g_nElementShape = MORPH_RECT; //按3,十字形 else if ((char)c == 51) g_nElementShape = MORPH_CROSS; //space鍵,在矩形、橢圓、十字之間迴圈 else if ((char)c == ' ') g_nElementShape = (g_nElementShape + 1) % 3; } return 0; }
效果:
理解:
後面的那些都是基於腐蝕和膨脹的。
開運算——先腐蝕再膨脹,消除細小物體,在纖細點處分離物體。
閉運算——先膨脹後腐蝕,排除小型黑洞。
形態學梯度——膨脹-腐蝕,將團塊的邊緣突出出來,保留物體邊緣輪廓。
頂帽——原圖-開運算,分離比臨近點亮的一些斑塊,在一幅影象具有大幅背景並且微小物品有規律,可以用這個進行背景提取。
黑帽——原圖-閉運算,分離比臨近點暗的一些斑塊,效果圖有很完美的輪廓。