Opencv影象處理——數學形態學操作

2021-02-26 12:01:21

前言

本文講述影象處理的形態學操作


一、數學形態學影象處理基本概念

在這裡插入圖片描述

1.1、數學形態學簡介

       數學形態學(Mathematical morphology) 是一門建立在格論和拓撲學基礎之上的影象分析學科,是數學形態學影象處理的基本理論。其基本的運算包括: 二值腐蝕和膨脹、二值開閉運算、骨架抽取、極限腐蝕、擊中擊不中變換、形態學梯度、Top-hat變換、顆粒分析、流域變換、灰值腐蝕和膨脹、灰值開閉運算、灰值形態學梯度等。

1.2、數學形態學組成

       數學形態學是由一組形態學的代數運運算元組成的,它的基本運算有4個: 膨脹(或擴張)、腐蝕(或侵蝕)、開啟和閉合,它們在二值影象和灰度影象中各有特點。基於這些基本運算還可推導和組合成各種數學形態學實用演演算法,用它們可以進行影象形狀和結構的分析及處理,包括影象分割、特徵抽取、邊緣檢測、 影象濾波、影象增強和恢復等。數學形態學方法利用一個稱作結構元素的「探針」收集影象的資訊,當探針在影象中不斷移動時, 便可考察影象各個部分之間的相互關係,從而瞭解影象的結構特徵。數學形態學基於探測的思想,與人的FOA(Focus Of Attention)的視覺特點有類似之處。作為探針的結構元素,可直接攜帶知識(形態、大小、甚至加入灰度和色度資訊)來探測、研究影象的結構特點。

1.3、數學形態學應用

       數學形態學的基本思想及方法適用於與影象處理有關的各個方面,如基於擊中/擊不中變換的目標識別,基於流域概念的影象分割,基於腐蝕和開運算的骨架抽取及影象編碼壓縮,基於測地距離的影象重建,基於形態學濾波器的顆粒分析等。
數學形態學是一門建立在嚴格數學理論基礎上的學科,其基本思想和方法對影象處理的理論和技術產生了重大影響。事實上,數學形態學已經構成一種新的影象處理方法和理論,成為計算機數位影像處理及分形理論的一個重要研究領域,並且已經應用在多門學科的數位影像分析和處理的過程中。這門學科在計算機文字識別, 計算機顯微影象分析(如定量金相分析,顆粒分析), 醫學影象處理(例如細胞檢測、心臟的運動過程研究、脊椎骨癌影象自動數量描述),影象編碼壓縮,工業檢測(如食品檢驗和印刷電路自動檢測),材料科學, 機器人視覺,汽車運動情況監測等方面都取得了非常成功的應用。另外,數學形態學在指紋檢測、經濟地理、合成音樂和斷層X光照像等領域也有良好的應用前景。形態學方法已成為影象應用領域工程技術人員的必備工具。

二、二值影象

2.1、含義

       二值影象是指每個畫素點均為黑色或者白色的影象。二值影象一般用來描述字元影象,其優點是佔用空間少;缺點是當表示人物,風景的影象時,二值影象只能展示其邊緣資訊,影象內部的紋理特徵表現不明顯。這時候要使用紋理特徵更為豐富的灰度影象。

2.2、二值影象樣例

在這裡插入圖片描述

2.3、影象二值化處理邏輯

       影象的二值化處理是將影象上的點的灰度值為0或255,也就是將整個影象呈現出明顯的黑白效果。即將256個亮度等級的灰度影象通過適當的閾值選取而獲得仍然可以反映影象整體和區域性特徵的二值化影象。在數位影像處理中,要進行二值影象的處理與分析,首先要把灰度影象二值化,得到二值化影象,這樣子有利於在對影象做進一步處理時,影象的集合性質只與畫素值為0或255的點的位置有關,不再涉及畫素的多級值,使處理變得簡單,而且資料的處理和壓縮量小。為了得到理想的二值影象,一般採用封閉、連通的邊界定義不交疊的區域。所有灰度大於或等於閾值的畫素被判定為屬於特定物體,其灰度值為255表示,否則這些畫素點被排除在物體區域以外,灰度值為0,表示背景或者例外的物體區域。


2.4、opencv二值化處理常式

2.4.1、threshold()函數

簡介:對每個陣列元素應用一個固定級別的閾值,手動指定一個閾值,以此閾值來進行二值化處理
函數定義:

double threshold( InputArray src, OutputArray dst, double thresh, double maxval, int type );
/*
src輸入陣列(多通道,8位元或32位元浮點),即影象。
dst輸出陣列的大小和型別與src的通道數相同。
thresh引數閾值。
maxval用於#THRESH_BINARY和#THRESH_BINARY_INV thresholding的最大值型別。
type如果使用大津法或三角形法,則返回計算出的閾值。
*/

2.4.2、adaptiveThreshold()函數

簡介:對陣列應用自適應閾值,通過設定最後兩個引數來調整效果
函數定義:

void adaptiveThreshold( InputArray src, OutputArray dst, double maxValue, 
		int adaptiveMethod, int thresholdType, int blockSize, double C );
