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;
}

源图像: 在此处输入图像描述

分水岭结果: 在此处输入图像描述

4

2 回答 2

1

根据种子,返回的markers矩阵watershed包含分割区域的索引。所以每个组件都将具有相同的种子值。然后,您可以为每个种子创建一个二进制矩阵,例如:

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;
}
于 2015-11-12T20:13:36.663 回答
0

有很多方法可以做到这一点。根据已显示的当前图像,您可以简单地进行腐蚀和膨胀操作,以便将它们分开。但是,如果经过区域较大,这将不起作用。

你需要一个关闭操作: http ://docs.opencv.org/2.4/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html

  1. 阈值它。
  2. 应用关闭操作。
  3. 获取轮廓
于 2015-11-07T18:47:27.810 回答