openCV 分水岭

本文介绍了一个使用OpenCV实现的分水岭算法实战案例,通过鼠标绘制区域选择,自动进行图像分割,展示了从图像读取到最终效果展示的完整过程。代码中详细解释了如何利用分水岭算法进行图像处理,包括轮廓检测、颜色映射和图像混合等关键步骤。
摘要由CSDN通过智能技术生成
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
#define WINDOW_NAME1 "srcImg"
#define WINDOW_NAME2 "dstImg"

static void on_Mouse(int event, int x, int y, int flags, void*);
Mat srcImg, dstImg, tmpImg1, tmpImg2,maskImg;
Point prevPoint(-1, -1);


int main()
{
	/*载入原图,初始化掩模和灰度图*/
	srcImg = imread("test2.jpg");
	namedWindow(WINDOW_NAME1);
	namedWindow(WINDOW_NAME2);
	imshow(WINDOW_NAME1,srcImg);
	tmpImg1 = srcImg.clone();
	cvtColor(srcImg, maskImg, COLOR_BGR2GRAY);
	cvtColor(maskImg, tmpImg2, COLOR_GRAY2BGR);
	maskImg = Scalar::all(0);
	/*设置鼠标回调函数*/
	setMouseCallback(WINDOW_NAME1, on_Mouse, 0);
	/*询问按键进行处理*/
	while (1) {
		/*获取键值*/
		int c = waitKey(0);
		//c = (char)c;
		if ((char)c == 27) break;//esc退出
		if ((char)c == '2') {
			maskImg = Scalar::all(0);
			srcImg = tmpImg1.clone();
			imshow(WINDOW_NAME1, srcImg);//
		}
		if ((char)c == '1' || (char)c == ' ') {
			/*定义一些参数进行图像处理*/
			int i, j, compCount = 0;
			vector<vector<Point>> contoursExp;
			vector<Vec4i> hierarchyExp;
			/*寻找轮廓*/
			findContours(maskImg, contoursExp,hierarchyExp,RETR_CCOMP,CHAIN_APPROX_SIMPLE);
			if (contoursExp.empty()) continue;//如果轮廓为空,继续下一次循环运算
			Mat maskImg2(maskImg.size(), CV_32S);//复制掩模
			maskImg2 = Scalar::all(0);
			/*循环绘制轮廓*/
			for (int i = 0; i >= 0; i = hierarchyExp[i][0], compCount++) {
				drawContours(maskImg2, contoursExp, i, Scalar::all(compCount + 1), -1, 8, hierarchyExp, INT_MAX);
			}
			if (compCount == 0) continue;
			/*生成随机颜色*/
			vector<Vec3b> colorTab;
			for (i = 0; i < compCount; i++) {
				uchar b = theRNG().uniform(0, 255);
				uchar g = theRNG().uniform(0, 255);
				uchar r = theRNG().uniform(0, 255);
				colorTab.push_back(Vec3b(b,g,r));
			}
			/*计算处理时间*/
			double dTime = (double)getTickCount();
			watershed(srcImg, maskImg2);
			dTime = (double)getTickCount() - dTime;
			printf("\t处理时间=%gms\n", dTime*1000. / getTickFrequency());
			/*将分水岭图像遍历存入watershedImg*/
			Mat watershedImg(maskImg2.size(), CV_8UC3);
			for (i = 0; i < maskImg2.rows; i++) {
				for (j = 0; j < maskImg2.cols; j++) {
					int index = maskImg2.at<int>(i, j);
					if (index == -1) watershedImg.at<Vec3b>(i, j) = Vec3b(255, 255, 255);
					else if (index <= 0 || index > compCount) watershedImg.at<Vec3b>(i, j) = Vec3b(0, 0, 0);//
					else watershedImg.at<Vec3b>(i, j) = colorTab[index - 1];
				}
			}
				/*混合灰度图和分水岭效果图并显示*/
			watershedImg = watershedImg * 0.5 + tmpImg2 * 0.5;
			imshow("waterTransform", watershedImg);
		}
	}

	//while (waitKey(1) != 'q') {};
	return 0;
}

void on_Mouse(int event, int x, int y, int flags, void*) {
	/*处理鼠标不在窗口中的情况*/
	if (x<0 || x>srcImg.cols || y<0 || y>srcImg.rows) return;
	/*处理鼠标左键相关消息*/
	if (event == EVENT_LBUTTONUP || !(flags&EVENT_FLAG_LBUTTON)) prevPoint = Point(-1, -1);
	else if (event == EVENT_LBUTTONDOWN) prevPoint = Point(x, y);
	/*鼠标左键按下并移动,绘制白色线条*/
	else if (event == EVENT_MOUSEMOVE && (flags&EVENT_FLAG_LBUTTON)) {
		Point pt(x, y);
		if (prevPoint.x < 0) prevPoint = pt;//?
		line(maskImg, prevPoint, pt, Scalar::all(255), 5, 8, 0);
		line(srcImg, prevPoint, pt, Scalar::all(255), 5, 8, 0);
		prevPoint = pt;
		imshow(WINDOW_NAME2, srcImg);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值