/*
src源8位元單通道影象。
dst目標映像與src大小和型別相同的param 
maxValue指定給滿足條件的畫素的非零值
adaptiveMethod自適應閾值演演算法的使用#BORDER_REPLICATE |#BORDER_ISOLATED用於處理邊界。
thresholdType Thresholding type必須是#THRESH_BINARY或#THRESH_BINARY_INV,
blockSize用於計算閾值的畫素鄰域的大小畫素:3、5、7等等。
引數C常數從平均值或加權平均值中減去。正常情況下為正,但也可能為零或負。
*/

三、Opencv影象基本二值運算

3.1、腐蝕操作:erode()函數

簡介:使用指定的結構元素來腐蝕源影象,該結構元素決定取最小值的畫素鄰域的形狀
定義:

void erode( InputArray src, OutputArray dst, InputArray kernel, Point anchor = Point(-1,-1), int iterations = 1,
            int borderType = BORDER_CONSTANT,  const Scalar& borderValue = morphologyDefaultBorderValue() );
/*
src:為輸入影象物件通道數可以是任意的,但深度應該是CV_8U、CV_16U、CV_16S、CV_32F或CV_64F。
dst:輸出與src大小和型別相同的影象。
kernel:用於擴充套件的核心結構元素;如果elemenat=Mat(),則為3 x 3矩形使用結構元素。
anchor:可以使用#getStructuringElement建立核心anchor元素中錨點的位置;預設值(-1,-1)表示錨點位於元素中心。
iterations:迭代次數應用腐蝕。
borderType:畫素外推方法,不支援邊框環繞。
borderValue:如果是常數border,則為border值
*/

3.2、膨脹操作:dilate()函數

簡介:使用指定的結構元素來擴充套件源影象,該結構元素確定取最大值的畫素鄰域的形狀
定義:

void dilate( InputArray src, OutputArray dst, InputArray kernel, Point anchor = Point(-1,-1), int iterations = 1,
             int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue() );
/*
src:為輸入影象物件通道數可以是任意的,但深度應該是CV_8U、CV_16U、CV_16S、CV_32F或CV_64F。
dst:輸出與src大小和型別相同的影象。
kernel:用於擴充套件的核心結構元素;如果elemenat=Mat(),則為3 x 3矩形使用結構元素。
anchor:可以使用#getStructuringElement建立核心anchor元素中錨點的位置;預設值(-1,-1)表示錨點位於元素中心。
iterations 迭代應用擴充套件的次數。
borderType:畫素外推方法,不支援邊框環繞。
borderValue:如果是常數border,則為border值
*/

3.3、morphologyEx()函數

簡介:morphologyEx可以使用侵蝕和擴張來執行高階形態轉換基本操作。任何操作都可以在原地完成。在多通道影象的情況下,每個通道獨立處理。
定義:

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() );
/*
src:源影象。通道的數量可以是任意的。深度應該是CV_8U、CV_16U、CV_16S、CV_32F或CV_64F。
dst:目標映像的大小和型別與源映像相同。
Type:形態學運算的型別,請參見#MorphTypes
kernel:核心結構元素。可以使用#getStructuringElement建立它。
anchor :錨定與核心的錨定位置。負值表示錨點位於核心中心。
iterations :迭代應用腐蝕和膨脹的次數。
borderType:畫素外推方法,請參見#BorderTypes。#不支援邊框自動換行。
borderValue:如果是常數Border,則為Border值。預設值具有特殊的意思。
迭代次數是應用侵蝕或膨脹操作的次數。
例如,具有兩次迭代的開啟操作(#MORPH_OPEN)等價於apply
*/

3.3.1、開操作:MORPH_OPEN

先腐蝕後膨脹的操作。
作用:消除細小物體,在纖細處分離物體和平滑較大物體邊界。

3.3.2、閉操作:MORPH_CLOSE

先膨脹後腐蝕的操作。
作用:填充物體內細小空洞,連線鄰近物體和平滑邊界。

3.3.3、梯度運算:MORPH_GRADIENT

對二值影象進行這一操作可以將團塊的邊緣突出來。
作用:形態學梯度來保留物體的邊緣輪廓

3.3.4、頂帽操作:MORPH_TOPHAT

從原圖中減去開運算後的圖,得到的效果圖突出了比原型輪廓周圍的區域更明亮的區域
作用:分離比鄰近點亮一些的斑塊

3.3.5、黑帽操作:MORPH_BLACKHAT

突出了比原圖輪廓周圍的區域更暗的區域
作用:分離比鄰近點暗一些的斑塊

3.4、 getStructuringElement()函數

簡介:返回用於形態學操作的指定大小和形狀的結構元素
作用:我們一般利用這個函數來配合前面各個函數定義中的引數kernel來使用,構造一個符合的結構元素
定義:

Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));
/*
shape:元素可以是#MorphShapes之一的形狀
ksize:結構元素的大小。
anchor:錨定元素內的錨定位置。預設值\f$(-1,-1)\f$表示錨在中間。只有十字形元素的形狀取決於錨點位置。在其他情況下,錨定只會調節結果的大小操作轉移。
*/

