OpenCV數(shù)字圖像處理基于C++之圖像形態(tài)學(xué)處理詳解
1、圖像腐蝕
? 原理:腐蝕用來(lái)收縮或細(xì)化二值圖像中的前景,借此實(shí)現(xiàn)去噪聲、元素分割等功能。和所有形態(tài)學(xué)濾波器一樣,腐蝕和膨脹這兩個(gè)濾波器的作用范圍是由結(jié)構(gòu)元素定義的像素集。在某個(gè)像素上應(yīng)用結(jié)構(gòu)元素時(shí),結(jié)構(gòu)元素的錨點(diǎn)與該像素對(duì)齊,所有與結(jié)構(gòu)元素相交的像素就包含在當(dāng)前集合中。腐蝕就是把當(dāng)前像素替換成所定義像素集合中的最小像素值;膨脹是腐蝕的反運(yùn)算,它把當(dāng)前像素替換成所定義像素集合中的最大像素值。由于輸入的二值圖像只包含黑色(值為0)和白色(值為255)像素,因此每個(gè)像素都會(huì)被替換成白色或黑色像素。
? 要形象地理解這兩種運(yùn)算的作用,可考慮背景(黑色)和前景(白色)的物體。腐蝕時(shí),如果結(jié)構(gòu)元素放到某個(gè)像素位置時(shí)碰到了背景(即交集中有一個(gè)像素是黑色的),那么這個(gè)像素就變?yōu)楸尘?膨脹時(shí),如果結(jié)構(gòu)元素放到某個(gè)背景像素位置時(shí)碰到了前景物體,那么這個(gè)像素就被標(biāo)為白色。正因如此,圖像腐蝕后物體尺寸會(huì)縮小(形狀被腐蝕),而圖像膨脹后物體會(huì)擴(kuò)大。在腐蝕圖像中,有些面積較小的物體(可看作背景中的“噪聲”像素)會(huì)徹底消失。與之類似,膨脹后的物體會(huì)變大.而物體中一些“空隙”會(huì)被填滿。OpenCV默認(rèn)使用3×3正方形結(jié)構(gòu)元素。在調(diào)用函數(shù)時(shí),就能得到默認(rèn)的結(jié)構(gòu)元素。你也可以通過(guò)提供一個(gè)矩陣來(lái)指定結(jié)構(gòu)元素的大小(以及形狀),矩陣中的非零元素將構(gòu)成結(jié)構(gòu)元素。
作用:去除圖像中的某些部分以及會(huì)縮小細(xì)化目標(biāo)
1.1 CV腐蝕函數(shù)
CV_EXPORTS_W void erode( InputArray src, OutputArray dst, InputArray kernel, Point anchor = Point(-1,-1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar& borderValue = morphologyDefaultBorderValue() ); src 輸入圖像;通道的數(shù)量可以是任意的,但是深度值應(yīng)該是以下之一: CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. dst 和源圖像同樣大小和類型的輸出圖像。 kernel 用于腐蝕的結(jié)構(gòu)元素;如果element=Mat(),是一個(gè)3 x 3的矩形結(jié)構(gòu)元素. Kernel 可以通過(guò)使用getStructuringElement來(lái)創(chuàng)建。 anchor 素中的錨點(diǎn)的位置,默認(rèn)是值(-1,-1),也就是說(shuō)錨點(diǎn)在元素的中心位置。 iterations 腐蝕的迭代次數(shù)。 borderType像素外推方法。參見#BorderTypes, BORDER_WRAP不支持。 borderValue 固定邊緣的情況下的邊緣值。 參考 dilate,morphologyEx,getStructuringElement
Mat cv::getStructuringElement( int shape, Size ksize, Point anchor = Point(-1,-1) ) 參數(shù)1:結(jié)構(gòu)元的形狀(0:矩形結(jié)構(gòu)元;1:十字架結(jié)構(gòu)元;2:橢圓結(jié)構(gòu)元); 參數(shù)2:結(jié)構(gòu)元大小(size(m, n)); 參數(shù)3:結(jié)構(gòu)元中心點(diǎn)所在位置(point(x, y))默認(rèn)為中心點(diǎn)
Mat element = getStructuringElement(0, Size(3, 3)); //構(gòu)造矩形結(jié)構(gòu)元素 Mat image_erosion; erode(image_bw, image_erosion, element, Point(-1, -1), 3); //執(zhí)行腐蝕操作 imshow("image_erosion", image_erosion);
原圖
二值圖
CV腐蝕
1.2 自定義腐蝕函數(shù)
void erode_my(Mat &src,Mat &dst,int size) { for (int i = 0; i < src.rows; ++i) { for (int j = 0; j < src.cols; ++j) { uchar minV = 255; //uchar maxV = 0; //遍歷周圍最小像素值 for (int yi = i - size / 2; yi <= i + size / 2; yi++) { for (int xi = j - size / 2; xi <= j + size / 2; xi++) { if (xi < 0 || xi >= src.cols || yi < 0 || yi >= src.rows) { continue; } minV = (std::min<uchar>)(minV, src.at<uchar>(yi, xi)); //maxV = (std::max<uchar>)(maxV, src.at<uchar>(yi, xi)); } } dst.at<uchar>(i, j) = minV; } } }
自定義腐蝕
1.3 對(duì)比
erode_my(image_bw, image_erosion_my,9); 當(dāng)腐蝕結(jié)構(gòu)擴(kuò)大到9×9時(shí)效果基本與cv自帶函數(shù)一致。
2、圖像膨脹
原理:腐蝕用來(lái)收縮或細(xì)化二值圖像中的前景,借此實(shí)現(xiàn)去噪聲、元素分割等功能。腐蝕過(guò)程:用結(jié)構(gòu)元來(lái)逐個(gè)像素掃描被腐蝕圖像,并根據(jù)結(jié)構(gòu)元和被腐蝕圖像的關(guān)系確定腐蝕結(jié)果。
注意,腐蝕操作等形態(tài)學(xué)操作,是逐個(gè)像素地來(lái)確定值的,每次判定的點(diǎn)都與結(jié)構(gòu)元中心點(diǎn)所對(duì)應(yīng),如果結(jié)構(gòu)元完全處于前景圖像中,就將結(jié)構(gòu)元中心點(diǎn)所對(duì)應(yīng)的腐蝕結(jié)果圖像中的像素點(diǎn)處理為前景色(如1)。如果結(jié)構(gòu)元不完全處于前景圖像中,就將結(jié)構(gòu)元中心點(diǎn)所對(duì)應(yīng)的腐蝕結(jié)果圖像中的像素點(diǎn)處理為背景色(如0)。(結(jié)構(gòu)元也被稱為核)
作用:增大圖像中的目標(biāo),或者填充、連接某些目標(biāo)。
2.1 CV膨脹函數(shù)
CV_EXPORTS_W void dilate( InputArray src, OutputArray dst, InputArray kernel, Point anchor = Point(-1,-1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar& borderValue = morphologyDefaultBorderValue() ); src 輸入圖像;通道的數(shù)量可以是任意的,但是深度值應(yīng)該是以下之一:CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. dst 和源圖像同樣大小和類型的輸出圖像。 kernel 膨脹核元素,如果elemenat=Mat(), 是一個(gè)3 x 3的矩形核元素,核可以使用getStructuringElement來(lái)創(chuàng)建。 anchor 元素中的錨點(diǎn)的位置,默認(rèn)是值(-1,-1),也就是說(shuō)錨點(diǎn)在元素的中心位置。 iterations 膨脹的迭代次數(shù)。 borderType 像素外推方法。參見#BorderTypes, BORDER_WRAP不支持。 borderValue 固定邊緣的情況下的邊緣值。 參考:erode,morphologyEx,getStructuringElement
//膨脹 Mat element = getStructuringElement(0, Size(3, 3)); //構(gòu)造矩形結(jié)構(gòu)元素 Mat image_dilate; dilate(image_bw, image_dilate, element, Point(-1, -1), 9); //執(zhí)行膨脹操作 imshow("image_dilate", image_dilate);
二值圖
CV膨脹
2.2 自定義膨脹函數(shù)
void dilate_my(Mat& src, Mat& dst, int size) { for (int i = 0; i < src.rows; ++i) { for (int j = 0; j < src.cols; ++j) { //uchar minV = 255; uchar maxV = 0; //遍歷周圍最大像素值 for (int yi = i - size / 2; yi <= i + size / 2; yi++) { for (int xi = j - size / 2; xi <= j + size / 2; xi++) { if (xi < 0 || xi >= src.cols || yi < 0 || yi >= src.rows) { continue; } //minV = (std::min<uchar>)(minV, src.at<uchar>(yi, xi)); maxV = (std::max<uchar>)(maxV, src.at<uchar>(yi, xi)); } } dst.at<uchar>(i, j) = maxV; } } }
自定義膨脹
2.3 對(duì)比
dilate_my(image_bw, image_dilate_my, 9); 當(dāng)膨脹結(jié)構(gòu)擴(kuò)大到9×9時(shí)效果基本與cv自帶函數(shù)一致。
腐蝕圖像相當(dāng)于對(duì)其反色圖像膨脹后再取反色;
膨脹圖像相當(dāng)于對(duì)其反色圖像腐蝕后再取反色。
3、開運(yùn)算
原理:先腐蝕,再膨脹。
作用:平滑物體輪廓、斷開狹窄的狹頸、消除細(xì)長(zhǎng)的突出和物體??梢匀サ魣D像上一些小的對(duì)象。(假設(shè)圖像前景色是白色,背景色是黑色)
原圖
3.1 方法一
//先腐蝕后膨脹 Mat open_image; Mat element = getStructuringElement(0, Size(3, 3)); //構(gòu)造矩形結(jié)構(gòu)元素 erode(image_bw, image_erosion, element, Point(-1, -1), 3); //執(zhí)行腐蝕操作 dilate(image_erosion, open_image, element, Point(-1, -1), 3); //執(zhí)行膨脹操作 imshow("open", open_image);
3.2 方法二
morphologyEx(image_bw, open_image, MORPH_OPEN, element); imshow("open2", open_image);
4、閉運(yùn)算
原理:先膨脹,再腐蝕。
作用:閉運(yùn)算可以填充小洞,填充小的噪點(diǎn)。
4.1 方法一
Mat close_image; Mat element = getStructuringElement(0, Size(3, 3)); //構(gòu)造矩形結(jié)構(gòu)元素 dilate(image_bw, image_dilate, element, Point(-1, -1), 3); //執(zhí)行膨脹操作 erode(image_dilate, close_image, element, Point(-1, -1), 3); //執(zhí)行腐蝕操作 imshow("close", close_image);
4.2 方法二
morphologyEx(image_bw, close_image, MORPH_CLOSE, element); imshow("close2", close_image);
4.3 morphologyEx函數(shù)介紹
void morphologyEx( InputArray src, OutputArray dst, int op, InputArray kernel, Point anchor = Point(-1,-1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar& borderValue = morphologyDefaultBorderValue() ); (1)參數(shù)1:InputArray src 輸入圖像,圖像數(shù)據(jù)類型必須為CV_8U, CV_16U, CV_16S, CV_32F or CV_64F中的一種。 (2)參數(shù)2:OutputArray dst 輸出圖像,數(shù)據(jù)類型與大小和輸入圖像一樣。 (3)參數(shù)3:int op 形態(tài)學(xué)處理的類型: MORPH_ERODE = 0:腐蝕處理 MORPH_DILATE = 1:膨脹處理 MORPH_OPEN = 2:開運(yùn)算處理 MORPH_CLOSE = 3:閉運(yùn)算處理 MORPH_GRADIENT = 4:形態(tài)學(xué)梯度 MORPH_TOPHAT = 5:頂帽變換 MORPH_BLACKHAT = 6:黑帽變換 MORPH_HITMISS = 7 :擊中-擊不中變換 (4)參數(shù)4:InputArray kernel結(jié)構(gòu)元矩陣 (5)參數(shù)5:Point anchor = Point(-1,-1) 結(jié)構(gòu)元中心點(diǎn), 默認(rèn)值Point(-1,-1), 表示正中心 (6)參數(shù)6:int iterations = 1 腐蝕膨脹處理的次數(shù),默認(rèn)值為1; 如果是開運(yùn)算閉運(yùn)算,次數(shù)表示先腐蝕或者膨脹幾次,再膨脹腐蝕幾次,而不是開運(yùn)算閉運(yùn)算幾次: 如開運(yùn)算且次數(shù)為2:erode -> erode -> dilate -> dilate (7)參數(shù)7:int borderType = BORDER_CONSTANT 圖像邊框插值類型,默認(rèn)類型為固定值填充 BORDER_CONSTANT = 0:固定值 i 填充:iiiiii | abcdefgh | iiiiiii BORDER_REPLICATE = 1:兩端復(fù)制:aaaaaa | abcdefgh | hhhhhhh BORDER_REFLECT = 2:鏡像復(fù)制:fedcba | abcdefgh | hgfedcb BORDER_WRAP = 3:去除一端的值然后復(fù)制: cdefgh | abcdefgh | abcdefg BORDER_REFLECT_101 = 4:去除一端的值然后鏡像復(fù)制: gfedcb|abcdefgh|gfedcba BORDER_TRANSPARENT = 5:推導(dǎo)賦值 uvwxyz | abcdefgh | ijklmno BORDER_REFLECT101 = BORDER_REFLECT_101: same as BORDER_REFLECT_101 BORDER_DEFAULT = BORDER_REFLECT_101: same as BORDER_REFLECT_101 BORDER_ISOLATED = 16:< do not look outside of ROI (8)參數(shù)8:const Scalar& borderValue = morphologyDefaultBorderValue() 文檔中說(shuō)明:param borderValue Border value in case of a constant border. The default value has a special meaning.
5、頂帽運(yùn)算
原理:頂帽(或禮帽)運(yùn)算是原始圖像減去圖像開運(yùn)算的結(jié)果。
頂帽運(yùn)算:原始圖像 — 圖像開運(yùn)算
作用:得到圖像的噪聲。如下圖所示:
5.1 方法一
//構(gòu)造結(jié)構(gòu)元 Mat kernel = getStructuringElement(0, Size(5, 5)); Mat image_lm; //頂帽變換(禮帽變換) morphologyEx(image_bw, image_lm, 5, kernel); cv::imshow("image_lm", image_lm);
5.2 方法二
Mat image_lm2; //**頂帽運(yùn)算:原始圖像 — 圖像開運(yùn)算** //dst=img1-img2;//這兩個(gè)減法效果相同 若dst<0,則dst=0 subtract(image_bw,open_image2, image_lm2);//注意:要求被處理圖片尺寸一致 cv::imshow("image_lm2",image_lm2);
Mat image_lm2; absdiff(image_bw, open_image2, image_lm2);//若dst<0,則dst=|dst|>=0 用于檢測(cè)兩幅相似圖像的不同點(diǎn),效果比上面的兩種減法好 cv::imshow("image_lm2", image_lm2);
6、黑帽運(yùn)算
原理:黑帽運(yùn)算是圖像閉運(yùn)算操作減去原始圖像的結(jié)果。
黑帽運(yùn)算:閉運(yùn)算 — 原始圖像
作用:得到圖像內(nèi)部的小孔,或者前景色中的小黑點(diǎn)。如下圖所示:
6.1 方法一
//構(gòu)造結(jié)構(gòu)元 Mat kernel = getStructuringElement(0, Size(5, 5)); //底帽變換(黑帽變換) Mat image_hm; morphologyEx(image_bw, image_hm, 6, kernel); cv::imshow("image_hm", image_hm);
6.2 方法二
Mat image_hm2; subtract(image_bw, close_image2, image_hm2);//注意:要求被處理圖片尺寸一致 cv::imshow("image_hm2", image_hm2);
Mat image_hm2; absdiff(image_bw, close_image2, image_hm2);//若dst<0,則dst=|dst|>=0 用于檢測(cè)兩幅相似圖像的不同點(diǎn),效果比上面的兩種減法好 cv::imshow("image_hm2", image_hm2);
7、形態(tài)學(xué)梯度
原理:膨脹圖與腐蝕圖之差;
作用:對(duì)二值圖進(jìn)行這一操作可以得到圖像中白色區(qū)域的邊界,因此可以用形態(tài)學(xué)梯度來(lái)保留物體的邊界輪廓。
7.1 方法一
//構(gòu)造結(jié)構(gòu)元 Mat kernel = getStructuringElement(0, Size(5, 5)); Mat image_lm; //形態(tài)學(xué)梯度 morphologyEx(image_bw, image_td, 4, kernel); cv::imshow("image_td", image_td);
7.2 方法二
Mat image_tw2; subtract(image_dilate, image_erosion, image_tw2);//注意:要求被處理圖片尺寸一致 cv::imshow("image_tw2", image_tw2);
Mat image_tw2; absdiff(image_dilate, image_erosion, image_tw2);//若dst<0,則dst=|dst|>=0 用于檢測(cè)兩幅相似圖像的不同點(diǎn),效果比上面的兩種減法好 cv::imshow("image_tw2", image_tw2);
部分參考來(lái)自:數(shù)字圖像處理(c++ opencv)–持續(xù)更新 - 知乎 (zhihu.com)
總結(jié)
到此這篇關(guān)于OpenCV數(shù)字圖像處理基于C++之圖像形態(tài)學(xué)處理的文章就介紹到這了,更多相關(guān)OpenCV數(shù)字圖像處理基于C++內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言開發(fā)實(shí)現(xiàn)貪吃蛇小游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言開發(fā)實(shí)現(xiàn)貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10C語(yǔ)言實(shí)現(xiàn)奇數(shù)階魔方陣的方法
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)奇數(shù)階魔方陣的方法,涉及數(shù)組及相關(guān)數(shù)學(xué)函數(shù)的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02C語(yǔ)言小項(xiàng)目實(shí)戰(zhàn)之通訊錄功能
這篇文章主要介紹了如何設(shè)計(jì)和實(shí)現(xiàn)一個(gè)簡(jiǎn)單的通訊錄管理系統(tǒng),包括聯(lián)系人信息的存儲(chǔ)、增加、刪除、查找、修改和排序等功能,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-01-01opencv實(shí)現(xiàn)圖片與視頻中人臉檢測(cè)功能
這篇文章主要為大家詳細(xì)介紹了opencv實(shí)現(xiàn)圖片與視頻中人臉檢測(cè)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01