OpenCV学习笔记(八):形态学morpholgy(2):开/闭运算,形态学梯度、顶帽/黑帽morphologyEx()
OpenCV學(xué)習(xí)筆記(八):形態(tài)學(xué)morpholgy(2):開(kāi)、閉運(yùn)算,形態(tài)學(xué)梯度、頂帽、黑帽:morphologyEx()
數(shù)學(xué)形態(tài)學(xué)(Mathematical morphology) 是一門(mén)建立在格論和拓?fù)鋵W(xué)基礎(chǔ)之上的圖像分析學(xué)科,是數(shù)學(xué)形態(tài)學(xué)圖像處理的基本理論。其基本的運(yùn)算包括:二值腐蝕和膨脹、二值開(kāi)閉運(yùn)算、骨架抽取、極限腐蝕、擊中擊不中變換、形態(tài)學(xué)梯度、Top-hat變換、顆粒分析、流域變換、灰值腐蝕和膨脹、灰值開(kāi)閉運(yùn)算、灰值形態(tài)學(xué)梯度等。
一、開(kāi)運(yùn)算(Opening Operation)
其實(shí)就是先腐蝕后膨脹的過(guò)程:
 
 開(kāi)運(yùn)算可以用來(lái)消除小物體、在纖細(xì)點(diǎn)處分離物體、平滑較大物體的邊界的同時(shí)并不明顯改變其面積。
二、閉運(yùn)算(Closing Operation)
先膨脹后腐蝕的過(guò)程:
 
 閉運(yùn)算能夠排除小型黑洞(黑色區(qū)域),可以將團(tuán)塊的邊緣突出出來(lái)。
三、形態(tài)學(xué)梯度(Morphological Gradient)
膨脹圖與腐蝕圖之差:
 
 對(duì)二值圖像進(jìn)行這一操作可以將團(tuán)塊(blob)的邊緣突出出來(lái)。我們可以用形態(tài)學(xué)梯度來(lái)保留物體的邊緣輪廓。
四、頂帽(Top Hat)
頂帽運(yùn)算(Top Hat)又常常被譯為”禮帽“運(yùn)算,源圖與“開(kāi)運(yùn)算圖“之差:
 
 因?yàn)殚_(kāi)運(yùn)算帶來(lái)的結(jié)果是放大了裂縫或者局部低亮度的區(qū)域,因此,從原圖中減去開(kāi)運(yùn)算后的圖,得到的效果圖突出了比原圖輪廓周?chē)膮^(qū)域更明亮的區(qū)域,所以頂帽運(yùn)算往往用來(lái)分離比鄰近點(diǎn)亮一些的斑塊。當(dāng)一幅圖像具有大幅的背景的時(shí)候,而微小物品比較有規(guī)律的情況下,可以使用頂帽運(yùn)算進(jìn)行背景提取。
五、黑帽(Black Hat)
為”閉運(yùn)算“的結(jié)果圖與原圖像之差:
 
 黑帽運(yùn)算后的效果圖突出了比原圖輪廓周?chē)膮^(qū)域更暗的區(qū)域,黑帽運(yùn)算用來(lái)分離比鄰近點(diǎn)暗一些的斑塊。
六、morphologyEx函數(shù)詳解:
C++: void morphologyEx( InputArray src, OutputArray dst, int op, InputArraykernel, Pointanchor=Point(-1,-1), intiterations=1, intborderType=BORDER_CONSTANT, constScalar& borderValue=morphologyDefaultBorderValue() );第一個(gè)參數(shù),InputArray類(lèi)型的src,輸入圖像,即源圖像,(CV_8U, CV_16U,CV_16S, CV_32F 或CV_64F)。
 第二個(gè)參數(shù),OutputArray類(lèi)型的dst,即目標(biāo)圖像。
 第三個(gè)參數(shù),int類(lèi)型的op,表示形態(tài)學(xué)運(yùn)算的類(lèi)型:
第五個(gè)參數(shù),Point類(lèi)型的anchor,錨的位置,其有默認(rèn)值(-1,-1),表示錨位于中心。
 第六個(gè)參數(shù),int類(lèi)型的iterations,迭代使用函數(shù)的次數(shù),默認(rèn)值為1。
 第七個(gè)參數(shù),int類(lèi)型的borderType,用于推斷圖像外部像素的某種邊界模式。注意它有默認(rèn)值BORDER_ CONSTANT。
 第八個(gè)參數(shù),const Scalar&類(lèi)型的borderValue,當(dāng)邊界為常數(shù)時(shí)的邊界值,有默認(rèn)值morphologyDefaultBorderValue(),一般我們不用去管他。需要用到它時(shí),可以看官方文檔中的createMorphologyFilter()函數(shù)得到更詳細(xì)的解釋。
