opencv分水嶺算法對圖像進行切割


先看效果


說明

使用分水嶺算法對圖像進行切割,設置一個標記圖像能達到比較好的效果,還能防止過度切割。

1、這里首先對閾值化的二值圖像進行腐蝕,去掉小的白色區域,得到圖像的前景區域。並對前景區域用255白色標記
2、相同對閾值化后的圖像進行膨脹,然后再閾值化並取反。得到背景區域。

並用128灰度表示

3、將前景和背景疊加在一起在同一幅圖像中顯示。
4、用標記圖和原圖,利用opencv的watershed對圖像進行切割。

源代碼
class WatershedSegment{
private:
	cv::Mat markers;
public:
	void setMarkers(const cv::Mat &image){
		image.convertTo(markers,CV_32S);
	}

	cv::Mat process(const cv::Mat &image) {

		// Apply watershed
		cv::watershed(image,markers);
		markers.convertTo(markers,CV_8U);
		return markers;
	}
};
int _tmain(int argc, _TCHAR* argv[])
{
	cv::Mat image = cv::imread("group.jpg");
	cv::Mat binary = cv::imread("binary.bmp",0);  //沒加0害得我找好久錯誤的原因。即使"binary.bmp"為二值圖像不加0讀進來還是3通道
	//cv::threshold(image,binary,60,255,CV_THRESH_BINARY);  //閾值化操作
	//binary = 255 - binary; //讓前景變為白色區域
	cv::namedWindow("binary",CV_WINDOW_AUTOSIZE);
	cv::imshow("binary",binary);

	cv::Mat fImage;
	cv::erode(binary,fImage,cv::Mat(),cv::Point(-1,-1),6); //binary = 255 - binary; //讓前景變為白色區域//腐蝕去掉小的干擾物體得到前景圖像
	cv::namedWindow("eroded",CV_WINDOW_AUTOSIZE);
	cv::imshow("eroded",fImage);

	cv::Mat bImage;
	cv::dilate(binary,bImage,cv::Mat(),cv::Point(-1,-1),6);
	cv::threshold(bImage,bImage,1,128,cv::THRESH_BINARY_INV);//對原始二值圖像閾值化並取反,得到背景圖像
	cv::namedWindow("bImage",CV_WINDOW_AUTOSIZE);
	cv::imshow("bImage",bImage);

	cv::Mat marker(binary.size(),CV_8U,cv::Scalar(0));
	marker = fImage + bImage;  //創建標記圖像
	cv::namedWindow("marker",CV_WINDOW_AUTOSIZE);
	cv::imshow("marker",marker);

	WatershedSegment segmenter;
	segmenter.setMarkers(marker);
	cv::Mat segment = segmenter.process(image);
	cv::namedWindow("segmenter",CV_WINDOW_AUTOSIZE);
	cv::imshow("segmenter",segment);
	cv::waitKey(0);
	return 0;
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM