形態學操作——開閉運算、頂帽底(黑)帽變換

膨脹和腐蝕運算的問題:

邊緣形狀發生了變化,膨脹發生了擴張,腐蝕發生了收縮
目標物體變形,對識別時的特征提取會造成影響

解決方法:

開操作:

gongshi
B對A的開操作就是先B對A腐蝕,緊接著用B對結果進行膨脹
效果
先腐蝕再膨脹的結果并不是恢復原狀,而是會消除黏連部分,同時不影響其他部分的形狀.
平滑物體的輪廓,斷開較窄的狹頸并消除較細的突出。
效果:
效果

閉操作:

公式
B對A的閉操作就是先B對A膨脹,緊接著用B對結果進行腐蝕
效果
先膨脹再腐蝕的結果并不是恢復原狀,而是填充小的裂縫、孔隙,且不影響形狀.
平滑物體的輪廓,彌合較窄的間斷和細小的溝壑,消除小的孔洞,填充輪廓中的斷痕。
效果:
效果
更加詳細的過程如下:
詳細過程
除了開閉運算,黑帽頂帽運算也是形態學操作比較重要的操作。

頂帽變換:原圖-灰度開運算(灰度腐蝕+灰度膨脹)

效果:
1、保留比結構元素小的部分
2、保留比周圍環境亮的像素

底帽變換:灰度閉運算(灰度膨脹+灰度腐蝕)-原圖 效果:

1、保留比結構元素小的部分
2、保留比周圍環境暗的像素

解釋:
頂帽處理使背景變得趨于一致了,前景和背景的對比度加深了
這是因為,在頂帽處理中當結構元素比前景目標物的大小
大的時候,腐蝕的步驟會選擇周圍比較暗的值代替比較亮的值
所以背景變暗了,同時前景被去掉了。再用原圖和結果相減,就可以把背景去掉,把開運算中去掉的前景給保留下來
1
2

代碼實現

