|   | 1 |  initial version  | 
take a look at the code below for taking some ideas
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
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);
    src = src * 3;
    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;
    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)
            filtered_contours.push_back(contours[i]);
    }
    drawContours(src, contours, -1, Scalar(0, 255, 0), 1);
    drawContours(src, filtered_contours, -1, Scalar(0, 0, 255), 1);
    imshow("src", src);
    waitKey(0);
    return 0;
}
|   | 2 |  No.2 Revision  | 
take a look at the code below for taking some ideas

#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, //cvtColor(gray, src, COLOR_GRAY2BGR);
    src = src * 3;
 
    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)
            filtered_contours.push_back(contours[i]);
    }
    drawContours(src, contours, -1, Scalar(0, 255, 0), 1);
    drawContours(src, filtered_contours, -1, Scalar(0, 0, 255), 1);
    imshow("src", imshow("Contours filtered by Circularity", src);
    waitKey(0);
    return 0;
}