Pankaja
Pankaja

Reputation: 1

Find Circular circles in an image

I have an image.I want to detect the four holes which i have marked with a red line.

I have all the images in the link below. https://www.dropbox.com/sh/mlrm51qx8s1mcw0/AABu_dLm8RbvPO60H4CJ7I3ka?dl=0

InputImage(Input_Image.bmp)

Preprocessed image(PreprocessedImage.bmp)

Working image(holes detected) (DetectedHoles.bmp)

NonWorking Image(Only 3 holes detected)(NoNWorking.bmp)

Initially, this is preprocessing I do on the input image Input Image :Input_Image.bmp

hcontadj=vision.ContrastAdjuster;
Extracted_Rim_ContrasT_Adj=step(hcontadj,Extracted_Rim);
J = adapthisteq(Extracted_Rim);
Sharp_Img=imsharpen(J);
se=strel('disk',300);
imtop_op=imtophat(Sharp_Img,se);


 hgamma = ...
     vision.GammaCorrector(90.0,'Correction','De-gamma');
%  hgamma = ...
%      vision.GammaCorrector(12.0,'Correction','Gamma');
 y = step(hgamma, imtop_op);

h1 = imfilter(y,fspecial('gaussian',60,5));
H2=h1.*6.0;

se = strel('disk',14);
% Perform a morphological close operation on the image.
closeBW = imclose(H2,se);
figure, imshow(closeBW);

The output image obtained after the above processing PreprocessedImage.bmp

imfindcircles() and viscircles() are used to find the [centre,Raddi] and mark the circles with blue color respectively.

 [centers, radii] = imfindcircles(New_Open_Img,[32  100],'Sensitivity',0.81,'ObjectPolarity','dark');

    [h,x,y]=viscircles(centers, radii,'EdgeColor','b');

The output image obtained after the above two functions imfindcircles() and viscircles() is DetectedHoles.bmp

The non working image in which only three holes are detected NoNWorking.bmp.In this case all the four circles are not detected properly.

I fine tuned Sensitivity and Radius in imfindcircles() ,but still i am not able to detect all the circles.

It would be grateful if you give me some idea to tackle this issue.

Thanks

Upvotes: 0

Views: 6645

Answers (1)

P.R.
P.R.

Reputation: 3917

I assume you are using Matlab, unfortunately I do not have Matlab installed here, but I can give you an answer in python which should translate straight to Matlab.

I think you are going in a good direction by using the Hough Transform for circles (imfindcircles). But it is crucial to set the radius range correct. Especially if you expect the images you process to be similar. If the images you uploaded are representative, your radius should be between 10 and 15 (maybe even too generous, as the circles you want to detect are only around 25px wide).

Also rather than preprocessing your image with morphological operations, I would use a edge detector. I tried it with the canny edge detector BW1 = edge(I,'Canny');. If you do this, you will detect the circle in the middle as well, by you can remove it in a post processing step. You simply have to check which circle is neither furthest up or down, nor furthest left or right.

The python/skimage based code (slightly changed from the example code: http://scikit-image.org/docs/dev/auto_examples/plot_circular_elliptical_hough_transform.html ):

import numpy as np
import matplotlib.pyplot as plt

from skimage import data, color
from skimage.transform import hough_circle
from skimage.feature import peak_local_max, canny
from skimage.draw import circle_perimeter
from skimage.util import img_as_ubyte
from skimage.io import imread


# Load picture and detect edges
image = imread('test.jpeg')[..., 0]
edges = canny(image, sigma=3, low_threshold=10, high_threshold=50)

fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(20, 10))

# Detect two radii
hough_radii = np.arange(13, 15, 2)
hough_res = hough_circle(edges, hough_radii)

centers = []
accums = []
radii = []

for radius, h in zip(hough_radii, hough_res):
    # For each radius, extract 5 circles
    num_peaks = 5
    peaks = peak_local_max(h, num_peaks=num_peaks)
    centers.extend(peaks)
    accums.extend(h[peaks[:, 0], peaks[:, 1]])
    radii.extend([radius] * num_peaks)

# Draw the most prominent 5 circles
image = color.gray2rgb(image)
for idx in np.argsort(accums)[::-1][:]:
    center_x, center_y = centers[idx]
    radius = radii[idx]
    cx, cy = circle_perimeter(center_y, center_x, radius)
    image[cy, cx] = (220, 20, 20)

ax.imshow(image, cmap=plt.cm.gray)

Notebook (with result) here: https://gist.github.com/groakat/0e04d10a08fc05bff7e1

In Matlab it should be something like

I = imread('test.jpeg');

BW1 = edge(I,'Canny');

[centers, radii, metric] = imfindcircles(BW1,[10 15]);

centersStrong5 = centers(1:5,:);
radiiStrong5 = radii(1:5);
metricStrong5 = metric(1:5);


imshow(I)
viscircles(centersStrong5, radiiStrong5,'EdgeColor','b');

Upvotes: 2

Related Questions