【OpenCV學習筆記】之形態學操作(Morphological Processing)

一、圖像的形態學操作(Morphological Image Processing)

       形態學一般指生物學中研究動物和植物結構的一個分支。用數學形態學(也稱圖像代數)表示以形態爲基礎對圖像進行分析的數學工具。基本思想是用具有一定形態的結構元素去度量和提取圖像中的對應形狀以達到對圖像分析和識別的目的。形態學圖像處理的數學基礎和所用語言是集合論。形態學圖像處理的應用可以簡化圖像數據,保持它們基本的形狀特性,併除去不相干的結構。

      形態學圖像處理的基本運算有:膨脹、腐蝕、開操作和閉操作,擊中與擊不中變換,TOP-HAT變換,黑帽變換等

      形態學的應用:消除噪聲、邊界提取、區域填充、連通分量提取、凸殼、細化、粗化等;分割出獨立的圖像元素,或者圖像中相鄰的元素;求取圖像中明顯的極大值區域和極小值區域;求取圖像梯度

在講各種形態學操作之前,先來看看結構元素:

       膨脹和腐蝕操作的核心內容是結構元素。(後面的開閉運算等重要的也是結構元素的設計,一個合適的結構元素的設計可以帶來很好的處理效果)一般來說結構元素是由元素爲1或者0的矩陣組成。結構元素爲1的區域定義了圖像的領域,領域內的像素在進行膨脹和腐蝕等形態學操作時要進行考慮。

       一般來說,二維或者平面結構的結構元素要比處理的圖像小得多。結構元素的中心像素,即結構元素的原點,與輸入圖像中感興趣的像素值(即要處理的像素值)相對應。三維的結構元素使用01來定義x-y平面中結構元素的範圍,使用高度值定義第三維。

OpenCV裏面的API介紹:

Mat kernel = getStructuringElement(int shape,Size ksize,Point anchor);
//結構元素的定義:形狀 (MORPH_RECT \MORPH_CROSS(交叉形) \MORPH_ELLIPSE);結構元素大小;錨點 默認是Point(-1, -1)意思就是中心像素,也可以自己指定

 結構元素的選取,依據具體項目問題對象而定,遠不止這幾種大可自己設計。

1.1 膨脹(Dilate)

         膨脹是腐蝕運算的對偶運算,其作用是在結構元素的約束下將與目標區域相接觸的背景合併到該目標物中,使目標邊界向外部擴張,物體的面積增大了相應數量的點。

集合論思想:

原理步驟:

OpenCV裏面的API介紹:

void dilate( const Mat& src, Mat& dst, const Mat& element,Point anchor=Point(-1,-1), int iterations=1,int borderType=BORDER_CONSTANT,const Scalar& borderValue=morphologyDefaultBorderValue() );

參數解釋:

  • src:原圖像。
  • dst:目標圖像。
  • element:腐蝕操作的內核。 如果不指定,默認爲一個簡單的 3x3 矩陣。否則,我們就要明確指定它的形狀,可以使用函數getStructuringElement().
  • anchor:默認爲Point(-1,-1),內核中心點。省略時爲默認值。
  • iterations:腐蝕次數。省略時爲默認值1。
  • borderType:推斷邊緣類型,具體參見borderInterpolate函數。默認爲BORDER_DEFAULT,省略時爲默認值。
  • borderValue:邊緣值,具體可參見createMorphoogyFilter函數。可省略。

1.2 腐蝕(Erode)

         腐蝕是一種在結構元素約束下消除目標圖形的部分邊界點,使其邊界向內部收縮的的算法,具有收縮目標區域的作用。

集合論思想:

                 

原理步驟:

OpenCV裏面的API介紹:

void erode( const Mat& src, Mat& dst, const Mat& element,Point anchor=Point(-1,-1), int iterations=1,int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue() );

參數和膨脹一模一樣;

1.3 開運算(Open)

開運算:先腐蝕後膨脹;

作用:用來消除圖像中細小對象,在纖細點處分離物體和平滑較大物體的邊界而有不明顯改變其面積和形狀。

集合論思想:

         

開運算的幾何解釋:

                      

Opencv裏面的API介紹:——見最後總結

1.4 閉運算(Close)

       閉運算:先膨脹後腐蝕;

         作用:用來填充目標內部的細小孔洞(fill hole),將斷開的鄰近目標連接,在不明顯改變物體面積和形狀的情況下平滑其邊界。

集合論思想:

          

閉運算的幾何解釋:

                   

Opencv裏面的API介紹:——見最後總結

1.5 形態學梯度、頂帽、黑帽

(1)形態學梯度(Morphological gradient)

         形態學梯度操作能描述圖像亮度變化的劇烈程度;當我們想要突出高亮區域的外圍時,則可以選用形態學梯度來突出邊緣,可以保留物體的邊緣輪廓。

常見的幾種梯度:

基本梯度,膨脹減去腐蝕:

Opencv裏面的API介紹:——見最後總結

 

(2)禮/頂帽(Top hat)

         頂帽是原圖與原圖的開運算的差值圖像。開運算放大了裂縫或者局部低亮度的區域,所以,從原圖中減去開運算後的圖,得到的結果突出了比原圖輪廓周圍的區域更明亮的區域,這個操作與選擇的核的大小有關。TopHat運算一般用來分離比鄰近點亮一些的斑塊,可以使用這個運算提取背景。

Opencv裏面的API介紹:——見最後總結

(3) 黑帽(Black hat)

        黑帽是閉運算結果與原圖的差值圖像。黑帽運算的結果突出了比原圖輪廓周圍區域更暗的區域,所以黑帽運算用來分離比鄰近點暗一些的斑塊。

Opencv裏面的API介紹:——見最後總結

1.6 總結:

