// 用Canny算子检测边缘
Canny( g_grayImage, g_cannyMat_output, g_nThresh, g_nThresh*2, 3 );
// 寻找轮廓
findContours( g_cannyMat_output, g_vContours, g_vHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
// 绘出轮廓
Mat drawing = Mat::zeros( g_cannyMat_output.size(), CV_8UC3 );
for( int i = 0; i< g_vContours.size(); i++ )
{
Scalar color = Scalar( g_rng.uniform(0, 255), g_rng.uniform(0,255), g_rng.uniform(0,255) );//任意值
drawContours( drawing, g_vContours, i, color, 2, 8, g_vHierarchy, 0, Point() );
}
// 寻找轮廓
findContours( g_thresholdImage_output, g_vContours, g_vHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
// 遍历每个轮廓,寻找其凸包
vector<vector<Point> >hull( g_vContours.size() );
for( unsigned int i = 0; i < g_vContours.size(); i++ )
{
convexHull( Mat(g_vContours[i]), hull[i], false );
}
// 绘出轮廓及其凸包
Mat drawing = Mat::zeros( g_thresholdImage_output.size(), CV_8UC3 );
for(unsigned int i = 0; i< g_vContours.size(); i++ )
{
Scalar color = Scalar( g_rng.uniform(0, 255), g_rng.uniform(0,255), g_rng.uniform(0,255) );
drawContours( drawing, g_vContours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
drawContours( drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
}
// 使用Threshold检测边缘
threshold( g_grayImage, threshold_output, g_nThresh, 255, THRESH_BINARY );
// 找出轮廓
findContours( threshold_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
// 多边形逼近轮廓 + 获取矩形和圆形边界框
vector<vector<Point> > contours_poly( contours.size() );
vector<Rect> boundRect( contours.size() );
vector<Point2f>center( contours.size() );
vector<float>radius( contours.size() );
//一个循环,遍历所有部分,进行本程序最核心的操作
for( unsigned int i = 0; i < contours.size(); i++ )
{
approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );//用指定精度逼近多边形曲线
boundRect[i] = boundingRect( Mat(contours_poly[i]) );//计算点集的最外面(up-right)矩形边界
minEnclosingCircle( contours_poly[i], center[i], radius[i] );//对给定的 2D点集,寻找最小面积的包围圆形
}
// 绘制多边形轮廓 + 包围的矩形框 + 圆形框
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
for( int unsigned i = 0; i<contours.size( ); i++ )
{
Scalar color = Scalar( g_rng.uniform(0, 255), g_rng.uniform(0,255), g_rng.uniform(0,255) );//随机设置颜色
drawContours( drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point() );//绘制轮廓
rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );//绘制矩形
circle( drawing, center[i], (int)radius[i], color, 2, 8, 0 );//绘制圆
}
// 使用Canndy检测边缘
Canny( g_grayImage, g_cannyMat_output, g_nThresh, g_nThresh*2, 3 );
// 找到轮廓
findContours( g_cannyMat_output, g_vContours, g_vHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
// 计算矩
vector<Moments> mu(g_vContours.size() );
for(unsigned int i = 0; i < g_vContours.size(); i++ )
{ mu[i] = moments( g_vContours[i], false ); }
// 计算中心矩
vector<Point2f> mc( g_vContours.size() );
for( unsigned int i = 0; i < g_vContours.size(); i++ )
{ mc[i] = Point2f( static_cast<float>(mu[i].m10/mu[i].m00), static_cast<float>(mu[i].m01/mu[i].m00 )); }
// 绘制轮廓
Mat drawing = Mat::zeros( g_cannyMat_output.size(), CV_8UC3 );
for( unsigned int i = 0; i< g_vContours.size(); i++ )
{
Scalar color = Scalar( g_rng.uniform(0, 255), g_rng.uniform(0,255), g_rng.uniform(0,255) );//随机生成颜色值
drawContours( drawing, g_vContours, i, color, 2, 8, g_vHierarchy, 0, Point() );//绘制外层和内层轮廓
circle( drawing, mc[i], 4, color, -1, 8, 0 );;//绘制圆
}
//定义一些参数
int i, j, compCount = 0;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
//寻找轮廓
findContours(g_maskImage, contours, hierarchy, RETR_CCOMP, 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为零时的处理
if( compCount == 0 )
continue;
//生成随机颜色
vector<Vec3b> colorTab;
for( 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./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<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( WINDOW_NAME2, watershedImage );
inpaintMask = Mat::zeros(srcImage1.size(), CV_8U);
参考书籍《OpenCV3编程入门》