openCV學習筆記(二十三) —— 形態學濾波—— 開運算、閉運算、形態學梯度、頂帽、黑帽
阿新 • • 發佈:2019-02-13
原理
程式
#include<opencv2/opencv.hpp> using namespace std; using namespace cv; /* 巨集定義 */ #define ORIGINAL_WINDOW_NAME "【原始圖】" #define OPEN_CLOSE_WINDOW_NAME "【開運算/閉運算】" #define ERODE_DILATE_WINDOW_NAME "【腐蝕/膨脹】" #define TOP_BLACK_HAT_WINDOW_NAME "【頂帽/黑帽】" #define GRADIENT_WINDOW_NAME "形態學梯度" /* 全域性變數宣告 */ Mat g_srcImage, g_dstImage; //原始圖和效果圖 int g_nElementShape = MORPH_RECT; //元素結構的形狀 //變數接收的TrackBar位置引數 int g_nMaxIteratorNum = 10; int g_nOpenCloseNum = 0; int g_nErodeDilateNum = 0; int g_nTopBlackHatNum = 0; int g_nGradientNum = 0; /* 全域性函式宣告 */ static void onOpenClose(int, void *); static void onErodeDilate(int, void *); static void onTopBlackHat(int, void *); static void onGradient(int, void *); /* main()函式 */ int main() { //載入原圖 g_srcImage = imread("test.jpg"); if (!g_srcImage.data) { printf("讀取srcImage錯誤!\n"); return -1; } //顯示原始圖 namedWindow(ORIGINAL_WINDOW_NAME); imshow(ORIGINAL_WINDOW_NAME, g_srcImage); //建立四個視窗 namedWindow(OPEN_CLOSE_WINDOW_NAME); namedWindow(ERODE_DILATE_WINDOW_NAME); namedWindow(TOP_BLACK_HAT_WINDOW_NAME); namedWindow(GRADIENT_WINDOW_NAME); //引數賦值 g_nOpenCloseNum = 9; g_nErodeDilateNum = 9; g_nTopBlackHatNum = 2; g_nGradientNum = 9; //分別為四個視窗建立滾動條 createTrackbar("迭代值", OPEN_CLOSE_WINDOW_NAME, &g_nOpenCloseNum, g_nMaxIteratorNum * 2 + 1, onOpenClose); createTrackbar("迭代值", ERODE_DILATE_WINDOW_NAME, &g_nErodeDilateNum, g_nMaxIteratorNum * 2 + 1, onErodeDilate); createTrackbar("迭代值", TOP_BLACK_HAT_WINDOW_NAME, &g_nTopBlackHatNum, g_nMaxIteratorNum * 2 + 1, onTopBlackHat); createTrackbar("迭代值", GRADIENT_WINDOW_NAME, &g_nGradientNum, g_nMaxIteratorNum * 2 + 1, onGradient); //輪詢獲取按鍵資訊 while (true) { int c; //執行回撥函式 onOpenClose(g_nOpenCloseNum, NULL); onErodeDilate(g_nErodeDilateNum, NULL); onTopBlackHat(g_nTopBlackHatNum, NULL); //獲取按鍵 c = waitKey(0); //按下鍵盤按鍵Q或者ESC, 程式退出 if ((char)c == 'q' || (char)c == 27) { break; } //按下鍵盤按鍵1,使用橢圓(Ellipse)結構元素MORPH_ELLIPSE if ((char)c == 49) //鍵盤按鍵1的ASCII碼為49 { printf("使用橢圓結構元素"); g_nElementShape = MORPH_ELLIPSE; } //按下鍵盤按鍵2,使用矩形(Rectangle)結構元素MORPH_RECT else if ((char)c == 50) //鍵盤按鍵2的ASCII碼為50 { printf("使用矩形結構元素"); g_nElementShape = MORPH_RECT; } //按下鍵盤按鍵3,使用十字形(Cross-shaped)結構元素MORPH_RECT else if ((char)c == 51) //鍵盤按鍵3的ASCII碼為50 { printf("使用十字形結構元素"); g_nElementShape = MORPH_CROSS; } //按下鍵盤空格,在矩形、橢圓、十字形結構元素中迴圈 else if ((char)c == ' ') { printf("在矩形、橢圓、十字形結構元素中迴圈"); g_nElementShape = (g_nElementShape + 1) % 3; } } destroyAllWindows(); return 0; } /* 開運算/閉運算視窗的回撥函式 */ static void onOpenClose(int, void *) { //偏移量的定義 int offset = g_nOpenCloseNum - g_nMaxIteratorNum; //偏移量 int AbsoluteOffset = offset > 0 ? offset : -offset; //偏移量絕對值 //自定義核 Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset * 2 + 1, AbsoluteOffset * 2 + 1), Point(AbsoluteOffset, AbsoluteOffset)); //進行操作 if (offset < 0) { printf("開運算...\n"); morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element); } else { printf("閉運算...\n"); morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element); } imshow(OPEN_CLOSE_WINDOW_NAME, g_dstImage); } /* 腐蝕/膨脹視窗的回撥函式 */ static void onErodeDilate(int, void *) { //偏移量的定義 int offset = g_nErodeDilateNum - g_nMaxIteratorNum; //偏移量 int AbsoluteOffset = offset > 0 ? offset : -offset; //偏移量絕對值 //自定義核 Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset * 2 + 1, AbsoluteOffset * 2 + 1), Point(AbsoluteOffset, AbsoluteOffset)); //進行操作 if (offset < 0) { printf("腐蝕運算...\n"); erode(g_srcImage, g_dstImage, element); } else { printf("膨脹運算...\n"); dilate(g_srcImage, g_dstImage, element); } imshow(ERODE_DILATE_WINDOW_NAME, g_dstImage); } /* 頂帽/黑帽視窗的回撥函式 */ static void onTopBlackHat(int, void *) { //偏移量的定義 int offset = g_nTopBlackHatNum - g_nMaxIteratorNum; //偏移量 int AbsoluteOffset = offset > 0 ? offset : -offset; //偏移量絕對值 //自定義核 Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset * 2 + 1, AbsoluteOffset * 2 + 1), Point(AbsoluteOffset, AbsoluteOffset)); //進行操作 if (offset < 0) { printf("頂帽運算...\n"); morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element); } else { printf("黑帽運算...\n"); morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element); } imshow(TOP_BLACK_HAT_WINDOW_NAME, g_dstImage); } /* 形態學梯度視窗的回撥函式 */ static void onGradient(int, void *) { //偏移量的定義 int offset = g_nGradientNum - g_nMaxIteratorNum; //偏移量 int AbsoluteOffset = offset > 0 ? offset : -offset; //偏移量絕對值 //自定義核 Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset * 2 + 1, AbsoluteOffset * 2 + 1), Point(AbsoluteOffset, AbsoluteOffset)); //進行操作 printf("形態學梯度運算...\n"); morphologyEx(g_srcImage, g_dstImage, MORPH_GRADIENT, element); imshow(GRADIENT_WINDOW_NAME, g_dstImage); }