Skip to content Skip to sidebar Skip to footer

Opencv Divide Contacted Circles Into Single

I have an image to process.I need detect all the circles in the image.Here is it. And here is my code. import cv2 import cv2.cv as cv img = cv2.imread(imgpath) cv2.imshow('imgorg'

Solution 1:

Adapting the idea of @jochen I came to this:

  1. extract the full circle mask as you've done (I called it fullForeground )

enter image description here

  1. from your colored image, compute grayscale, blur (median blur size 7) it and and extract edges, for example with cv::Laplacian This laplacian thresholded > 50 gives:

cv::Laplacian(blurred, lap, 0, 5); // no deltalapMask = lap > 50; // thresholding to values > 50

enter image description here

This one dilated once gives:

cv::dilate(lapMask, dilatedThresholdedLaplacian, cv::Mat()); // dilate the edge mask once

enter image description here

Now subtraction fullForeground - dilatedThresholdedLaplacian (same as and_not operator for this type of masks) gives:

enter image description here

from this you can compute contours. For each contour you can compute the area and compare it to the area of an enclosing circle, giving this code and result:

std::vector<std::vector<cv::Point> > contours;
cv::findContours(separated.clone(), contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

double minArea = 500;
double minCircleRatio = 0.5;
for(unsignedint i=0; i<contours.size(); ++i)
{
    double cArea = cv::contourArea(contours[i]);
    if(cArea < minArea) continue;

    //filteredContours.push_back(contours[i]);//cv::drawContours(input, contours, i, cv::Scalar(0,255,0), 1);
    cv::Point2f center;
    float radius;
    cv::minEnclosingCircle(contours[i], center, radius);

    double circleArea = radius*radius*CV_PI;

    if(cArea/circleArea < minCircleRatio) continue;

    cv::circle(input, center, radius, cv::Scalar(0,0,255),2);
}

enter image description here

here is another image showing the coverage:

enter image description here

hope this helps

Solution 2:

I think the first mistake ist the value of thesh. In your example the command cv2.threshold converts all white areas to black and everything else to white. I would suggest using a smaller value for thesh so that all black pixel get converted to white and all white or "colored" pixels (inside the circles) get converted to black or vise versa. The value of thesh should be a little bigger than the brightest of the black pixels. See opencv docu for threshold for more information. Afterwards I would let opencv find all contours in the thresholded image and filter them for "valid" circles, e.g. by size and shape. If that is not sufficiant you could segment the inner circle from the rest of the image: First compute threasholdImageA with all white areas colored black. Then compute threasholdImageB with all the black areas being black. Afterwards combine both, threasholdImageA and threasholdImageB, (e.g. with numpy.logical_and) to have a binary image with only the inner circle being white and the rest black. Of course the values for the threshold have to be chosen wisely to get the specific result. That way also circles where the inner part directly touches the background will be segmented.

Post a Comment for "Opencv Divide Contacted Circles Into Single"