Revision history [back]

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()
{

// 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;
}


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()
{

// 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;
}


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()
{

// 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;
}