#include <opencv2/opencv.hpp>
#include <iostream>
#include "windows.h"
#include <stdio.h>using namespace cv;
using namespace std;//*--------------------------【練習】形態學操作morphology大練習------------------------------------*/
//請調整滾動條觀察圖像效果
//按鍵操作說明 :
//鍵盤按鍵【空格SPACE】- 在矩形、橢圓、十字形結構元素中循環
//鍵盤按鍵【1】- 使用橢圓結構元素
//鍵盤按鍵【2】- 使用矩形結構元素
//鍵盤按鍵【3】- 使用十字形結構元素
Mat g_secImage, g_dstImage;	//原圖和效果圖
int g_nElementShape = MORPH_RECT;	//初始化元素結構形狀//變量接受的Trackbar值
int  g_nMaxIterationMun = 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_TopBlakHat(int, void*);		//回調函數
void ShowHelpText1();
void ShowHelpText2();
int main()
{SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);		//字體為綠色//載入原圖g_secImage = imread("D:\\opencv_picture_test\\形態學操作\\黑白.jpg");//判斷圖像是否加載成功if (g_secImage.empty()){cout << "圖像加載失敗!" << endl;return -1;}elsecout << "圖像加載成功!" << endl << endl;//顯示原圖像namedWindow("原圖像", WINDOW_NORMAL);     //定義窗口顯示屬性imshow("原圖像", g_secImage);//創建三個窗口namedWindow("【開運算/閉運算】", WINDOW_NORMAL);    namedWindow("【腐蝕/膨脹】", WINDOW_NORMAL);namedWindow("【頂帽/黑帽】", WINDOW_NORMAL);//參數賦值g_nOpenCloseNum = 9;g_nErodeDilateNum =9;g_nTopBlackHatNum =2;//分別為三個窗口建立滑動條createTrackbar("迭代值", "【開運算/閉運算】", &g_nOpenCloseNum, g_nMaxIterationMun*2+1,on_OpenClose);createTrackbar("迭代值", "【腐蝕/膨脹】", &g_nErodeDilateNum, g_nMaxIterationMun * 2 + 1, on_ErodeDilate);createTrackbar("迭代值", "【頂帽/黑帽】", &g_nTopBlackHatNum, g_nMaxIterationMun * 2 + 1, on_TopBlakHat);//show幫助信息ShowHelpText1();//輪詢獲取按鍵信息while (1){int c;//執行回調函數on_OpenClose(g_nOpenCloseNum,0);on_ErodeDilate(g_nErodeDilateNum,0);on_TopBlakHat(g_nTopBlackHatNum,0);//獲取按鍵c = waitKey(0);//按下按鍵ESC程序退出if ((char)c == 27){break;}//按鍵1,使用橢圓結構元素if ((char)c == 49){g_nElementShape = MORPH_ELLIPSE;}//按鍵2,使用矩形結構元素else if ((char)c == 50){g_nElementShape = MORPH_RECT;}//按鍵3,使用十字形結構元素else if ((char)c == 51){g_nElementShape = MORPH_CROSS;}//按鍵空格,換一種結構元素else if ((char)c == ' '){g_nElementShape = (g_nElementShape+1)%3;}}
}
//*--------------------------【回調函數】-----------------------------------*/static void on_OpenClose(int, void*)
{//偏移量定義int offset = g_nOpenCloseNum - g_nMaxIterationMun;	//偏移量int Abs_offset = offset > 0 ? offset : -offset;	//偏移量的絕對值//自定義核Mat element = getStructuringElement(g_nElementShape,Size(Abs_offset*2+1, Abs_offset*2+1),Point(Abs_offset, Abs_offset));	//返回的是內核矩陣//進行操作if (offset < 0){morphologyEx(g_secImage, g_dstImage, MORPH_OPEN, element);}else{morphologyEx(g_secImage, g_dstImage, MORPH_CLOSE, element);}//顯示效果圖imshow("【開運算/閉運算】", g_dstImage);
}
static void on_ErodeDilate(int, void*)
{//偏移量定義int offset = g_nErodeDilateNum - g_nMaxIterationMun;	//偏移量int Abs_offset = offset > 0 ? offset : -offset;	//偏移量的絕對值//自定義核Mat element = getStructuringElement(g_nElementShape, Size(Abs_offset * 2 + 1, Abs_offset * 2 + 1), Point(Abs_offset, Abs_offset));	//返回的是內核矩陣//進行操作if (offset < 0){morphologyEx(g_secImage, g_dstImage, MORPH_ERODE, element);}else{morphologyEx(g_secImage, g_dstImage, MORPH_DILATE, element);}//顯示效果圖imshow("【腐蝕/膨脹】", g_dstImage);
}
static void on_TopBlakHat(int, void*)
{//偏移量定義int offset = g_nTopBlackHatNum - g_nMaxIterationMun;	//偏移量int Abs_offset = offset > 0 ? offset : -offset;	//偏移量的絕對值//自定義核Mat element = getStructuringElement(g_nElementShape, Size(Abs_offset * 2 + 1, Abs_offset * 2 + 1), Point(Abs_offset, Abs_offset));	//返回的是內核矩陣//進行操作if (offset < 0){morphologyEx(g_secImage, g_dstImage, MORPH_TOPHAT, element);}else{morphologyEx(g_secImage, g_dstImage, MORPH_BLACKHAT, element);}//顯示效果圖imshow("【頂帽/黑帽】", g_dstImage);
}//-----------------------------------【ShowHelpText( )函數】-----------------------------
//          描述:輸出一些幫助信息//關于morphologyEx參數的問題://MORPH_BLACKHAT:黑帽運算//MORPH_TOPHAT:頂帽運算//MORPH_CLOSE:閉運算//MORPH_OPEN:開運算//MORPH_GRADIENT:形態學梯度//MORPH_ERODE:腐蝕運算//MORPH_DILATE:膨脹運算//關于getStructuringElement參數的問題://MORPH_RECT:矩形內核//MORPH_CROSS:交叉型內核//MORPH_ELLIPSE:橢圓形矩陣
//請調整滾動條觀察圖像效果
//按鍵操作說明 :
//鍵盤按鍵【空格SPACE】- 在矩形、橢圓、十字形結構元素中循環
//鍵盤按鍵【1】- 使用橢圓結構元素
//鍵盤按鍵【2】- 使用矩形結構元素
//鍵盤按鍵【3】- 使用十字形結構元素
//----------------------------------------------------------------------------------------------
void ShowHelpText1()
{//輸出一些幫助信息printf("\n\n\n請調整滾動條觀察圖像效果\n");printf("\n\n\t按鍵操作說明\n");printf("\n\n\t鍵盤按鍵【空格SPACE】- 在矩形、橢圓、十字形結構元素中循環\n");printf("\n\n\t鍵盤按鍵【1】- 使用橢圓結構元素\n");printf("\n\n\t鍵盤按鍵【2】- 使用矩形結構元素\n");printf("\n\n\t鍵盤按鍵【3】- 使用十字形結構元素\n");
}
void ShowHelpText2()
{//輸出一些幫助信息printf("\n\n\n\morphologyEx 參數有以下幾種類型\n");printf("\n\n\tMORPH_BLACKHAT:黑帽運算\n");printf("\n\n\tMORPH_TOPHAT:頂帽運算\n");printf("\n\n\tMORPH_CLOSE:閉運算\n");printf("\n\n\tMORPH_OPEN:開運算\n");printf("\n\n\t//MORPH_GRADIENT:形態學梯度\n");printf("\n\n\tMORPH_ERODE:腐蝕運算\n");printf("\n\n\tMORPH_DILATE:膨脹運算\n");printf("\n\n\n\getStructuringElement參數的問題:\n");printf("\n\n\tMORPH_RECT:矩形內核\n");printf("\n\n\tMORPH_CROSS:交叉型內核\n");printf("\n\n\tMORPH_ELLIPSE:橢圓形矩陣\n");
}

