分水岭算法

/*分割目标
图像传给函数之前需要大致勾画标记出图像中的期望进行分割的区域,被标记为正指数

Void watershed(inputarray image,//输出图像 八位三通道彩色
	Inputoutputarray markers//计算结果
	)
	
	*/
	
	
#include <opencv2//highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;

//*********************************
//		分水岭算法
//*********************************

#define WINDOW_NAME "【程序窗口】"

Mat g_maskImage, g_srcImage;
Point prevPt(-1, -1);

static void ShowHelpText();
static void on_Mouse(int event, int x, int y, int flags, void*);

int main()
{
	//载入图片,初始化掩膜和灰度
	g_srcImage = imread("C:/Users/hasee-pc/Desktop/girl.jpg", 1);
	imshow(WINDOW_NAME, g_srcImage);
	Mat srcImage, grayImage;
	g_srcImage.copyTo(srcImage);
	cvtColor(g_srcImage, g_maskImage, COLOR_BGR2GRAY);
	cvtColor(g_maskImage, grayImage, COLOR_GRAY2BGR);
	g_maskImage = Scalar::all(0);

	//鼠标回调函数
	setMouseCallback(WINDOW_NAME, on_Mouse, 0);

	while (1)
	{
		int c = waitKey(0);
		if ((char)c == 27)//esc
			break;
		if ((char)c == '2')//恢复原图
		{
			g_maskImage = Scalar::all(0);
			srcImage.copyTo(g_srcImage);
			imshow("image", g_srcImage);
		}
		if ((char) c== '1' || (char)c == ' ')
		{
			int i, j, compCount = 0;
			vector<vector<Point> > contours;
			vector<Vec4i> hierarchy;

			//寻找轮廓
			findContours(g_maskImage,
				contours,
				hierarchy,
				CV_RETR_CCOMP,
				CV_CHAIN_APPROX_SIMPLE
			);
			//轮廓为空处理
			if (contours.empty())
				continue;
			//复制掩膜
			Mat maskImage(g_maskImage.size(), CV_32S);
			maskImage = Scalar::all(0);

			//绘制轮廓
			for (int index = 0; index >= 0; index = hierarchy[index][0], compCount++)
			{
				drawContours(
					maskImage,
					contours,
					index,
					Scalar::all(compCount + 1),
					-1,
					8,
					hierarchy,
					INT_MAX
				);
			}
			//compCount为0处理
			if (compCount == 0)
				continue;

			//随机颜色
			vector<Vec3b> colorTab;
			for (int i = 0; i < compCount; ++i)
			{
				int b = theRNG().uniform(0, 255);
				int g = theRNG().uniform(0, 255);
				int r = theRNG().uniform(0, 255);

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

			//计算处理时间
			double dTime = (double)getTickCount();
			watershed(srcImage, maskImage);
			dTime = (double)getTickCount() - dTime;
			printf("\t 处理时间 = %gms\n", dTime*1000. / getTickCount());

			//分水岭图片遍历存入watershedImage中
			Mat watershedImage(maskImage.size(), CV_8UC3);
			for (i = 0; i < maskImage.rows; ++i)
			{
				for (j = 0; j < maskImage.cols; ++j)
				{
					int index = maskImage.at<int>(i, j);
					if (index == -1)
						watershedImage.at<Vec3b>(i, j) = Vec3b(255, 255, 255);
					else if (index <= 0 || index > compCount)
						watershedImage.at<Vec3b>(i, j) = Vec3b(0, 0, 0);
					else
						watershedImage.at<Vec3b>(i, j) = colorTab[index - 1];
				}
			}

			//混合灰度图和分水岭显示最终窗口
			watershedImage = watershedImage * 0.5 + grayImage * 0.5;
			imshow("watershed transform", watershedImage);
		}
	}

	waitKey(0);
}

static void on_Mouse(int event, int x, int y, int flags, void *)
{
	//鼠标不在窗口情况
	if (x < 0 || x >= g_srcImage.cols || y < 0 || y >= g_srcImage.rows)
		return;
	if (event == EVENT_LBUTTONUP || !(flags&EVENT_FLAG_LBUTTON))//鼠标左键
		prevPt = Point(-1, -1);
	else if (event == EVENT_LBUTTONDOWN)
		prevPt = Point(x, y);
	else if (event == EVENT_MOUSEMOVE && (flags&EVENT_FLAG_LBUTTON))//左键按下并且移动 绘制白线
	{
		Point pt(x, y);
		if (prevPt.x < 0)
			prevPt = pt;
		line(g_maskImage,
			prevPt,
			pt,
			Scalar::all(255),
			5,
			8,
			0
		);

		line(g_srcImage,
			prevPt,
			pt,
			Scalar::all(255),
			5,
			8,
			0
		);
		prevPt = pt;
		imshow(WINDOW_NAME, g_srcImage);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值