1. 程式人生 > >形態學影象處理:開運算、閉運算、形態學梯度、頂帽、黑帽合輯

形態學影象處理:開運算、閉運算、形態學梯度、頂帽、黑帽合輯

說明

開運算:先腐蝕後膨脹的過程,可以用來消除小物體、在纖細點處分離物體、平滑較大物體的邊界的同時並不明顯改變其面積。
閉運算:先膨脹後腐蝕的過程,能夠排除小型黑洞(黑色區域)。
形態學梯度:膨脹圖與腐蝕圖之差,對二值影象進行這一操作可以將團塊(blob)的邊緣突出出來。可以用形態學梯度來保留物體的邊緣輪廓。
頂帽:為原影象開運算的結果圖之差,放大了裂縫或者區域性低亮度的區域,突出了比原圖輪廓周圍的區域更明亮的區域,且這一操作和選擇的核的大小相關。頂帽運算往往用來分離比鄰近點亮一些的斑塊。當一幅影象具有大幅的背景的時候,而微小物品比較有規律的情況下,可以使用頂帽運算進行背景提取。
黑帽

:為閉運算的結果圖與原影象之差。黑帽運算後的效果圖突出了比原圖輪廓周圍的區域更暗的區域,且這一操作和選擇的核的大小相關。所以,黑帽運算用來分離比鄰近點暗一些的斑塊。

示例

//-----------------------------------【標頭檔案包含部分】---------------------------------------
//		描述:包含程式所依賴的標頭檔案
//---------------------------------------------------------------------------------------------- 
#include "pch.h"
#include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> //-----------------------------------【名稱空間宣告部分】-------------------------------------- // 描述:包含程式所使用的名稱空間 //-----------------------------------------------------------------------------------------------
using namespace std; using namespace cv; //-----------------------------------【全域性變數宣告部分】-------------------------------------- // 描述:全域性變數宣告 //----------------------------------------------------------------------------------------------- Mat g_srcImage, g_dstImage;//原始圖和效果圖 int g_nElementShape = MORPH_RECT;//元素結構的形狀 //變數接收的TrackBar位置引數 int g_nMaxIterationNum = 10; int g_nOpenCloseNum = 0; int g_nErodeDilateNum = 0; int g_nTopBlackHatNum = 0; //-----------------------------------【全域性函式宣告部分】-------------------------------------- // 描述:全域性函式宣告 //----------------------------------------------------------------------------------------------- static void on_OpenClose(int, void*);//回撥函式 static void on_ErodeDilate(int, void*);//回撥函式 static void on_TopBlackHat(int, void*);//回撥函式 static void ShowHelpText();//幫助文字顯示 //-----------------------------------【main( )函式】-------------------------------------------- // 描述:控制檯應用程式的入口函式,我們的程式從這裡開始 //----------------------------------------------------------------------------------------------- int main() { //改變console字型顏色 system("color 2F"); ShowHelpText(); //載入原圖 g_srcImage = imread("1.jpg");//工程目錄下需要有一張名為1.jpg的素材圖 if (!g_srcImage.data) { printf("Oh,no,讀取srcImage錯誤~! \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_nErodeDilateNum, g_nMaxIterationNum * 2 + 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,使用橢圓(Elliptic)結構元素結構元素MORPH_ELLIPSE if ((char)c == 49)//鍵盤按鍵1的ASII碼為49 g_nElementShape = MORPH_ELLIPSE; //按下鍵盤按鍵2,使用矩形(Rectangle)結構元素MORPH_RECT else if ((char)c == 50)//鍵盤按鍵2的ASII碼為50 g_nElementShape = MORPH_RECT; //按下鍵盤按鍵3,使用十字形(Cross-shaped)結構元素MORPH_CROSS else if ((char)c == 51)//鍵盤按鍵3的ASII碼為51 g_nElementShape = MORPH_CROSS; //按下鍵盤按鍵space,在矩形、橢圓、十字形結構元素中迴圈 else if ((char)c == ' ') g_nElementShape = (g_nElementShape + 1) % 3; } return 0; } //-----------------------------------【on_OpenClose( )函式】---------------------------------- // 描述:【開運算/閉運算】視窗的回撥函式 //----------------------------------------------------------------------------------------------- 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, CV_MOP_OPEN, element); else morphologyEx(g_srcImage, g_dstImage, CV_MOP_CLOSE, element); //顯示影象 imshow("【開運算/閉運算】", g_dstImage); } //-----------------------------------【on_ErodeDilate( )函式】---------------------------------- // 描述:【腐蝕/膨脹】視窗的回撥函式 //----------------------------------------------------------------------------------------------- static void on_ErodeDilate(int, void*) { //偏移量的定義 int offset = g_nErodeDilateNum - 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); } //-----------------------------------【on_TopBlackHat( )函式】-------------------------------- // 描述:【頂帽運算/黑帽運算】視窗的回撥函式 //---------------------------------------------------------------------------------------------- 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); } //-----------------------------------【ShowHelpText( )函式】---------------------------------- // 描述:輸出一些幫助資訊 //---------------------------------------------------------------------------------------------- static void ShowHelpText() { //輸出一些幫助資訊 printf("\n\n\n\t請調整滾動條觀察影象效果~\n\n"); printf("\n\n\t按鍵操作說明: \n\n" "\t\t鍵盤按鍵【ESC】或者【Q】- 退出程式\n" "\t\t鍵盤按鍵【1】- 使用橢圓(Elliptic)結構元素\n" "\t\t鍵盤按鍵【2】- 使用矩形(Rectangle )結構元素\n" "\t\t鍵盤按鍵【3】- 使用十字型(Cross-shaped)結構元素\n" "\t\t鍵盤按鍵【空格SPACE】- 在矩形、橢圓、十字形結構元素中迴圈\n" ); }

結果

morphologyEx