getStructuringElement函數(shù)相關(guān)的調(diào)用示例代碼如下
//結(jié)構(gòu)元素(內(nèi)核矩陣)的尺寸 int g_nStructElementSize = 3;//獲取自定義核 Mat element =getStructuringElement(MORPH_RECT,Size(2*g_nStructElementSize+1,2*g_nStructElementSize+1),Point(g_nStructElementSize, g_nStructElementSize ));第一個(gè)參數(shù)表示內(nèi)核的形狀,我們可以選擇如下三種形狀之一
矩形: MORPH_RECT 交叉形: MORPH_CROSS 橢圓形: MORPH_ELLIPSE第二和第三個(gè)參數(shù)分別是內(nèi)核的尺寸以及錨點(diǎn)的位置,對(duì)于錨點(diǎn)的位置,有默認(rèn)值Point(-1,-1),表示錨點(diǎn)位于中心
六、示例代碼:
#include <opencv2/opencv.hpp>using namespace cv; using namespace std;Mat g_srcImage, g_dstImage; //原始圖和效果圖 int g_nElementShape = MORPH_RECT; //元素結(jié)構(gòu)的形狀//變量接收的TrackBar位置參數(shù) int g_nMaxIterationNum = 10; // 最大方向值 int g_nOpenCloseNum = 0; // 開(kāi)閉/運(yùn)算內(nèi)核值 int g_nTopBlackHatNum = 0; // 頂帽/黑帽內(nèi)核值int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 1、載入原圖g_srcImage = imread("F:/C++/2. OPENCV 3.1.0/TEST/綜合.png");if( !g_srcImage.data ) { printf("Oh,no,讀取srcImage錯(cuò)誤~! \n"); return false; }// 2、顯示原始圖namedWindow("【原始圖】");imshow("【原始圖】", g_srcImage);// 3、創(chuàng)建窗口namedWindow("【開(kāi)運(yùn)算/閉運(yùn)算】",1);namedWindow("【頂帽/黑帽】",1);// 4、參數(shù)賦值g_nOpenCloseNum=9;g_nTopBlackHatNum=10;// 5、分別為二個(gè)窗口創(chuàng)建滾動(dòng)條createTrackbar("迭代值", "【開(kāi)運(yùn)算/閉運(yùn)算】",&g_nOpenCloseNum,g_nMaxIterationNum*2+1,on_OpenClose);createTrackbar("迭代值", "【頂帽/黑帽】",&g_nTopBlackHatNum,g_nMaxIterationNum*2+1,on_TopBlackHat);// 6、輪詢獲取按鍵信息while(1){//執(zhí)行回調(diào)函數(shù)on_OpenClose(g_nOpenCloseNum, 0);on_TopBlackHat(g_nTopBlackHatNum,0);//獲取按鍵int c = waitKey(0);//按下鍵盤(pán)按鍵Q或者ESC,程序退出if( (char)c == 'q'||(char)c == 27 )break;//按下鍵盤(pán)按鍵1,使用橢圓(Elliptic)結(jié)構(gòu)元素結(jié)構(gòu)元素MORPH_ELLIPSEif( (char)c == 49 )//鍵盤(pán)按鍵1的ASII碼為49g_nElementShape = MORPH_ELLIPSE;//按下鍵盤(pán)按鍵2,使用矩形(Rectangle)結(jié)構(gòu)元素MORPH_RECTelse if( (char)c == 50 )//鍵盤(pán)按鍵2的ASII碼為50g_nElementShape = MORPH_RECT;//按下鍵盤(pán)按鍵3,使用十字形(Cross-shaped)結(jié)構(gòu)元素MORPH_CROSSelse if( (char)c == 51 )//鍵盤(pán)按鍵3的ASII碼為51g_nElementShape = MORPH_CROSS;//按下鍵盤(pán)按鍵space,在矩形、橢圓、十字形結(jié)構(gòu)元素中循環(huán)else if( (char)c == ' ' )g_nElementShape = (g_nElementShape + 1) % 3;}return a.exec(); }1)開(kāi)運(yùn)算/閉運(yùn)算 回調(diào)函數(shù)
static void on_OpenClose(int, void*) {//偏移量的定義int offset = g_nOpenCloseNum - g_nMaxIterationNum; //偏移量int Absolute_offset = offset > 0 ? offset : -offset;//偏移量絕對(duì)值//自定義核Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset*2+1, Absolute_offset*2+1), Point(Absolute_offset, Absolute_offset) );//進(jìn)行操作if( offset < 0 )// 偏移量小于0 時(shí),開(kāi)運(yùn)算morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);else if (offset == 0)g_srcImage.copyTo(g_dstImage);else// 偏移量大于0 時(shí),閉運(yùn)算morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);//顯示圖像imshow("【開(kāi)運(yùn)算/閉運(yùn)算】",g_dstImage); }2)頂帽運(yùn)算/黑帽運(yùn)算 回調(diào)函數(shù)
static void on_TopBlackHat(int, void*) {//偏移量的定義int offset = g_nTopBlackHatNum - g_nMaxIterationNum;//偏移量int Absolute_offset = offset > 0 ? offset : -offset;//偏移量絕對(duì)值//自定義核Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset*2+1, Absolute_offset*2+1), Point(-1, -1) );//進(jìn)行操作if( offset < 0 )morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT , element);else if (offset == 0)g_srcImage.copyTo(g_dstImage);elsemorphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);//顯示圖像imshow("【頂帽/黑帽】",g_dstImage); }結(jié)果:
 MORPH_ELLIPSE
 
 
 MORPH_RECT
 
 
 MORPH_CROSS
 
 
總結(jié)
以上是生活随笔為你收集整理的OpenCV学习笔记(八):形态学morpholgy(2):开/闭运算,形态学梯度、顶帽/黑帽morphologyEx()的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: pytorch查看模型的可训练参数
- 下一篇: QT学习笔记(三):Qt软件打包发布(Q