3.5、createTrackbar()函數

簡介:函數createTrackbar建立具有指定名稱的軌跡欄(滾軸或範圍控制元件)和範圍,將變數值指定為與軌跡欄同步的位置,並指定要在軌跡欄位置更改時呼叫的回撥函數onChange。建立的軌跡欄是顯示在指定的視窗中。
定義:

int createTrackbar(const String& trackbarname, const String& winname, int* value, 
					int count,TrackbarCallback onChange = 0,void* userdata = 0);
/*
trackbarname:建立的軌跡欄的名稱。
winname:將用作所建立軌跡欄父級的視窗的名稱。
value:指向整數變數的可選指標,該整數變數的值反映滾軸。建立時,滾軸位置由該變數定義。
count:滾軸的最大位置。最小位置總是0。
onChange:指向每次滾軸改變位置時要呼叫的函數的指標。這個函數的原型應該是void Foo(int,void\*);其中第一個引數是trackbar位置,第二個引數是使用者資料(見下一個引數)。如果回撥是空指標,不呼叫回撥,但只更新值。
userdata:按原樣傳遞給回撥的使用者資料。它可以用來處理軌跡欄不使用全域性變數的事件。
*/ 

3.6、形態學操作型別列舉:

enum MorphTypes{
    MORPH_ERODE    = 0, //!< see #erode
    MORPH_DILATE   = 1, //!< see #dilate
    MORPH_OPEN     = 2, //!< an opening operation
    MORPH_CLOSE    = 3, //!< a closing operation
    MORPH_GRADIENT = 4, //!< a morphological gradient
    MORPH_TOPHAT   = 5, //!< "top hat"
    MORPH_BLACKHAT = 6, //!< "black hat"
    MORPH_HITMISS  = 7  //!< "hit or miss"
};

四、程式碼演示:

4.1、腐蝕與膨脹

程式碼塊

//腐蝕與膨脹
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;

Mat src, dst;
int element_size = 2;
int max_size = 20;
void CallBack_Demo(int, void*) {
	int s = element_size * 2 + 1;
	Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));
	dilate(src, dst, structureElement, Point(-1, -1));//膨脹
	
	//erode(src, dst, structureElement);//腐蝕
	imshow("output_image", dst);
}
int main() {
	src = imread("D:\\Myfile\\素材照片\\opencv素材照片\\4.jpg");
	if (!src.data) {
		cout << "could not load image..." << endl;
		return 0;
	}
	namedWindow("input_image", WINDOW_AUTOSIZE);
	imshow("input_image", src);
	namedWindow("output_image", WINDOW_AUTOSIZE);
	createTrackbar("Element Size :", "output_image", &element_size, max_size, CallBack_Demo);
	CallBack_Demo(0, 0);
	imshow("output_image", dst);

	waitKey(0);
	return 0;
}

執行結果:
在這裡插入圖片描述

4.2、開、閉、梯度、頂帽、黑帽等操作

程式碼塊:

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

using namespace std;
using namespace cv;
int main() {
	Mat src, dst;
	src = imread("D:\\Myfile\\素材照片\\opencv素材照片\\11.jpg");
	if (!src.data) {
		cout << "could not load image..." << endl;
		return 0;
	}
	namedWindow("input_image", WINDOW_AUTOSIZE);
	imshow("input_image", src);
	
	//Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));//結構元素
	//morphologyEx(src, dst, MORPH_OPEN, kernel);//開操作,先腐蝕後膨脹
	//morphologyEx(src, dst, MORPH_CLOSE, kernel);//閉操作,先膨脹後腐蝕

	//梯度:膨脹減去腐蝕,基本梯度(內部梯度,方向梯度)
	//morphologyEx(src, dst, MORPH_GRADIENT, kernel);

	//頂帽 原影象和開操作影象
	//morphologyEx(src, dst, MORPH_TOPHAT, kernel);

	//黑帽 原影象和閉操作影象
	//morphologyEx(src, dst, MORPH_BLACKHAT, kernel);

	//提取水平和垂直線
	cvtColor(src, dst, COLOR_BGR2GRAY);
	Mat Bin_dst;
	adaptiveThreshold(dst, Bin_dst, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);//二值化影象
	Mat hline = getStructuringElement(MORPH_RECT, Size(src.cols / 16, 1), Point(-1, -1));
	Mat vline = getStructuringElement(MORPH_RECT, Size(1, src.rows / 16), Point(-1, -1));
	Mat kernels = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
	//Mat temp;
	//erode(Bin_dst, temp, kernels);
	//dilate(temp, dst, kernels);
	morphologyEx(Bin_dst, dst, MORPH_OPEN, hline);
	bitwise_not(dst, dst);
	blur(dst, dst, Size(3, 3), Point(-1, -1));
	namedWindow("output_image", WINDOW_AUTOSIZE);
	imshow("output_image", dst);
	waitKey(0);
	return 0;
}

執行結果:
在這裡插入圖片描述

總結

本文講述數學形態學操作:腐蝕、膨脹、開、閉、梯度、頂帽、黑帽

參考來源

如有疑問,請留言!
如有錯誤,敬請指正!