Ask Your Question
1

Opencv multiple circle detection in a image

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

mvsri gravatar image

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

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 -0500 )edit

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

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

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

mvsri gravatar imagemvsri ( 2020-09-10 01:40:07 -0500 )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 -0500 )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 -0500 )edit

3 answers

Sort by ยป oldest newest most voted
2

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

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

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 -0500

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

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
2

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

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
Login/Signup to Answer

Question Tools

1 follower

Stats

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

Seen: 116 times

Last updated: Sep 13