Search code examples
c++image-processinghough-transformdiplib

Detecting circles with DIPlib


I'm trying to detect the circles in this image: image and then drawing such circles in another blank image using DIPlib in C++.

Following the advices of Cris Luengo I've changed the code and now looks like this:

#include <iostream>
#include <vector>
#include <diplib.h>
#include <dipviewer.h>
#include <diplib/file_io.h>
#include <diplib/display.h>
#include <diplib/color.h>
#include <diplib/linear.h>
#include <diplib/detection.h>
#include <diplib/generation.h>

using namespace std;

int main()
{
    try{
    //read image
    dip::Image img;
    dip::ImageReadTIFF(img,"circle.tif");
    dip::ColorSpaceManager csm;
    img = csm.Convert(img, "grey");

    //circle detection
    //first convert the image in binary
    dip::Image bin_img = img<128;

    //Now calculate the gradient vector of the images
    dip::Image gv=dip::Gradient(img);

    //Apply the Hough transform to find the cicles
    dip::FloatCoordinateArray circles;
    circles=dip::FindHoughCircles(bin_img,gv,{},0.0,0.2);

    //Draw circles
    dip::Image detec_img= g_img.Similar(dip::DT_UINT8);
    for(auto i: circles){
                dip::FloatArray center;
                center.push_back(i[0]);
                center.push_back(i[1]);

                dip::dfloat diameter=i[2]*2;
                dip::DrawBandlimitedBall(detec_img,diameter,center, {255}, "empty");

                center.clear();
                }
    dip::ImageWriteTIFF(detec_img, "detected.tif");

I also changed the parameters of the FindHoughCircles function because there are two concentric circles in the image so the distance between centers has to be 0.0 but the program is unable to detect it. This is the result:

This is the updated result


Solution

  • The documentation for dip::FindHoughCircles reads:

    Finds circles in 2D binary images using the 2-1 Hough transform. First, circle centers are computed using dip::HoughTransformCircleCenters, and then a radius is calculated for each center. Note that only a single radius is returned per center coordinates.

    That is, this function is not able to find concentric circles.

    One workaround could be to run the function twice, with different limits for the circle sizes.


    In DIPlib, all allocated images (either through the dip::Image constructor, though img.Forge(), through img.Similar(), etc.) are not initialized. You need to explicitly set the pixels to zero before you start drawing in it: detec_img.Fill(0). Your output image has some very nice display of previous memory use in the bottom half, I wonder what computations lead to that! :)