Ask Your Question
1

Opencv multiple circle detection in a image

asked 2020-09-09 07:31:53 -0600

mvsri gravatar image

updated 2020-09-10 01:38:54 -0600

Hey there, I writing a code for colony counter (Spots detection on a plate), This is the code i'm using as of now.

const cv::Mat in = load_image;   // Load image from a folder
cv::Mat tmp_mat, red_mat, blur_mat, gray_mat;
std::vector<cv::Mat> split_s;

cv::cvtColor(in, tmp_mat, cv::COLOR_BGR2HSV);
cv::split(tmp_mat, split_s);

cv::Mat mas_img, out_img;

for(int i = 0; i < load_image.rows; i++)
{
    for(int j = 0; j < load_image.cols; j++)
    {
        if((int)split_s[1].at<uchar>(i,j) >=
  70)
        {
            split_s[1].at<uchar>(i,j) = 250;
        }
        else {
            split_s[1].at<uchar>(i,j) = 0;
        }
      }
  }
cv::imshow("After", split_s[1]); 
cv::GaussianBlur(split_s[1], split_s[1], cv::Size(3,3), 0, 0); 
cv::imshow("Blur", split_s[1]);

std::vector<cv::Vec3f> circles;
cv::HoughCircles(split_s[1], circles, cv::HOUGH_GRADIENT, 1,
distances to each other
             200, 20, 1, 50 
);
for( size_t i = 0; i < circles.size(); i++ )
{
    cv::Vec3i c = circles[i];
    cv::Point center = cv::Point(c[0], c[1]);
    int radius = c[2];
    cv::circle( load_image, center, radius, cv::Scalar(255,0,255),
 2, cv::LINE_AA);
 }
 cv::imshow("result", load_image);

The Output of cv::imshow("Blur", split_s[1]) is as follows:

image description

but the problem is after HoughCircles Detection not every circle is detected. How to detected each and every circle in the image

Edit 1: Original Image:- image description

Edit 2: Result Image:- image description

edit retag flag offensive close merge delete

Comments

could you post the original image

sturkmen gravatar imagesturkmen ( 2020-09-09 07:53:51 -0600 )edit

... and mark the circles that aren't detected...

mvuori gravatar imagemvuori ( 2020-09-10 00:20:06 -0600 )edit

I have updated the result image, where circles detected are makred.

mvsri gravatar imagemvsri ( 2020-09-10 01:40:07 -0600 )edit

There is now HOUGH_GRADIENT_ALT (only in recent OpenCV versions) that should improve the detection, see this PR.

Eduardo gravatar imageEduardo ( 2020-09-10 04:58:17 -0600 )edit

I hope to provide more pictures to facilitate the creation of data sets and targeted experiments.

jsxyhelu gravatar imagejsxyhelu ( 2020-09-12 18:16:37 -0600 )edit

3 answers

Sort by ยป oldest newest most voted
2

answered 2020-09-10 03:23:12 -0600

kbarni gravatar image

Try the DistanceTransform, it's another good method for circle detection in binary images.

This example should help.

edit flag offensive delete link more
2

answered 2020-09-12 18:15:37 -0600

updated 2020-09-13 01:41:36 -0600

Inevitably, we need to consider the characteristics of "circle" and try SimpleBlobDetector to implement it. The changes also include canceling the parameters of the basic morphological transformation, or directly canceling the morphological change.

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <opencv2/features2d.hpp>

void main()
{
    const cv::Mat in = cv::imread("15996646131571621.jpg");
    cv::Mat src;
    cv::dilate(in, src, cv::Mat());
    cv::erode(src, src, cv::Mat());

    cv::Mat hsv;
    cv::cvtColor(src, hsv, cv::COLOR_BGR2HSV);

    std::vector<cv::Mat> split_s;
    cv::split(hsv, split_s);
    split_s[1] = split_s[1] > 70;

    cv::SimpleBlobDetector::Params params;
    params.filterByColor = false;
    params.minThreshold = 120;
    std::vector<cv::KeyPoint> keypoints;
    cv::Ptr<cv::SimpleBlobDetector> detector = cv::SimpleBlobDetector::create(params);
    detector->detect(split_s[1], keypoints);
    cv::drawKeypoints(in, keypoints, in, cv::Scalar(0, 0, 255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
    cv::imshow("result", in);
    cv::waitKey();
}
edit flag offensive delete link more
2

answered 2020-09-12 12:34:19 -0600

updated 2020-09-13 03:28:30 -0600

EDIT : there is an open source project OpenCFU

here is just a simple code to show an alternative way

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"


void main()
{
    const cv::Mat in = cv::imread("15996646131571621.jpg");

    cv::Mat src;
    cv::dilate(in, src, cv::Mat(), cv::Point(-1, -1), 2);
    cv::erode(src, src, cv::Mat(), cv::Point(-1, -1), 2);

    cv::Mat hsv;
    cv::cvtColor(src, hsv, cv::COLOR_BGR2HSV);

    std::vector<cv::Mat> split_s;
    cv::split(hsv, split_s);

    split_s[1] = split_s[1] > 70;
    cv::dilate(split_s[1], split_s[1], cv::Mat());

    std::vector<std::vector<cv::Point> > contours;
    findContours(split_s[1], contours, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);

    for (size_t i = 0; i < contours.size(); i++)
    {
        cv::Rect r = cv::boundingRect(contours[i]);

        cv::Mat resized;
        cv::resize(in(r), resized, cv::Size(5, 5), 0, 0);
        cv::Scalar mean_s = cv::mean(resized);

        if( (mean_s[0] > 120 ) & (mean_s[0]< 200) )
        {
            cv::drawContours(in, contours, i, cv::Scalar(0, 255, 0), 1);
            cv::rectangle(in, r, cv::Scalar(0, 0, 255), 1);
        }
    }

    cv::imshow("result", in);
    cv::waitKey();
}
edit flag offensive delete link more

Comments

OpenCFU has achieved great results, but its documentation is relatively lacking except for a review paper. I wonder if you have studied it?

jsxyhelu gravatar imagejsxyhelu ( 2020-11-02 08:05:53 -0600 )edit
sturkmen gravatar imagesturkmen ( 2020-11-02 09:08:48 -0600 )edit

NextCFU sounds good,thanks you

jsxyhelu gravatar imagejsxyhelu ( 2020-11-03 05:58:23 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2020-09-09 07:31:53 -0600

Seen: 1,189 times

Last updated: Sep 13 '20