1. 程式人生 > >【 imgproc 模組. 影象處理】形態學變化

【 imgproc 模組. 影象處理】形態學變化

一、更多的形態學變化

    包括開運算 (Opening)、閉運算 (Closing)、形態梯度 (Morphological Gradient)、頂帽 (Top Hat)、黑帽(Black Hat)。具體可參考《數字影象處理 第三版》(岡薩雷斯)——第九章 形態學影象處理注:具體原理都是一些數學計算公式、方法,目前只大概瞭解,後面可具體研讀。

二、開運算

(1)教程中的解釋:

  • 開運算是通過先對影象腐蝕再膨脹實現的。

    dst = open( src, element) = dilate( erode( src, element ) )

  • 能夠排除小團塊物體(假設物體較背景明亮)

  • 請看下面,左圖是原影象,右圖是採用開運算轉換之後的結果圖。 觀察發現字母拐彎處的白色空間消失。

    Opening

(2)資料整理

        開運算和閉運算都由腐蝕和膨脹複合而成, 開運算是先腐蝕後膨脹, 而閉運算是先膨脹後腐蝕。膨脹:亮區擴大;腐蝕:亮區縮小。

              

       一般來說, 開運算可以使影象的輪廓變得光滑, 還能使狹窄的連線斷開和消除細毛刺。 
如圖8.11所示, 開運算斷開了團中兩個小區域間兩個畫素寬的連線〈斷開了狹窄連線〉,並且去除了右側物體上部突出的一個小於結構元素的2×2的區域〈去除細小毛刺〉: 但與腐蝕不同的是, 影象大的輪廓並沒有發生整體的收縮, 物體位置也沒有發生任何變化。 

 (3)opencv程式碼實現

#include"stdafx.h"
#include<opencv2/opencv.hpp>
int open_value = 0;
int open_max = 5;
int morph_elem = 0;
int max_elem = 2;
cv::Mat src,dst;
void openOperator(int,void*);

int main(int argc, char** argv) {
    src = cv::imread("lena512color.tiff");
    if (src.empty()) {
        printf(
"Image load failed..."); return -1; } cv::namedWindow("src", CV_WINDOW_NORMAL); cv::createTrackbar("Opening_value:","src", &open_value, open_max, openOperator); cv::createTrackbar("Element:\n 0: Rect - 1: Cross - 2: Ellipse", "src",&morph_elem, max_elem,openOperator); openOperator(0, 0); //這句註釋掉時,剛開始執行時若不移動滑動條則圖片不會顯示 cvWaitKey(0); return 0; } void openOperator(int, void*) { /*getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1)); @用法:返回一個特定形狀(shape),大小(size),及錨點(anchor)的核,錨點為(-1,-1)時預設為中心 @引數:int shape MORPH_RECT = 0, MORPH_CROSS = 1, MORPH_ELLIPSE = 2 */ cv::Mat element = cv::getStructuringElement(morph_elem, cv::Size(2 * open_value + 1, 2 * open_value + 1), cv::Point(open_value, open_value)); morphologyEx(src, dst, cv::MORPH_OPEN, element);//element 為輸入的結構元,用於卷積的矩陣 /*@API: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() ); @用法: @引數:op形態學操作型別 MORPH_ERODE = 0, MORPH_DILATE = 1, MORPH_OPEN = 2, MORPH_CLOSE = 3, MORPH_GRADIENT = 4, MORPH_TOPHAT = 5, MORPH_BLACKHAT = 6, MORPH_HITMISS = 7 @引數:InputArray kernel,用於進行形態學操作的核,可以用getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));獲取 @引數:anchor,錨點,核的錨點位置,預設(-1,-1)則為中心 @引數:iterations,腐蝕、膨脹次數次數 @引數:borderType,引數外推方法, ...具體用到再查*/ cv::imshow("src", dst); }

二、閉運算

(1)教程中的解釋:

  • 閉運算是通過先對影象膨脹再腐蝕實現的。

    dst = close( src, element ) = erode( dilate( src, element ) )

能夠排除小型黑洞(黑色區域)。

Closing example

(2)相關資料整理:

閉運算同樣可以使輪廓變得光滑, 但與開運算相反, 它通常能夠彌合狹窄的間斷, 填充小的孔洞。

 

 

 (3)opencv實現程式碼:類似開運算

三、形態梯度

  • 膨脹圖與腐蝕圖之差

    dst = morph_{grad}( src, element ) = dilate( src, element ) - erode( src, element )

  • 能夠保留物體的邊緣輪廓,如下所示:

    Gradient

四、頂帽

  • 原影象與開運算結果圖之差
  • dst = tophat( src, element ) = src - open( src, element )

     Top Hat

 

五、黑帽

  • 閉運算結果圖與原影象之差

    dst = blackhat( src, element ) = close( src, element ) - src

    Black Hat

六、測試程式碼(官方)

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>

using namespace cv;

/// 全域性變數
Mat src, dst;

int morph_elem = 0;
int morph_size = 0;
int morph_operator = 0;
int const max_operator = 4;
int const max_elem = 2;
int const max_kernel_size = 21;

char* window_name = "Morphology Transformations Demo";

/** 回撥函式申明 */
void Morphology_Operations( int, void* );

/** @函式 main */
int main( int argc, char** argv )
{
  /// 裝載影象
  src = imread( argv[1] );

  if( !src.data )
  { return -1; }

 /// 建立顯示視窗
 namedWindow( window_name, CV_WINDOW_AUTOSIZE );

 /// 建立選擇具體操作的 trackbar
 createTrackbar("Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat", window_name, &morph_operator, max_operator, Morphology_Operations );

 /// 建立選擇核心形狀的 trackbar
 createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name,
                 &morph_elem, max_elem,
                 Morphology_Operations );

 /// 建立選擇核心大小的 trackbar
 createTrackbar( "Kernel size:\n 2n +1", window_name,
                 &morph_size, max_kernel_size,
                 Morphology_Operations );

 /// 啟動使用預設值
 Morphology_Operations( 0, 0 );

 waitKey(0);
 return 0;
 }

 /**
  * @函式 Morphology_Operations
  */
void Morphology_Operations( int, void* )
{
  // 由於 MORPH_X的取值範圍是: 2,3,4,5 和 6
  int operation = morph_operator + 2;

  Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );

  /// 執行指定形態學操作
  morphologyEx( src, dst, operation, element );
  imshow( window_name, dst );
  }