天天看點

opencv4 c++ 提取圖檔中的白色區域_【從零學習OpenCV 4】圖像矩的計算與應用

點選上方“ 小白學視覺 ”,選擇“ 星标 ”公衆号 重磅幹貨,第一時間送達

經過幾個月的努力,小白終于完成了市面上第一本OpenCV 4入門書籍《從零學習OpenCV 4》。為了更讓小夥伴更早的了解最新版的OpenCV 4,小白與出版社溝通,提前在公衆号上連載部分内容,請持續關注小白。

矩是描述圖像特征的算子,被廣泛用于圖像檢索和識别、圖像比對、圖像重建、圖像壓縮以及運動圖像序列分析等領域。本節中将介紹幾何矩與Hu矩的計算方法以及應用Hu矩實作圖像輪廓的比對。

幾何矩與中心矩

圖像幾何矩的計算方式如式(7.8)所示:

opencv4 c++ 提取圖檔中的白色區域_【從零學習OpenCV 4】圖像矩的計算與應用

其中是像素處的像素值。當x和y同時取值0時稱為零階矩,零階矩可以用于計算某個形狀的質心,當x和y分别取值0和1時被稱為一階矩,以此類推。圖像質心的計算公式如(7.9)所示:

opencv4 c++ 提取圖檔中的白色區域_【從零學習OpenCV 4】圖像矩的計算與應用

圖像中心距計算方式如式(7.10)所示:

opencv4 c++ 提取圖檔中的白色區域_【從零學習OpenCV 4】圖像矩的計算與應用

圖像歸一化幾何矩計算方式如式所示:

opencv4 c++ 提取圖檔中的白色區域_【從零學習OpenCV 4】圖像矩的計算與應用

OpenCV 4提供了計算圖像矩的moments()函數,該函數的函數原型在代碼清單7-28中給出。

代碼清單7-28 moments()函數原型Moments cv::moments(InputArray  array,                    bool  binaryImage = false                     )
           
  • array:計算矩的區域2D像素坐标集合或者單通道的CV_8U圖像
  • binaryImage:是否将所有非0像素值視為1的标志。

該函數用于計算圖像連通域的幾何矩和中心距以及歸一化的幾何矩。函數第一個參數是待計算矩的輸入圖像或者2D坐标集合。函數第二個參數為是否将所有非0像素值視為1的标志,該标志隻在第一個參數輸入為圖像類型的資料時才會有作用。函數會傳回一個Moments類的變量,Moments類中含有幾何矩、中心距以及歸一化的幾何矩的數值屬性,例如Moments.m00是零階矩,Moments.m01和Moments.m10是一階矩。Moments類中所有的屬性在表7-5給出。

表7-5 Moments類的屬性

種類 屬性
spatial moments m00、m10、m01、m20、m11、m02、m30、m21、m12、m03
central moments mu20、mu11、mu02、mu30、mu21、mu12、mu03
central normalized moments nu20、nu11、nu02、nu30、nu21、nu12、nu03

為了了解函數的使用方法,在代碼清單7-29中給出了計算圖像矩和讀取每一種矩數值方法的示例程式,程式的部分運作結果如圖7-24所示。

代碼清單7-29 myMoments.cpp計算圖像的矩#include #include #include using namespace cv;using namespace std;int main(){	Mat img = imread("approx.png");	// 二值化	Mat gray, binary;	cvtColor(img, gray, COLOR_BGR2GRAY);	threshold(gray, binary, 105, 255, THRESH_BINARY);	//開運算消除細小區域	Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));	morphologyEx(binary, binary, MORPH_OPEN, k);	// 輪廓發現	vector> contours;	vector hierarchy;	findContours(binary, contours, hierarchy, 0, 2, Point());	for (int n = 0; n < contours.size(); n++) 	{		Moments M;		M = moments(contours[n], true);		cout << "spatial moments:" << endl			<< "m00:" << M.m00 << " m01:" << M.m01 << " m10:" << M.m10 << endl			<< "m11:" << M.m11 << " m02:" << M.m02 << " m20:" << M.m20 << endl			<< "m12:" << M.m12 << " m21:" << M.m21 << " m03:" << M.m03 << " m30:"<< M.m30 << endl;		cout << "central moments:" << endl			<< "mu20:" << M.mu20 << " mu02:" << M.mu02 << " mu11:" << M.mu11 << endl			<< "mu30:" << M.mu30 << " mu21:" << M.mu21 << " mu12:" << M.mu12 << " mu03:" << M.mu03 << endl;		cout << "central normalized moments:" << endl			<< "nu20:" << M.nu20 << " nu02:" << M.nu02 << " nu11:" << M.nu11 << endl			<< "nu30:" << M.nu30 << " nu21:" << M.nu21 << " nu12:" << M.nu12 << " nu03:" << M.nu03 << endl;	}	return 0;}
           
