對分水嶺算法程序的理解(詳細註釋)

#include “opencv2/opencv.hpp”
#include “vector”
using namespace cv;
using namespace std;

void main()
{
Mat SrcImage = imread(“2.png”,2|4);
//imshow("【原圖】",SrcImage);
Mat GrayImage,EdgeImage;
cvtColor(SrcImage,GrayImage,COLOR_BGR2GRAY);
GaussianBlur(GrayImage,GrayImage,Size(5,5),0,0);//,Size(5,5)高斯內核大小
//imshow("【經高斯濾波後的灰度圖】",GrayImage);
Canny(GrayImage,EdgeImage,270,400,3);
//imshow("【邊緣二值圖】",EdgeImage);

vector<vector<Point>>  contours;
vector<Vec4i> hierarchy;
findContours(EdgeImage,contours,hierarchy,RETR_CCOMP,CHAIN_APPROX_SIMPLE,Point(0,0));//Point(0,0)爲每個輪廓的偏移量

Mat mark(EdgeImage.size(),CV_32SC1);//使用watershed()函數時,第二個參數要求爲32位單通道,之所以爲CV_32SC1,是因爲int index = mark.at<int>(i,j);
mark = Scalar::all(0);
Mat markImage = Mat::zeros(EdgeImage.size(),CV_8UC3);
int index=0,compCount=0;
for (;index>=0;index=hierarchy[index][0],compCount++)
{
	drawContours(mark,contours,index,Scalar::all(compCount+1),1,8,hierarchy);//繪製頂層輪廓
	drawContours(markImage,contours,index,Scalar::all(255),1,8,hierarchy);
}
imshow("傳入mark的沒有標記圖像",markImage);
convertScaleAbs(mark,markImage);
imshow("傳入mark的標記圖像",markImage);

//生成隨機顏色
vector<Vec3b> colorTab; //typedef Vec<uchar, 3> Vec3b;
for( int i = 0; i < compCount; i++ ) //compCount代表輪廓數(注水種子),就有多少個種子,圖像最後分割後就有多少個區域,就產生多少顏色。
{
	int b = theRNG().uniform(0, 255);//uniform(0, 255)傳回的是int型
	int g = theRNG().uniform(0, 255);
	int r = theRNG().uniform(0, 255);

	colorTab.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
}

Mat AfterWatershedImage;
watershed(SrcImage,mark);//使用watershed()函數時,第二個參數要求爲32位
convertScaleAbs(mark,AfterWatershedImage);
imshow("分水嶺算法處理過後的圖像",AfterWatershedImage);

Mat PerspectiveImage = Mat::zeros(mark.size(), CV_8UC3);//而分水嶺方法完成之後並不會直接生成分割後的圖像,還需要進一步的顯示處理
for (int i=0;i<mark.cols;i++)
{
	for(int j=0;j<mark.rows;j++)
	{
		int index = mark.at<int>(i,j);//mark的類型爲CV_32SC1,就是灰度圖
		if (index == -1) //區域與區域之間的分界處的值被置爲“-1”,以做區分。
			PerspectiveImage.at<Vec3b>(i,j) = Vec3b(255,255,255);
		else if( index <= 0 || index > compCount )//未被標記區域被置爲0
			PerspectiveImage.at<Vec3b>(i,j) = Vec3b(0,0,0);
		else//被標記的區域(0,compCount]
			PerspectiveImage.at<Vec3b>(i,j) = colorTab[index-1];//經過分水嶺後的圖像爲集水盆圖像,圖像不同區域有一樣的顏色,而這些顏色是由畫注水種子的輪廓時給定的,
	}                                                           //如果index一樣,代表爲同一塊區域內,經過這條程序就被標記爲同一種顏色
}	
imshow("After ColorFill",PerspectiveImage);

Mat wshed;
addWeighted(SrcImage,0.3,PerspectiveImage,0.7,0,wshed);
imshow("經過整合的圖像",wshed);

waitKey(0);

}

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