How to draw contours of each segmented object [closed]
Hello,
I apply watershed segmentation to detect touching objects. It works okay. Now, I would like to draw contours of each object. But the objects in the result of the segmentation are still touching. So, I fail to draw contours of each one. How can I apply a mask for each object? Then I could draw contours separately.
#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
vector<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;
}
Source:
Watershed result:
Your objects have different color in the output of th watershed. So, just threshold the image to get each of them.
@LorenaGdL Yes, but I need a general solution as number of the objects could be different. So I looked at the tutorial on opencv.org about how each object gets filled with random color. I modified it in a way that I could store each object in a vector.
But I keep getting the object on the right, in images[0] and images[1]
images.push_back(dst.clone());
However, if you want my 2cts on this, you can easily avoid those per-pixel loops and get your original image segmented in 5 lines:
@LorenaGdL Thanks, I managed to do what I wanted. I will post an answer but turns out I have to wait 2 days for that.
Is there then a way to get the number of pixels of the largest object, 2nd largest, 3rd largest..so on?