opencv4 c++ 提取圖檔中的白色區域_【從零學習OpenCV 4】圖像矩的計算與應用

圖7-24 myMoments.cpp程式部分運作結果

Hu矩

Hu矩具有旋轉、平移和縮放不變性,是以在圖像具有旋轉和放縮的情況下Hu矩具有更廣泛的應用領域。Hu矩是由二階和三階中心距計算得到七個不變矩,具體計算公式如式(7.12)所示:

opencv4 c++ 提取圖檔中的白色區域_【從零學習OpenCV 4】圖像矩的計算與應用

OpenCV 4提供了用于計算Hu矩的HuMoments()函數,根據參數類型的不同該函數具有兩種原型。在代碼清單7-30中給出這兩種函數原型。

代碼清單7-30 HuMoments()函數原型void cv::HuMoments(const Moments &  moments,                   double  hu[7]                    )	void cv::HuMoments(const Moments &  m,                   OutputArray  hu                    )
           
  • moments:輸入的圖像矩
  • hu[7]:輸出Hu矩的七個值
  • m:輸入的圖像矩
  • hu:輸出Hu矩的矩陣

該函數可以根據圖像的中心距計算圖像的Hu矩。兩個函數原型隻有第二個參數的資料類型不同,第一個參數是輸入圖的Moments類的圖像矩,第二個參數是輸出的Hu矩,第一種函數原型輸出值存放在長度為7的double類型數組中,第二種函數原型輸出值為Mat類型。

為了了解函數的使用方法,在代碼清單7-31中給出了計算圖像Hu的示例程式,程式的部分運作結果如圖7-25所示。

代碼清單7-31 myHuMoments.cpp計算圖像的Hu矩#include #include #include using namespace cv;using namespace std;int main(){	system("color F0");  //更改輸出界面顔色	Mat img = imread("approx.png");	if (img.empty())	{		cout << "請确認圖像檔案名稱是否正确" << endl;		return -1;	}	// 二值化	Mat gray, binary;	cvtColor(img, gray, COLOR_BGR2GRAY);	threshold(gray, binary, 105, 255, THRESH_BINARY);	//開運算消除細小區域	Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));	morphologyEx(binary, binary, MORPH_OPEN, k);	// 輪廓發現	vector> contours;	vector hierarchy;	findContours(binary, contours, hierarchy, 0, 2, Point());	for (int n = 0; n < contours.size(); n++)	{		Moments M;		M = moments(contours[n], true);		Mat hu;		HuMoments(M, hu);  //計算Hu矩		cout << hu << endl;	}	return 0;}
           
opencv4 c++ 提取圖檔中的白色區域_【從零學習OpenCV 4】圖像矩的計算與應用

圖7-25 myHuMoments.cpp程式部分運作結果

基于Hu矩的輪廓比對

Hu矩具有旋轉、平移和比例不變性,是以可以通過Hu實作圖像輪廓的比對。OpenCV 4提供了利用Hu矩進行輪廓比對的matchShapes()函數,該函數的函數原型在代碼清單7-32中給出。

代碼清單7-32 matchShapes()函數原型double cv::matchShapes(InputArray  contour1,                       InputArray  contour2,                       int  method,                       double  parameter                        )
           
  • contour1:原灰階圖像或者輪廓
  • contour2:模闆圖像或者輪廓
  • method:比對方法的标志,可以選擇的參數及含義在表7-6給出。
  • parameter:特定于方法的參數(現在不支援)

該函數用于實作在圖像或者輪廓中尋找與模闆圖像或者輪廓像素比對的區域。函數的第一個參數是原灰階圖像或者輪廓,第二個參數是模闆圖像或者輪廓。函數第三個參數是兩個輪廓Hu矩比對的計算方法标志,可以選擇的參數和每種方法相似性計算公式在表7-6給出。函數最後一個參數在目前的OpenCV 4版本中沒有意義,可以将參數設定為0。

表7-6 matchShapes()函數中比對方法的标志

标志參數 簡記 原理
CONTOURS_MATCH_I1 1
CONTOURS_MATCH_I2 2
CONTOURS_MATCH_I3 3

為了了解函數的用法,在代碼清單7-33中給出了利用Hu矩實作模闆與原圖像或者輪廓之間比對的示例程式。程式中原圖像有三個字母,模闆圖像有一個字母,并且模闆圖像中字母的尺寸小于原圖像中字母的尺寸。通過對兩張圖像提取輪廓并計算每個輪廓的Hu矩,之後尋找原圖像和模闆圖像中Hu矩最相似的兩個輪廓,并在原圖像中繪制出相似輪廓,程式運作結果在圖7-26給出。

