/*分割目标
图像传给函数之前需要大致勾画标记出图像中的期望进行分割的区域,被标记为正指数
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);
}
}