#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);
}
}
openCV 分水岭
最新推荐文章于 2024-09-25 12:33:22 发布
本文介绍了一个使用OpenCV实现的分水岭算法实战案例,通过鼠标绘制区域选择,自动进行图像分割,展示了从图像读取到最终效果展示的完整过程。代码中详细解释了如何利用分水岭算法进行图像处理,包括轮廓检测、颜色映射和图像混合等关键步骤。
摘要由CSDN通过智能技术生成