代碼實現效果:
321

代碼解釋

調用opencv庫函數morphologyEx,通過調整參數就可以實現不同的形態學操作。
其中回調函數中要求得變量:偏移量(當前迭代值和預置最大迭代值之差),用它的正負來判斷是進行哪種對偶操作。用它的絕對值來決定矩陣核的大小(邊長為奇數),以及結構元素錨點的位置。
另外需要注意:十字形的element形狀唯一依賴于錨點的位置。
而在其他情況下,錨點只是影響形態學運算結果的偏移。

相關鏈接:[https://www.cnblogs.com/zsb517/archive/2012/06/08/2541193.html(https://www.cnblogs.com/zsb517/archive/2012/06/08/2541193.html)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/378727.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/378727.shtml
英文地址,請注明出處:http://en.pswp.cn/news/378727.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java 基礎實戰_Java基礎實戰(三)

是否是否是否是否獲取字符串字符數組大寫?小寫?數字?非字母與數字大寫字母小寫字母數字i結束ii1第一步 拆分字符串為字符數組&#xff1a;static void count(String str) {// 將字符串拆分為字符數組char[] charArray str.toCharArray();}第二步 定義相關變量記錄結果&…

11-圖像梯度-Sobel算子

圖像梯度是指圖像某像素在x和y兩個方向上的變化率&#xff08;與相鄰像素比較&#xff09;&#xff0c;是一個二維向量&#xff0c;由2個分量組成&#xff0c;X軸的變化、Y軸的變化 。 其中X軸的變化是指當前像素右側&#xff08;X加1&#xff09;的像素值減去當前像素左側&…

給IE有效指定編碼

<title>下一站</title> <meta http-equiv"Content-Type" content"text/html; charsetutf-8" /> IE每次打開&#xff0c;均是一片空白&#xff0c;查看右鍵&#xff0d;編碼&#xff0c;顯示是GB2312。要手功改為UTF-8后才能正常顯示頁面…

形態學操作——擊中擊不中變換

操作目的 HitMiss變換是形態檢測的一個工具&#xff0c;通過定義形狀模板可以在圖像中獲取同一形狀物體的位置坐標。 算法講解 1、用擊中結構去腐蝕原始圖像得到擊中結果X&#xff08;這個過程可以理解為在原始圖像中尋找和擊中結構完全匹配的模塊&#xff0c;匹配上了之后&…

stack.pop()方法_C.示例中的Stack.Pop()方法

stack.pop()方法C&#xff03;Stack.Pop()方法 (C# Stack.Pop() method) Stack.Pop() method is used to remove an object from the top of the stack. The method removes and returns the object from the top. Stack.Pop()方法用于從堆棧頂部刪除對象。 該方法從頂部刪除并…

java list的作用_集合框架(List集合的特有功能概述和測試)

package cn.itcast_03;import java.util.ArrayList;import java.util.List;/** List集合的特有功能&#xff1a;* A:添加功能* void add(int index,Object element):在指定位置添加元素* B:獲取功能* Object get(int index):獲取指定位置的元素* C:列表迭代器* ListIterator li…

12-圖像梯度-Scharr算子和laplacian算子

Scharr算子 cv2.Scharr(img,cv2.CV_64F,1,0) 第一個參數&#xff1a;當前的圖像對象名稱 第二個參數&#xff1a;當前圖像的深度&#xff0c;通常情況下指定為-1&#xff0c;表示輸出和輸入的深度是一樣的&#xff1b;cv2.CV_64F可以存6字節的大小&#xff0c;為了方便后面的取…

新的一年新希望,百忙中繼續學習

公司來了一批新同事&#xff0c;我又忙于購買設備&#xff0c;布置辦公桌了。 小林建議我找一份更合適的工作&#xff0c;目前的我其實是在混日子&#xff0c;因為我并不擅長溝通與銷售。 暫時還是保持這樣吧&#xff0c;我還需要一定時間來積蓄力量。 轉載于:https://www.cnbl…

Oracle Internal Event:10200 Consistent Read診斷事件

10200(consistent read buffer status)內部診斷事件可以用于探測一致性讀CR(consistent read)塊的訪問情況&#xff0c;雖然cr讀的統計信息可以從v$sysstat或AWR/statspack中獲取&#xff0c;但是10200 event還是我們研究Consistent Read一致性讀的有力工具。該事件可以通過在會…

多線程循環輸出abcc++_C ++循環| 查找輸出程序| 套裝4

多線程循環輸出abccProgram 1: 程序1&#xff1a; #include <iostream>using namespace std;int A 5;int fun(){return A--;}int main(){int A 5;while (fun()) {cout << A ::A << " ";}return 0;}Output: 輸出&#xff1a; 9 8 7 6 5Explana…

Opencv——圖像金字塔與圖像尺寸縮放

主要講解 1、resize()函數調用 函數定義&#xff1a; 調用方式&#xff1a; resize(srcImage, dstImage, Size(64, 128)); //對圖片進行修改 resize(srcImage, dstImage, Size(), 0.5, 0.5);第6個參數的含義&#xff1a; INTER_NEAREST:最鄰近插值 (放大好用) INTER_ARE…

java nature_Java中BufferedReader和scanner的對比 - nature

原地址&#xff1a;http://blog.sina.com.cn/s/blog_5fd837410100rtwk.html Scanner 和BufferedReader同樣能實現將鍵盤輸入的數據送入程序&#xff0c; import java.io.*; import java.util.Scanner; public class C { public static void main(String []args) throws IOExcep…

13-Canny邊緣檢測

Canny邊緣檢測主要思路步驟如下&#xff1a; 1&#xff0c;使用高斯濾波器&#xff0c;以平滑圖像&#xff0c;濾除噪聲 2&#xff0c;計算圖像中每個像素點的梯度強度和方向 3&#xff0c;應用非極大值抑制&#xff0c;以消除邊緣檢測帶來的雜散響應 4&#xff0c;應用雙閾值檢…

c# uri.host_C#| Uri.IsHexEncoding()方法與示例

c# uri.hostUri.IsHexEncoding()方法 (Uri.IsHexEncoding() Method) Uri.IsHexEncoding() method is a static method or Uri class. Which is used to return that given string is hex-encoded or not? If the given string is hex coded then it returns true otherwise it…

一位老鳥對 23 種設計模式的有趣見解(轉)

在網絡上流暢很廣的一篇舊文&#xff0c;暫時沒找到原作者&#xff0c;目前所看到的最早轉載時間是 2005 年 2 月 28 日。作者用輕松的語言&#xff0c;形象解釋了 23 種模式&#xff0c;有很好的啟發作用。創建型模式 1、FACTORY—追MM少不了請吃飯了&#xff0c;麥當勞的雞翅…

微機原理——移位指令

例題 思路 選擇移位語句&#xff0c;右移&#xff0c;將AL移出的送入DX左端&#xff0c;將BL移出的送入DX左端。循環八次 MOV AL,01100101B; MOV BL,11011010B; XOR DX,DX;兩個值相同&#xff0c;異或結果為0。等效&#xff1a;MOV DX,0 MOV CX,8;count L1: SHR AL,1;邏輯右…

14-圖像金字塔

由第一個圖可知&#xff0c;圖像金字塔這無非就是對圖像進行放大和縮小罷了 1&#xff0c;高斯金字塔 向下采樣方法(縮小)&#xff0c;越采樣越小&#xff0c;即從金字塔底部向上采樣 cv2.pyrDown(img) 向上采樣方法(放大)&#xff0c;越采樣越大&#xff0c;即從金字塔頂…

JAVA和javascrito_JAVA 和JavaScript的split方法異同

Split的方法很常用&#xff0c;除了str.split("regex")&#xff0c;其實還可以多傳一個參數&#xff1a;str.split("regex", limit)。但是要注意&#xff0c;JavaScript和java的split中limit參數作用是不同的。簡單說&#xff0c;JavaScript中&#xff0c;…

如果__name__ =='__main__':在Python中怎么辦?

In order to understand the details of __name__ variable and the if condition, let us go through a simple exercise. Run a simple python file with just the following lines and run the file as python3 code, 為了了解__name__變量和if條件的詳細信息&#xff0c;讓…

Eclipse C/C++開發環境搭建

1 Eclipse的安裝 到http://java.sun.com/j2se/1.5.0/download.jsp 下載JRE安裝&#xff1b; 到http://eclipse.org下載Eclipse安裝。&#xff08;這兒可以下載Java版本的&#xff0c;也可以下載C/C 版本的&#xff09; 2 對于下載的Java版本或著只下載Eclipse IDE的&#xff0c…