Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Another approach would be to use the SimpleBlobDetector() class, and playing with the parameters extract (have a look here for a nice explanation of the parameters) the desired result, plus that it can be implemented with much less code and personally I find find it neater approach. Have a look in the example bellow:

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
    Mat src = imread("markers.png");

    // resizing for practical reasons
    Mat rsz;
    Size size(800, 900);
    resize(src, rsz, size);

    imshow("rsz", rsz);

    vector<KeyPoint> keypoints;
    // Change parameters
    SimpleBlobDetector::Params params;

    params.filterByCircularity = true;
    params.maxCircularity = .85;
    params.minCircularity = .785;

    Ptr<FeatureDetector> blobsDetector = SimpleBlobDetector::create(params);
    blobsDetector->detect(rsz, keypoints);

    Mat drawImage = rsz.clone();
    for (size_t i = 0; i < keypoints.size(); ++i)
        circle(drawImage, keypoints[i].pt, 16, Scalar(0, 0, 255), 2);
//    imwrite("result.png", drawImage);
    imshow("result", drawImage);

    waitKey(0);
    return 0;
}

image description

Another approach would be to use the SimpleBlobDetector() class, and playing with the parameters extract (have a look here for a nice explanation of the parameters) the desired result, plus that it can be implemented with much less code and personally I find find it neater approach. Have a look in the example bellow:

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
    Mat src = imread("markers.png");

    // resizing for practical reasons
    Mat rsz;
    Size size(800, 900);
    resize(src, rsz, size);

    imshow("rsz", rsz);

    vector<KeyPoint> keypoints;
    // Change parameters
    SimpleBlobDetector::Params params;

    // Specify how close you want to be to a square, if you check  
    // the link you can make this work for other shapes as well
    params.filterByCircularity = true;
    params.maxCircularity = .85;
    params.minCircularity = .785;

    Ptr<FeatureDetector> blobsDetector = SimpleBlobDetector::create(params);
    blobsDetector->detect(rsz, keypoints);

    Mat drawImage = rsz.clone();
    for (size_t i = 0; i < keypoints.size(); ++i)
        circle(drawImage, keypoints[i].pt, 16, Scalar(0, 0, 255), 2);
//    imwrite("result.png", drawImage);
    imshow("result", drawImage);

    waitKey(0);
    return 0;
}

image description

Another approach would be to use the SimpleBlobDetector() class, and playing with the parameters extract (have a look here for a nice explanation of the parameters) the desired result, plus that it can be implemented with much less code and personally I find find it a bit neater as an approach. Have a look in the example bellow:

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
    Mat src = imread("markers.png");

    // resizing for practical reasons
    Mat rsz;
    Size size(800, 900);
    resize(src, rsz, size);

    imshow("rsz", rsz);

    vector<KeyPoint> keypoints;
    // Change parameters
    SimpleBlobDetector::Params params;

    // Specify how close you want to be to a square, if you check  
    // the link you can make this work for other shapes as well
    params.filterByCircularity = true;
    params.maxCircularity = .85;
    params.minCircularity = .785;

    Ptr<FeatureDetector> blobsDetector = SimpleBlobDetector::create(params);
    blobsDetector->detect(rsz, keypoints);

    Mat drawImage = rsz.clone();
    for (size_t i = 0; i < keypoints.size(); ++i)
        circle(drawImage, keypoints[i].pt, 16, Scalar(0, 0, 255), 2);
//    imwrite("result.png", drawImage);
    imshow("result", drawImage);

    waitKey(0);
    return 0;
}

image description