1. 程式人生 > >OpenCV 系列 --- 形態學操作(膨脹、腐蝕)

OpenCV 系列 --- 形態學操作(膨脹、腐蝕)

形態學操作是基於形狀的一系列影象處理操作,基本的運算包括:腐蝕、膨脹、開、閉等。在進行其他演算法研發時,我基本只用膨脹與腐蝕操作,因此本文只介紹這兩種操作,其他的可以相似地進行。

關鍵點

  1. 操作是對影象中的高亮區域進行的,比如膨脹,就是將影象中的高亮區域擴大。
  2. 它們可以達到的目的
    • 去除噪聲
    • 分離出獨立的元素或者連線獨立的元素
    • 可以求影象梯度或者影象中的小洞

測試用圖

為了更加清晰地顯示出操作前後的差距,採用如下圖所示的二值圖
這裡寫圖片描述
一定要注意,形態學操作不光可以用在二值圖,也可以用在灰度圖,甚至可以用在彩色圖。

基本原理

  1. 膨脹
    膨脹就是利用一個核(叫做結構元素)與影象進行卷積。隨著核的移動,每次都取核覆蓋區域的最大畫素值,因此最終完成的效果是將高亮區域擴大。
  2. 腐蝕
    同樣地,腐蝕也是卷積操作。隨著核的移動,每次都取核覆蓋區域的最小畫素值,因此最終完成的效果是將高亮區域縮小。

程式碼示例

以下程式碼是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 ); }

結果

  1. 採用7*7矩形結構元素
    這裡寫圖片描述
    左圖是腐蝕、右圖為膨脹。可以看出,腐蝕縮小了白色(高亮)區域,而膨脹擴大了白色區域。
  2. 採用十字結構元素,大小為7,結果如下
    這裡寫圖片描述
    左圖是腐蝕、右圖為膨脹。可以看出,腐蝕縮小了白色(高亮)區域,而膨脹擴大了白色區域。
  3. 採用橢圓結構元素,大小為15,結果如下
    這裡寫圖片描述

可以看出,當白色區域為圓形時,採用橢圓形的結構元素生成的結果較為規則,圓形結構保持較為完整。