opencv 图像的腐蚀与膨胀
-
形態學操作就是基于形狀的一系列圖像處理操作。通過將?結構元素?作用于輸入圖像來產生輸出圖像。
-
最基本的形態學操作有二:腐蝕與膨脹(Erosion 與 Dilation)。 他們的運用廣泛:
- 消除噪聲
- 分割(isolate)獨立的圖像元素,以及連接(join)相鄰的元素。
- 尋找圖像中的明顯的極大值區域或極小值區域。
-
通過以下圖像,我們簡要來討論一下膨脹與腐蝕操作(譯者注:注意這張圖像中的字母為黑色,背景為白色,而不是一般意義的背景為黑色,前景為白色):
膨脹
-
此操作將圖像??與任意形狀的內核 (),通常為正方形或圓形,進行卷積。
-
內核??有一個可定義的?錨點, 通常定義為內核中心點。
-
進行膨脹操作時,將內核??劃過圖像,將內核??覆蓋區域的最大相素值提取,并代替錨點位置的相素。顯然,這一最大化操作將會導致圖像中的亮區開始”擴展” (因此有了術語膨脹?dilation?)。對上圖采用膨脹操作我們得到:
背景(白色)膨脹,而黑色字母縮小了。
腐蝕
-
腐蝕在形態學操作家族里是膨脹操作的孿生姐妹。它提取的是內核覆蓋下的相素最小值。
-
進行腐蝕操作時,將內核??劃過圖像,將內核??覆蓋區域的最小相素值提取,并代替錨點位置的相素。
-
以與膨脹相同的圖像作為樣本,我們使用腐蝕操作。從下面的結果圖我們看到亮區(背景)變細,而黑色區域(字母)則變大了。
源碼
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include "highgui.h" #include <stdlib.h> #include <stdio.h>using namespace cv;/// 全局變量 Mat src, erosion_dst, dilation_dst;int erosion_elem = 0; int erosion_size = 0; int dilation_elem = 0; int dilation_size = 0; int const max_elem = 2; int const max_kernel_size = 21;/** Function Headers */ void Erosion( int, void* ); void Dilation( int, void* );/** @function main */ int main( int argc, char** argv ) {/// Load 圖像src = imread( argv[1] );if( !src.data ){ return -1; }/// 創建顯示窗口namedWindow( "Erosion Demo", CV_WINDOW_AUTOSIZE );namedWindow( "Dilation Demo", CV_WINDOW_AUTOSIZE );cvMoveWindow( "Dilation Demo", src.cols, 0 );/// 創建腐蝕 TrackbarcreateTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo",&erosion_elem, max_elem,Erosion );createTrackbar( "Kernel size:\n 2n +1", "Erosion Demo",&erosion_size, max_kernel_size,Erosion );/// 創建膨脹 TrackbarcreateTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",&dilation_elem, max_elem,Dilation );createTrackbar( "Kernel size:\n 2n +1", "Dilation Demo",&dilation_size, max_kernel_size,Dilation );/// Default startErosion( 0, 0 );Dilation( 0, 0 );waitKey(0);return 0; }/** @function Erosion */ void Erosion( int, void* ) {int erosion_type;if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; }else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; }else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }Mat element = getStructuringElement( erosion_type,Size( 2*erosion_size + 1, 2*erosion_size+1 ),Point( erosion_size, erosion_size ) );/// 腐蝕操作erode( src, erosion_dst, element );imshow( "Erosion Demo", erosion_dst ); }/** @function Dilation */ void Dilation( int, void* ) {int dilation_type;if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; }else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; }else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }Mat element = getStructuringElement( dilation_type,Size( 2*dilation_size + 1, 2*dilation_size+1 ),Point( dilation_size, dilation_size ) );///膨脹操作dilate( src, dilation_dst, element );imshow( "Dilation Demo", dilation_dst ); }解釋
大部分代碼應該不需要解釋了。
- 裝載圖像 (可以是 RGB圖像或者灰度圖 )
- 創建兩個顯示窗口 (一個用于膨脹輸出,一個用于腐蝕輸出)
- 為每個操作創建兩個 Trackbars:
- 第一個 trackbar “Element” 返回?erosion_elem?或者?dilation_elem
- 第二個 trackbar “Kernel size” 返回?erosion_size?或者?dilation_size?。
- 每次移動標尺, 用戶函數?Erosion?或者?Dilation?就會被調用,函數將根據當前的trackbar位置更新輸出圖像。
讓我們分析一下這兩個函數:
Erosion:
/** @function Erosion */ void Erosion( int, void* ) {int erosion_type;if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; }else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; }else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }Mat element = getStructuringElement( erosion_type,Size( 2*erosion_size + 1, 2*erosion_size+1 ),Point( erosion_size, erosion_size ) );/// 腐蝕操作erode( src, erosion_dst, element );imshow( "Erosion Demo", erosion_dst ); }-
進行?腐蝕?操作的函數是?erode?。 它接受了三個參數:
-
src: 原圖像
-
erosion_dst: 輸出圖像
-
element: 腐蝕操作的內核。 如果不指定,默認為一個簡單的??矩陣。否則,我們就要明確指定它的形狀,可以使用函數getStructuringElement:
Mat element = getStructuringElement( erosion_type,Size( 2*erosion_size + 1, 2*erosion_size+1 ),Point( erosion_size, erosion_size ) );
我們可以為我們的內核選擇三種形狀之一:
- 矩形: MORPH_RECT
- 交叉形: MORPH_CROSS
- 橢圓形: MORPH_ELLIPSE
然后,我們還需要指定內核大小,以及?錨點?位置。不指定錨點位置,則默認錨點在內核中心位置。
-
-
就這些了,我們現在可以對圖像進行腐蝕操作了。
Note
?OpenCV的?erode?函數還有另外的參數,其中一個參數允許你一下對圖像進行多次腐蝕操作。在這個簡單的文檔中沒有用到它,但是你可以參考OpenCV的使用手冊。
Dilation:
下面是膨脹的代碼,你可以看到,它和?Erosion?函數是多么相似。 這里我們同樣可以指定內核的形狀,錨點和大小。
/** @function Dilation */ void Dilation( int, void* ) {int dilation_type;if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; }else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; }else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }Mat element = getStructuringElement( dilation_type,Size( 2*dilation_size + 1, 2*dilation_size+1 ),Point( dilation_size, dilation_size ) );/// 膨脹操作dilate( src, dilation_dst, element );imshow( "Dilation Demo", dilation_dst ); }總結
以上是生活随笔為你收集整理的opencv 图像的腐蚀与膨胀的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: opencv简单滤波
- 下一篇: opencv 其他形态学变换