代碼清單7-33 myMatchShapes.cpp基于Hu矩的輪廓比對#include #include #include using namespace cv;using namespace std;void findcontours(Mat &image, vector> &contours){	Mat gray, binary;	vector hierarchy;	//圖像灰階化	cvtColor(image, gray, COLOR_BGR2GRAY);	//圖像二值化	threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);	//尋找輪廓	findContours(binary, contours, hierarchy, 0, 2);}int main(){	Mat img = imread("ABC.png");	Mat img_B = imread("B.png");	if (img.empty() || img_B.empty())	{		cout << "請确認圖像檔案名稱是否正确" << endl;		return -1;	}	resize(img_B, img_B, Size(), 0.5, 0.5);	imwrite("B.png", img_B);	imshow("B", img_B);	// 輪廓提取	vector> contours1;	vector> contours2;	findcontours(img, contours1);	findcontours(img_B, contours2);	// hu矩計算	Moments mm2 = moments(contours2[0]);	Mat hu2;	HuMoments(mm2, hu2);	// 輪廓比對	for (int n = 0; n < contours1.size(); n++)	{		Moments mm = moments(contours1[n]);		Mat hum;		HuMoments(mm, hum);		//Hu矩比對		double dist;		dist = matchShapes(hum, hu2, CONTOURS_MATCH_I1, 0);		if (dist < 1)		{			drawContours(img, contours1, n, Scalar(0, 0, 255), 3, 8);		}	}	imshow("match result", img);	waitKey(0);	return 0;}
           
opencv4 c++ 提取圖檔中的白色區域_【從零學習OpenCV 4】圖像矩的計算與應用

圖7-26 myMatchShapes.cpp程式運作結果 從零學習OpenCV 4往期推薦

【從零學習OpenCV 4】Windows系統中安裝OpenCV 4

【從零學習OpenCV 4】Ubuntu系統中安裝OpenCV 4

【從零學習OpenCV 4】opencv_contrib擴充子產品的安裝

【從零學習OpenCV 4】Mat類介紹

【從零學習OpenCV 4】Mat類構造與指派

【從零學習OpenCV 4】Mat類支援的運算

【從零學習OpenCV 4】這4種讀取Mat類元素的的方法你都知道麼?

【從零學習OpenCV 4】namedWindow函數&imshow函數的使用

【從零學習OpenCV 4】顔色模型與轉換

【從零學習OpenCV 4】多通道分離與合并

【從零學習OpenCV 4】圖像像素統計

【從零學習OpenCV 4】兩圖像間的像素操作

【從零學習OpenCV 4】圖像二值化

【從零學習OpenCV 4】LUT查找表

【從零學習OpenCV 4】圖像仿射變換

【從零學習OpenCV 4】圖像透視變換

【從零學習OpenCV 4】極坐标變換

【從零學習OpenCV 4】繪制幾何圖形

【從零學習OpenCV 4】圖像金字塔

【從零學習OpenCV 4】建立圖像視窗滑動條

【從零學習OpenCV 4】滑鼠響應

【從零學習OpenCV 4】圖像直方圖繪制

【從零學習OpenCV 4】直方圖歸一化

【從零學習OpenCV 4】直方圖比較

【從零學習OpenCV 4】直方圖均衡化

【從零學習OpenCV 4】直方圖比對

【從零學習OpenCV 4】圖像卷積

【從零學習OpenCV 4】圖像中添加椒鹽噪聲

【從零學習OpenCV 4】圖像中添加高斯噪聲

【從零學習OpenCV 4】均值濾波

【從零學習OpenCV 4】方框濾波

【從零學習OpenCV 4】高斯濾波

【從零學習OpenCV 4】雙邊濾波

【從零學習OpenCV 4】邊緣檢測原理

【從零學習OpenCV 4】Sobel算子 

【從零學習OpenCV 4】Scharr算子

【從零學習OpenCV 4】Laplacian算子

【從零學習OpenCV 4】Canny算法

【從零學習OpenCV 4】圖像距離變換

【OpenCV 4開發詳解】圖像連通域分析

……

經過幾個月的努力,市面上第一本OpenCV 4入門書籍《從零學習OpenCV 4》将春節後由人民郵電出版社發行。如果小夥伴覺得内容有幫助,希望到時候多多支援!
關注小白的小夥伴可以提前看到書中的内容,我們建立了學習交流群,歡迎各位小夥伴添加小白微信加入交流群,添加小白時請備注“學習OpenCV 4”。
opencv4 c++ 提取圖檔中的白色區域_【從零學習OpenCV 4】圖像矩的計算與應用
opencv4 c++ 提取圖檔中的白色區域_【從零學習OpenCV 4】圖像矩的計算與應用

繼續閱讀