2015-11-06 57 views
2

我使用分水岭分割来检测触摸对象,并且它可以正常工作。现在,我想绘制每个对象的轮廓,以便我可以获得它们的长度,面积,时刻等。但分割结果中的对象仍然触摸。所以,我没有画出每一个的轮廓。我怎样绘制每个物体的轮廓?如何绘制每个分段对象的轮廓

#include <opencv2/imgproc/imgproc.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <iostream> 

using namespace std; 
using namespace cv; 

int main() 
{ 
    Mat src = imread("source.png"); 

    // Create binary image from source image 
    Mat srcGray; 
    cvtColor(src, srcGray, CV_BGR2GRAY); 

    Mat srcThresh; 
    threshold(srcGray, srcThresh, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); 

    // Perform the distance transform algorithm 
    Mat dist; 
    distanceTransform(srcThresh, dist, CV_DIST_L2, 3); 

    // Normalize the distance image for range = {0.0, 1.0} 
    normalize(dist, dist, 0, 1., NORM_MINMAX); 

    // Threshold to obtain the peaks 
    threshold(dist, dist, 0.1, 3.5, CV_THRESH_BINARY); 

    // Create the CV_8U version of the distance image 
    Mat dist_8u; 
    dist.convertTo(dist_8u, CV_8U); 

    // Find total markers 
    std::vector<std::vector<Point> > contours; 
    findContours(dist_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); 
    int ncomp = contours.size(); 

    // Create the marker image for the watershed algorithm 
    Mat markers = Mat::zeros(dist.size(), CV_32SC1); 

    // Draw the foreground markers 
    for (int i = 0; i < ncomp; i++) 
     drawContours(markers, contours, i, Scalar::all(i + 1), -1); 

    // Draw the background marker 
    circle(markers, Point(5, 5), 3, CV_RGB(255, 255, 255), -1); 

    // Perform the watershed algorithm 
    watershed(src, markers); 

    Mat wgResult = (markers.clone()) * 10000; 

    imshow("Watershed", wgResult); 

    waitKey(0); 
    return 0; 
} 

图片来源: enter image description here

流域结果: enter image description here

回答

1

通过watershed返回的markers矩阵包含分段区域的索引,根据该种子。因此,每个组件将具有相同的种子值。然后,您可以创建一个二进制矩阵像每个种子:

Mat1b mask = (markers == seed); 

一旦你有每个组件的二进制掩码,你可以很容易地计算出它的面积,时刻等..

代码:

#include <opencv2/opencv.hpp> 
#include <iostream> 
using namespace std; 
using namespace cv; 

int main() 
{ 
    Mat src = imread("D:\\SO\\img\\postit.png"); 

    // Create binary image from source image 
    Mat srcGray; 
    cvtColor(src, srcGray, CV_BGR2GRAY); 

    Mat srcThresh; 
    threshold(srcGray, srcThresh, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); 

    // Perform the distance transform algorithm 
    Mat dist; 
    distanceTransform(srcThresh, dist, CV_DIST_L2, 3); 

    // Normalize the distance image for range = {0.0, 1.0} 
    normalize(dist, dist, 0, 1., NORM_MINMAX); 

    // Threshold to obtain the peaks 
    threshold(dist, dist, 0.1, 3.5, CV_THRESH_BINARY); 

    // Create the CV_8U version of the distance image 
    Mat dist_8u; 
    dist.convertTo(dist_8u, CV_8U); 

    // Find total markers 
    std::vector<std::vector<Point> > contours; 
    findContours(dist_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); 
    int ncomp = contours.size(); 

    // Create the marker image for the watershed algorithm 
    Mat markers = Mat::zeros(dist.size(), CV_32SC1); 

    // Draw the foreground markers 
    for (int i = 0; i < ncomp; i++) 
     drawContours(markers, contours, i, Scalar::all(i + 1), -1); 

    // Draw the background marker 
    circle(markers, Point(5, 5), 3, CV_RGB(255, 255, 255), -1); 

    // Perform the watershed algorithm 
    watershed(src, markers); 

    for (int seed = 1; seed <= ncomp; ++seed) 
    { 
     Mat1b mask = (markers == seed); 

     // Now you have the mask, you can compute your statistics 

     imshow("Mask", mask); 
     waitKey(); 
    } 

    return 0; 
} 
+0

greate solution! – sturkmen