《OpenCV3编程入门》学习笔记6 图像处理(四)形态学滤波(2):开运算、闭运算、形态学梯度、顶帽、黑帽
6.4 形態學濾波(2):開運算、閉運算、形態學梯度、頂帽、黑帽
高級形態學變換,基于腐蝕與膨脹,利用morphologyEx函數實現
6.4.1 開運算
1.腐蝕后膨脹的過程,數學表達式:dst=open(src,element)=dilate(erode(src,element))
2.作用:消除小物體,在纖細點處分離物體,并且在平滑較大物體的邊界的同時不明顯改變其面積
6.4.2 閉運算
1.膨脹后腐蝕的過程,數學表達式:dst=close(src,element)=erode(dilate(src,element))
2.作用:排除小型黑洞
6.4.3 形態學梯度
1.膨脹圖與腐蝕圖之差,數學表達式:dst=morph-grad(src,element)=dilate(src,element)-erode(src,element)
2.作用:將團塊的邊緣突出,保留物體邊緣輪廓
6.4.4 頂帽(Top Hat)
1.原圖像與開運算結果之差,數學表達式:dst=tophat(src,element)=src-open(src,element)
2.作用:開運算放大了裂縫或局部低亮度區域,所以頂帽突出了比原圖輪廓周圍區域更明亮的區域,用來分離比臨近點亮一些的區域,在一幅大背景物品微小有規律的圖像中,可以進行背景提取
6.4.5 黑帽(Black Hat)
1.閉運算結果與原圖之差,數學表達式:dst=blackhhat(src,element)=close(src,element)-src
2.作用:黑帽突出了比原圖輪廓周圍區域更暗的區域,用來分離比臨近點暗一些的區域,效果圖有非常完美的輪廓
6.4.6 OpenCV源碼核心API函數:morphologyEx()
1.函數原型:
void morphologyEx(InputArray src,OutputArray dst,int op,InputArraykernel,Pointanchor=Point(-1,-1),intiterations=1,intborderType=BORDER_CONSTANT,constScalar& borderValue=morphologyDefaultBorderValue() );
2.參數說明:
(1)輸入圖像
(2)目標圖像
(3)形態學運算類型
(4)形態學運算內核,getStructuringElement函數配合使用
(5)錨的位置,默認(-1,-1)表示中心
(6)迭代使用函數次數,默認1
(7)用于推斷圖像外部像素的某種邊界模式,默認BORDER_CONSTANT
(8)當邊界為常數時的邊界值,默認值morphologyDefaultValue()
6.4.7 綜合示例
/* 效果:4個顯示窗口,原始圖,開/閉運算,腐蝕/膨脹,頂帽/黑帽滾動條控制形態學效果,迭代值為10的時候為中間點通過按鍵1、2、3及空格調節成不同的元素結構(矩形、橢圓、十字形)
*/
#include<opencv2/opencv.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;//元素結構形狀
//變量接收的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();int main()
{//改變console顏色system("color 3B");//顯示提示信息ShowHelpText();//載入原圖g_srcImage = imread("love.jpg");if (!g_srcImage.data){printf("載入原圖像失敗~!\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,使用橢圓結構元素MORPH_ELLIPSEif ((char)c == 49)//鍵盤1的ASII碼為49g_nElementShape = MORPH_ELLIPSE;//按下鍵盤按鍵2,使用矩形結構元素MORPH_RECTelse if ((char)c == 50)//鍵盤2的ASII碼為50g_nElementShape = MORPH_RECT;//按下鍵盤按鍵3,使用十字形結構元素MORPH_CROSSelse if ((char)c == 51)//鍵盤3的ASII碼為51g_nElementShape = MORPH_CROSS;//按下鍵盤按鍵space,在矩形、橢圓、十字形結構元素中循環else if ((char)c == ' ')g_nElementShape = (g_nElementShape + 1) % 3;}return 0;
}
//【開運算/閉運算】窗口回調函數
static void on_OpenClose(int, void*)
{//偏移量定義(滑動條以g_nMaxIterationNum點為原點,計算偏移量(<0)絕對值為開運算度,偏移量(>0)絕對值為閉運算度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) //g_nOpenCloseNum=0~9morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);else //g_OpenCloseNum=10~21morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);//顯示圖像imshow("【開運算/閉運算】", g_dstImage);
}
//【腐蝕/膨脹】窗口回調函數
static void on_ErodeDilate(int, void*)
{//偏移量定義(滑動條以g_nMaxIterationNum點為原點,計算偏移量(<0)絕對值為腐蝕度,偏移量(>0)絕對值為膨脹度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) //g_nErodeDilateNum=0~9erode(g_srcImage, g_dstImage, element);else //g_nErodeDilateNum=10~21dilate(g_srcImage, g_dstImage, element);//顯示圖像imshow("【腐蝕/膨脹】", g_dstImage);
}
//【頂帽運算/黑帽運算】窗口回調函數
static void on_TopBlackHat(int, void*)
{//偏移量定義(滑動條以g_nMaxIterationNum點為原點,計算偏移量(<0)絕對值為頂帽度,偏移量(>0)絕對值為黑帽度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) //g_nTopBlackHatNum=0~9morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);else //g_nTopBlackHatNum=10~21morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);//顯示圖像imshow("【頂帽/黑帽】", g_dstImage);
}
static void ShowHelpText()
{printf("--------------------------------------------------------------------\n");printf("請調整滑動條觀察圖像效果\n");printf("按鍵操作說明:\n");printf("\t\t鍵盤按鍵[ESC]或[Q]-退出程序\n");printf("\t\t鍵盤按鍵[1]-使用橢圓結構元素\n");printf("\t\t鍵盤按鍵[2]-使用矩形結構元素\n");printf("\t\t鍵盤按鍵[3]-使用十字形結構元素\n");printf("\t\t鍵盤按鍵[space]-在巨型、橢圓、十字形結構元素中循環\n");printf("--------------------------------------------------------------------\n");
}
運行效果:
??
??
?
總結
以上是生活随笔為你收集整理的《OpenCV3编程入门》学习笔记6 图像处理(四)形态学滤波(2):开运算、闭运算、形态学梯度、顶帽、黑帽的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《OpenCV3编程入门》学习笔记6 图
- 下一篇: Python学习笔记2 基本数据类型