OpenCV 系列 --- 形態學操作(膨脹、腐蝕)
阿新 • • 發佈:2019-01-05
形態學操作是基於形狀的一系列影象處理操作,基本的運算包括:腐蝕、膨脹、開、閉等。在進行其他演算法研發時,我基本只用膨脹與腐蝕操作,因此本文只介紹這兩種操作,其他的可以相似地進行。
關鍵點
- 操作是對影象中的高亮區域進行的,比如膨脹,就是將影象中的高亮區域擴大。
- 它們可以達到的目的
- 去除噪聲
- 分離出獨立的元素或者連線獨立的元素
- 可以求影象梯度或者影象中的小洞
測試用圖
為了更加清晰地顯示出操作前後的差距,採用如下圖所示的二值圖
一定要注意,形態學操作不光可以用在二值圖,也可以用在灰度圖,甚至可以用在彩色圖。
基本原理
- 膨脹
膨脹就是利用一個核(叫做結構元素)與影象進行卷積。隨著核的移動,每次都取核覆蓋區域的最大畫素值,因此最終完成的效果是將高亮區域擴大。 - 腐蝕
同樣地,腐蝕也是卷積操作。隨著核的移動,每次都取核覆蓋區域的最小畫素值,因此最終完成的效果是將高亮區域縮小。
程式碼示例
以下程式碼是OpenCV文件中給出的一段程式碼,比較能說明問題,我加了一些註釋
#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()
{
/// Load an image
src = imread("coins.png" );
if( !src.data )
{
return -1;
}
/// Create windows
namedWindow( "Erosion Demo", CV_WINDOW_AUTOSIZE );
namedWindow( "Dilation Demo", CV_WINDOW_AUTOSIZE );
//Element:\n 0: Rect \n 1: Cross \n 2: Ellipse
/// 腐蝕操作滾動條
createTrackbar( "Element:", "Erosion Demo",&erosion_elem, max_elem,Erosion );
createTrackbar( "Kernel", "Erosion Demo",&erosion_size, max_kernel_size,Erosion );
/// 膨脹操作滾動條
createTrackbar( "Element:", "Dilation Demo",&dilation_elem, max_elem,Dilation );
createTrackbar( "Kernel", "Dilation Demo",&dilation_size, max_kernel_size,Dilation );
// 開始
Erosion( 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 );
}
結果
- 採用7*7矩形結構元素
左圖是腐蝕、右圖為膨脹。可以看出,腐蝕縮小了白色(高亮)區域,而膨脹擴大了白色區域。 - 採用十字結構元素,大小為7,結果如下
左圖是腐蝕、右圖為膨脹。可以看出,腐蝕縮小了白色(高亮)區域,而膨脹擴大了白色區域。 - 採用橢圓結構元素,大小為15,結果如下
可以看出,當白色區域為圓形時,採用橢圓形的結構元素生成的結果較為規則,圓形結構保持較為完整。