#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include
using namespace cv;
using namespace std;
#define WINDOW_NAME "【程序窗口1】"
Mat g_maskImage, g_srcImage;
Point prevPt(-1,-1);
static void on_Mouse(int event,int x,int y,int flags,void*);
int main(int argc, char**argv)
{
//【1】载入原图并显示,初始化掩膜和灰度图
g_srcImage = imread("2.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没什么区别好像
g_maskImage = Scalar:: all(0);
//【2】设置鼠标回调函数
setMouseCallback(WINDOW_NAME,on_Mouse,0);
//waitKey(0);//这里要加这一个,不然不知道为什么上面的函数就不会运行了,不响应了,因为这样才能把窗口保持住,才能进行操作啊
while (1)
{
//获取键值
int c = waitKey(0);//当然这里有的话上面那个也可以没有了
//若按键键值为ESC时,退出
if ((char)c == 27) break;
//若按键值为2时,恢复原图
if ((char)c == '2')
{
g_maskImage = Scalar::all(0);
srcImage.copyTo(g_srcImage);
imshow("image",g_srcImage);
}
//若检测到按键值为1或者空格,则进行处理
if ((char)c == '1' || (char)c == ' ')
{
//定义一些参数
int i, j, comCount = 0;
vector> contours;
vector 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], comCount++)
{
drawContours(maskImage, contours, index, Scalar::all(comCount+1), -1, 8, hierarchy, INT_MAX);
}
//comCount为0时的处理
if (comCount == 0) continue;
//生成随机颜色
vector colorTab;
for (i = 0; i < comCount; 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./getTickFrequency());
//双层循环,将分水岭图像遍历存入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(i,j);
if (index == -1)//区域间
{
watershedImage.at(i, j) = Vec3b(255, 255, 255);
}
else if (index <= 0 || index > comCount)//应该是为标记的地方,也就是不确定的地方
watershedImage.at(i, j) = Vec3b(0,0,0);
else//种子的位置?
watershedImage.at(i, j) = colorTab[index-1];
}
//混合灰度图和分水岭效果图并显示最终的窗口
watershedImage = watershedImage*0.5 + grayImage*0.5;
imshow("watershed transform", watershedImage);
}
}
return 0;
}
效果图如下:
要转行人工智能的可以加下面这个公众号: