Ask Your Question

Object detection and counting

asked 2019-01-12 06:15:53 -0500

bobziz gravatar image

Hi there. I want to count the bars in the attached image. The bars section isn't exactly circle and not same color. Image: image description

please help me what algorithm should I use for best performance and best precision? 1. Feature extraction, learning and object detection methods like hog, cascade, sift, surf? 2. Deep learning? 3. Circle detection like houghtransform? 4. Any other idea???


edit retag flag offensive close merge delete


Thanks. - I can take more images but its just a sample to know which algorithm can fit the problem. - I've read about Tensorflow and Imagenet but have not practical knowledge. - I want to do it via opencv for sure with most accuracy.

Why do you think it cant be done with (1)?

bobziz gravatar imagebobziz ( 2019-01-12 07:17:59 -0500 )edit

i tried Morphology_2.cpp with your imageimage description

sturkmen gravatar imagesturkmen ( 2019-01-12 07:20:35 -0500 )edit

Could a attach complete image?

bobziz gravatar imagebobziz ( 2019-01-12 07:24:10 -0500 )edit

here is another image with kernel size 15image description

sturkmen gravatar imagesturkmen ( 2019-01-12 07:29:32 -0500 )edit

Thanks, So what next? Do you mean to use it as circle detection input? I think its not precise and have many false rejection rate.

bobziz gravatar imagebobziz ( 2019-01-12 07:33:31 -0500 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2019-01-13 04:46:07 -0500

updated 2019-01-13 06:31:06 -0500

take a look at the code below for taking some ideas

image description

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

using namespace cv;
using namespace std;

void SimpleBlobDetector_test(Mat src, Mat gray)
    // Set up the detector with default parameters.
    SimpleBlobDetector::Params params;

    params.minThreshold = 0;
    params.maxThreshold = 255;
    params.filterByColor = false;
    params.filterByArea = false;
    params.filterByInertia = false;
    params.filterByConvexity = false;

    Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);

    // Detect blobs.
    std::vector<KeyPoint> keypoints;
    detector->detect(gray, keypoints);

    // Draw detected blobs as red circles.
    // DrawMatchesFlags::DRAW_RICH_KEYPOINTS flag ensures the size of the circle corresponds to the size of blob
    Mat im_with_keypoints;
    drawKeypoints(src, keypoints, im_with_keypoints, Scalar(0, 0, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

    // Show blobs
    imshow("keypoints", im_with_keypoints);

int main(int argc, char** argv)
    Mat src = imread(argv[1], IMREAD_COLOR);

    if (src.empty())
        std::cout << "Could not open or find the image!\n" << std::endl;
        std::cout << "Usage: " << argv[0] << " <Input image>" << std::endl;
        return -1;

    Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(31, 31));

    Mat gray;
    cvtColor(src, gray, COLOR_BGR2GRAY);

    morphologyEx(gray, gray, MORPH_OPEN, kernel);

    //cvtColor(gray, src, COLOR_GRAY2BGR);

    int ksize = 9;
    int scale = 1;
    int delta = 0;
    int ddepth = CV_16S;

    Mat grad, grad_x, grad_y;
    Mat abs_grad_x, abs_grad_y;

    Sobel(gray, grad_x, ddepth, 1, 0, ksize, scale, delta, BORDER_DEFAULT);
    Sobel(gray, grad_y, ddepth, 0, 1, ksize, scale, delta, BORDER_DEFAULT);

    convertScaleAbs(grad_x, abs_grad_x);
    convertScaleAbs(grad_y, abs_grad_y);

    addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);

    gray = grad < 50;

    SimpleBlobDetector_test(src, gray);

    vector<vector<Point> > contours;
    vector<vector<Point> > filtered_contours;
    findContours(gray, contours, RETR_TREE, CHAIN_APPROX_SIMPLE);

    for (size_t i = 0; i < contours.size(); i++)
        Moments moms = moments(contours[i]);
        double area = moms.m00;
        double perimeter = arcLength(contours[i], true);
        double ratio = 4 * CV_PI * area / (perimeter * perimeter);
        if (ratio >= 0.8)
    drawContours(src, contours, -1, Scalar(0, 255, 0), 1);
    drawContours(src, filtered_contours, -1, Scalar(0, 0, 255), 1);
    imshow("Contours filtered by Circularity", src);

    return 0;
edit flag offensive delete link more


Thanks a lot, but I think it depends so much on parameter values and can't be practical. Light changes and color changes will ruin the result after parameter set. I think learning methods may have better result but I'm not sure which algorithm can fit this problem.

bobziz gravatar imagebobziz ( 2019-01-13 13:13:10 -0500 )edit

could you provide a bit more sample images

sturkmen gravatar imagesturkmen ( 2019-01-14 08:38:35 -0500 )edit

I think you will have a better chance at success doing preprocessing on the input, to get a standard view and then apply something like above, rather then learning to localize circle shapes. Have a look at histogram equalization, contrast enhancement, color normalization, ...

StevenPuttemans gravatar imageStevenPuttemans ( 2019-01-16 06:01:03 -0500 )edit

Question Tools

1 follower


Asked: 2019-01-12 06:15:53 -0500

Seen: 1,317 times

Last updated: Jan 13 '19