//形態學操作(開、閉、形態學梯度、頂帽、黑帽)
	morphologyEx(src, dst, MORPH_BLACKHAT, kernel);
	//第一個參數,InputArray類型的src,輸入圖像,即源圖像,填Mat類的對象即可。圖像位深應該爲以下五種之一:CV_8U, CV_16U,CV_16S, CV_32F 或CV_64F。
	//第二個參數,OutputArray類型的dst,即目標圖像,函數的輸出參數,需要和源圖片有一樣的尺寸和類型。
	//第三個參數,int類型的op,表示形態學運算的類型,可以是如下之一的標識符:
	//MORPH_OPEN – 開運算(Opening operation):先腐蝕後膨脹,去掉小對象
	//MORPH_CLOSE – 閉運算(Closing operation):先膨脹後腐蝕,可以填充一些小的空洞(fill hole)
	//MORPH_GRADIENT - 形態學梯度(Morphological gradient):膨脹後的圖減去腐蝕後的圖(設置恰當的參數可以得到目標的大致邊緣)
	//MORPH_TOPHAT - “頂帽”(“Top hat”):原圖像與開操作之間的差值圖像(可以用來觀察開運算除去了哪些小目標)
	//MORPH_BLACKHAT - “黑帽”(“Black hat“):閉操作圖像與源圖像的差值圖像(可以觀察閉運算的效果)
	//第四個參數:結構元素即形態學運算的內核
	//第五個參數,Point類型的anchor,錨的位置,其有默認值( - 1, - 1),表示錨位於中心。
	//第六個參數,int類型的iterations,迭代使用函數的次數,默認值爲1。
	//第七個參數,int類型的borderType,用於推斷圖像外部像素的某種邊界模式。注意它有默認值BORDER_ CONSTANT。
	//第八個參數,const Scalar&類型的borderValue,當邊界爲常數時的邊界值,有默認值morphologyDefaultBorderValue(),一般我們不用去管他。需要用到它時,可以看官方文檔

示例程序:

//形態學的操作的學習
#include "stdafx.h"
#include<opencv2/opencv.hpp>
#include<iostream>

using namespace cv;

char output[] = "Morphlogy_image";
Mat dst, src;
void Morphlogy_Operators(int, void*);
int element_size = 3;
int max_size = 21;
int main(int argc, char**argv)
{
	Mat src = imread("C:/Users/59235/Desktop/工作/異常1/temp1.bmp");
	if (!src.data)
	{
		printf("could not load image...\n");
		return -1;
	}
	namedWindow("input image", CV_WINDOW_AUTOSIZE);
	imshow("input image", src);

	namedWindow(output, CV_WINDOW_AUTOSIZE);
	//軌跡條或滑動條(Trackbar)的控件工具
	createTrackbar("elementSIZE:", output, &element_size, max_size, Morphlogy_Operators);
	//參數一、trackbarname:滑動空間的名稱;參數二、winname:滑動空間用於依附的圖像窗口的名稱;數三、value:初始化閾值;參數四、count:滑動控件的刻度範圍;參數五、TrackbarCallback是回調函數
	Morphlogy_Operators(0, 0);

	waitKey(0);
	return 0;
}
//各種形態學操作
void Morphlogy_Operators(int, void*)
{
	int s = element_size + 1;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));
	//結構元素的定義:形狀 (MORPH_RECT \MORPH_CROSS(交叉形) \MORPH_ELLIPSE);結構元素大小;錨點 默認是Point(-1, -1)意思就是中心像素


	//膨脹
	//dilate(src,dst,kernel);

	//腐蝕
	//erode(src, dst, kernel);

	//形態學操作(開、閉、形態學梯度、頂帽、黑帽)
	morphologyEx(src, dst, MORPH_BLACKHAT, kernel);
	//第一個參數,InputArray類型的src,輸入圖像,即源圖像,填Mat類的對象即可。圖像位深應該爲以下五種之一:CV_8U, CV_16U,CV_16S, CV_32F 或CV_64F。
	//第二個參數,OutputArray類型的dst,即目標圖像,函數的輸出參數,需要和源圖片有一樣的尺寸和類型。
	//第三個參數,int類型的op,表示形態學運算的類型,可以是如下之一的標識符:
	//MORPH_OPEN – 開運算(Opening operation):先腐蝕後膨脹,去掉小對象
	//MORPH_CLOSE – 閉運算(Closing operation):先膨脹後腐蝕,可以填充一些小的空洞(fill hole)
	//MORPH_GRADIENT - 形態學梯度(Morphological gradient):膨脹後的圖減去腐蝕後的圖(設置恰當的參數可以得到目標的大致邊緣)
	//MORPH_TOPHAT - “頂帽”(“Top hat”):原圖像與開操作之間的差值圖像(可以用來觀察開運算除去了哪些小目標)
	//MORPH_BLACKHAT - “黑帽”(“Black hat“):閉操作圖像與源圖像的差值圖像(可以觀察閉運算的效果)
	//第四個參數:結構元素即形態學運算的內核
	//第五個參數,Point類型的anchor,錨的位置,其有默認值( - 1, - 1),表示錨位於中心。
	//第六個參數,int類型的iterations,迭代使用函數的次數,默認值爲1。
	//第七個參數,int類型的borderType,用於推斷圖像外部像素的某種邊界模式。注意它有默認值BORDER_ CONSTANT。
	//第八個參數,const Scalar&類型的borderValue,當邊界爲常數時的邊界值,有默認值morphologyDefaultBorderValue(),一般我們不用去管他。需要用到它時,可以看官方文檔

	imshow(output, dst);

	return;
}

       總之,形態學操作的靈活運用,可以起到消除噪聲,分割出獨立的圖像元素以及在圖像中連接起相鄰的區域。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章