scikit-image / scikit-image

Image processing in Python
https://scikit-image.org
Other
6.06k stars 2.22k forks source link

Circle Detection #5525

Open ashbrin opened 3 years ago

ashbrin commented 3 years ago

Description

I have referred to this link, https://scikit-image.org/docs/dev/auto_examples/edges/plot_circular_elliptical_hough_transform.html for detecting circles within an image. However upon running the code using my image, it goes for a spin. I have to kill my session after waiting for 30 min -->

Way to reproduce

Please use the code within the link I have posted in the Description

Version information

# Paste the output of the following python commands
from __future__ import print_function
import sys; print(sys.version)
import platform; print(platform.platform())
import skimage; print("scikit-image version: {}".format(skimage.__version__))
import numpy; print("numpy version: {}".format(numpy.__version__))
3.7.7 (default, May  6 2020, 11:45:54) [MSC v.1916 64 bit (AMD64)]
Windows-10-10.0.19041-SP0
scikit-image version: 0.16.2
numpy version: 1.19.1
![image1_2_circles](https://user-images.githubusercontent.com/28551494/130327738-c75154d2-e6d5-4122-a220-c6b0dd078bd7.JPG)
![image1_3_circles](https://user-images.githubusercontent.com/28551494/130327739-6ccd4d38-fbec-4f78-aabc-fb0de6802be0.JPG)
gunjan381 commented 3 years ago

please assign me this issue.

ashbrin commented 3 years ago

please assign me this issue.

Hi Gunjan, Could you advise how I assign the issue to you? Pardon my ignorance, I have not done this before. Thanks, Ananth

grlee77 commented 3 years ago

@ashbrin: Only people with write access to a repository can assign issues, so you will not be able to do it.

However, for us to address this we may need some more info to help reproduce the problem:

1.) If I understand correctly, the existing demo runs okay for you, but when you try it on your own image you get the failure?

2.) What is the shape of the image where you are seeing the failure? Are you able to share a link to it?

3.) Have you confirmed the same bug with the latest scikit-image release (0.18.2)?

@gunjan381, thank you for volunteering to help look at this. We usually don't explicitly assign issues as conflicting PRs for the same thing have not been common. I can assign you to this issue, but please let us know if you later decide not to work on it.

gunjan381 commented 3 years ago

ok. I am doing it.

ashbrin commented 3 years ago

@grlee77 : Here are my responses for your questions: 1.) If I understand correctly, the existing demo runs okay for you, but when you try it on your own image you get the failure? Yes, that is correct. I was able to get the output for the coffee mug. When I run it on my own image it goes for a spin and I have to kill the process 2) One of the images is 370 x 331 and other is 524 x 478 and both are RGB images. The links are: Image 1: https://user-images.githubusercontent.com/28551494/130327738-c75154d2-e6d5-4122-a220-c6b0dd078bd7.JPG Image 2: https://user-images.githubusercontent.com/28551494/130327739-6ccd4d38-fbec-4f78-aabc-fb0de6802be0.JPG 3) No, I have not tried with the latest scikit-image release. I will try and post my comments.

ashbrin commented 3 years ago

@grlee77 , I tried it in the scikit-image version 0.18.2 and it did not change the behavior.

grlee77 commented 3 years ago

Can you confirm what line of the example it is getting stuck at? (Many different functions are being called in that script: canny, hough_circle, hough_circle_peaks, circle_perimiter, hough_ellipse, ellipse_perimiter, etc.)

It will be helpful if you can provide the exact script as you ran it.

You will likely need to update some thresholds or other parameters a bit for it to work for your data. For example, you probably should set mode='reflect' for the Canny edge detectors on the images you provided so that the border of the image will not be so prominent in the edges image. That said, regardless of parameter tuning, it definitely should not be hanging indefinitely and we should determine why that is happening...

ashbrin commented 3 years ago

@grlee77 , I ran the code again in debug mode in Spyder. I used the image 3_circles_images.jpg. Here is the error it threw at the line: result.sort(order='accumulator') File "", line 1, in result.sort(order='accumulator')

ValueError: Cannot specify order when the array has no fields. plot_circular_elliptical_hough_transform.zip (Attachment: Python code I have used)

When I use ArgumentParser and pass the image and that is when the program hangs indefinitely. I did not see that behavior when I run it in debug mode.

ashbrin commented 3 years ago

@grlee77 , kindly let me know if you have been able to reproduce the issue based on the code and the image I have shared. Also I noticed that @gunjan381 has been withdrawn as an assignee. Just curious to know if anyone is looking into the issue. Thank you.

grlee77 commented 3 years ago

I am able to reproduce the problem using your example.

One issue is that some adjustment to the arguments in the call to canny is needed so that the edges variable has circles present in it after thresholding. With the current values in your attached script, only some straight lines near the edge show up. However, that change alone is not enough to fully resolve the issue.

I have not studied or worked with this kind of circle detection algorithm before, so it would take a bit of research to figure out what the issue likely is. Perhaps there is a problem in detecting concentric circles or starting parameter values are not at a reasonable point.

Let me ping @scikit-image/core to see if anyone has more experience with this transform. It looks like hough_circle was originally contributed by @sciunto, but he is no longer an active maintainer here.

stefanv commented 3 years ago

The plot thickens. The following snippet works:

from skimage import color, io
from skimage.feature import canny
from skimage.transform import hough_ellipse

image_rgb = io.imread("130327738-c75154d2-e6d5-4122-a220-c6b0dd078bd7.jpeg")
image_gray = color.rgb2gray(image_rgb)
edges = canny(image_gray, sigma=2.0,
              low_threshold=0.55, high_threshold=0.8)
hough_ellipse(edges, accuracy=50, threshold=250,
              min_size=100, max_size=120)
ashbrin commented 3 years ago

@stefanv , thanks much for your response. I did run the program with the parameters you have specified in your response. Unfortunately the hough_ellipse returns a null value. Could you kindly publish the entire code you got that gave you better results?

stefanv commented 3 years ago

@ashbrin What I meant was that this is confusing: the program does not freeze, whether when I run the other version it does. I am not sure why yet.

rfezzani commented 3 years ago

Hello @ashbrin and thank you for your interest in scikit-image.

Using your image and after adapting functions parameters:

from matplotlib import pyplot as plt
import numpy as np
import imageio

from skimage import color
from skimage.feature import canny
from skimage.transform import hough_circle, hough_circle_peaks
from skimage.draw import circle_perimeter

img_rgb = imageio.imread(
    "/tmp/130327738-c75154d2-e6d5-4122-a220-c6b0dd078bd7.JPG"
)

img = color.rgb2gray(img_rgb)
print(img.max())
edges = canny(img, sigma=3, mode="reflect")

hough_radii = np.arange(10, 130, 2)
hough_res = hough_circle(edges, hough_radii)
accums, cx, cy, radii = hough_circle_peaks(hough_res, hough_radii,
                                           min_xdistance=1,
                                           min_ydistance=1,
                                           total_num_peaks=2)

for center_y, center_x, radius in zip(cy, cx, radii):
    circy, circx = circle_perimeter(center_y, center_x, radius,
                                    shape=img_rgb.shape)
    img_rgb[circy, circx] = (220, 20, 20)

fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(8, 4))
ax0.imshow(img_rgb)
ax1.imshow(edges)
fig.tight_layout()

plt.show()

I obtained Figure_1

Closing, but feel free to reopen if you wish :wink:

ashbrin commented 3 years ago

@rfezzani , thanks for your support. Unfortunately the code does not run and it throws an error edges = canny(img, sigma=3, mode="reflect") Traceback (most recent call last):

File "", line 1, in edges = canny(img, sigma=3, mode="reflect")

TypeError: canny() got an unexpected keyword argument 'mode'

I removed the parameter mode and ran it but it won't detect the circles.

p.s. I do not find an option to "Open" the issue again.

rfezzani commented 3 years ago

The mode argument was added in the development branch of skimage and will be released soon :crossed_fingers: in v0.19, sorry :pray:. But if I remove the mode argument, I obtain the same result with skimage v0.18.1! What is your current version of the package?

rfezzani commented 3 years ago

BTW, you may find more help on image.sc dedicated forum :wink:. Github is more suited for development issues.

ashbrin commented 3 years ago

@rfezzani , the version of the package is 0.18.1. I have attached the output I got after running the code (removed the mode parameter). As I had mentioned earlier, it returns an empty plot. output_scikit_image

rfezzani commented 3 years ago

Hum, as I can't reproduce the issue, can any @scikit-image/core member confirm/infirm this behavior? @ashbrin, as I already mentioned, you may get more help on the image.sc forum :wink:

alexdesiqueira commented 3 years ago

Hey everyone, @ashbrin I tried to reproduce the following error:

result.sort(order='accumulator')
File "", line 1, in
result.sort(order='accumulator')

ValueError: Cannot specify order when the array has no fields.

It happens because result is empty, since edges is a Boolean with all values equal to false:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-10-39c2ec1ae6ac> in <module>
     17 result = hough_ellipse(edges, accuracy=20, threshold=250,
     18                        min_size=100, max_size=120)
---> 19 result.sort(order='accumulator')
     20 
     21 # Estimated parameters for the ellipse

ValueError: Cannot specify order when the array has no fields.

In [11]: result
Out[11]: array([], shape=(0, 6), dtype=float64)

In [12]: edges
Out[12]: 
array([[False, False, False, ..., False, False, False],
       [False, False, False, ..., False, False, False],
       [False, False, False, ..., False, False, False],
       ...,
       [False, False, False, ..., False, False, False],
       [False, False, False, ..., False, False, False],
       [False, False, False, ..., False, False, False]])

In [13]: edges.max()
Out[13]: False

Maybe the Canny parameters you chose/we proposed at the example are not well suited for the image you are using. I have the same results as @rfezzani when using this code without the argument mode in canny, in skimage 0.18.1. This way, the following code should solve the issue for you:

from matplotlib import pyplot as plt
import numpy as np
import imageio

from skimage import color
from skimage.feature import canny
from skimage.transform import hough_circle, hough_circle_peaks
from skimage.draw import circle_perimeter

img_rgb = imageio.imread(
    "/tmp/130327738-c75154d2-e6d5-4122-a220-c6b0dd078bd7.JPG"
)

img = color.rgb2gray(img_rgb)
print(img.max())
edges = canny(img, sigma=3)

hough_radii = np.arange(10, 130, 2)
hough_res = hough_circle(edges, hough_radii)
accums, cx, cy, radii = hough_circle_peaks(hough_res, hough_radii,
                                           min_xdistance=1,
                                           min_ydistance=1,
                                           total_num_peaks=2)

for center_y, center_x, radius in zip(cy, cx, radii):
    circy, circx = circle_perimeter(center_y, center_x, radius,
                                    shape=img_rgb.shape)
    img_rgb[circy, circx] = (220, 20, 20)

fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(8, 4))
ax0.imshow(img_rgb)
ax1.imshow(edges)
fig.tight_layout()

plt.show()

Could you please check if this code works? Thank you!

ashbrin commented 3 years ago

Hello @alexdesiqueira , Thanks for your efforts. I used the code you have just shared but unfortunately I am still returning only empty plots.

image

Thanks, Ananth

alexdesiqueira commented 3 years ago

Hi @ashbrin, after running that code, could you show us the results of:

>>> print(edges)
>>> print(edges.dtype)
>>> import matplotlib; print("matplotlib version: {}".format(matplotlib.__version__))

Thank you!

ashbrin commented 3 years ago

Hello @alexdesiqueira , For print(edges): [[False False False ... False False False] [False False False ... False False False] [False False False ... False False False] ... [False False False ... False False False] [False False False ... False False False] [False False False ... False False False]]

For print(edges.dtype) the output is bool

Fo matplotlib version: 3.2.2

alexdesiqueira commented 3 years ago

Hi @ashbrin, a last one, sorry. Could you check

>>> print(edges.max())

and let us know? I feel something is not right for the parameters, in your case. Thank you!

ashbrin commented 3 years ago

Hello @alexdesiqueira , The print(edges.max()) returned False

Thanks Ananth

alexdesiqueira commented 2 years ago

Hi @ashbrin, sorry for not answering you before. Somehow, your edges image is not properly defined; it returns only False when it should have some True around. I'd suggest you to try changing the line

edges = canny(img, sigma=3)

passing sigma=1.5, sigma=2, sigma=2.5, and plotting the results. Example:

from matplotlib import pyplot as plt
import numpy as np
import imageio

from skimage import color
from skimage.feature import canny
from skimage.transform import hough_circle, hough_circle_peaks
from skimage.draw import circle_perimeter

img_rgb = imageio.imread(
    "/tmp/130327738-c75154d2-e6d5-4122-a220-c6b0dd078bd7.JPG"
)

img = color.rgb2gray(img_rgb)
print(img.max())
edges = canny(img, sigma=3)  # <--- change sigma in this line to different values

hough_radii = np.arange(10, 130, 2)
hough_res = hough_circle(edges, hough_radii)
accums, cx, cy, radii = hough_circle_peaks(hough_res, hough_radii,
                                           min_xdistance=1,
                                           min_ydistance=1,
                                           total_num_peaks=2)

for center_y, center_x, radius in zip(cy, cx, radii):
    circy, circx = circle_perimeter(center_y, center_x, radius,
                                    shape=img_rgb.shape)
    img_rgb[circy, circx] = (220, 20, 20)

fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(8, 4))
ax0.imshow(img_rgb)
ax1.imshow(edges)
fig.tight_layout()

plt.show()

Please check the behavior of these plots, with different sigmas. Maybe one (or some) of them could solve your issue there. Please let us know :slightly_smiling_face:

grlee77 commented 2 years ago

comments moved over from Discussion

(we plan to close Discussions and move existing ones back to issues)

rfezzani on Oct 21, 2021 @ashbrin did you found a valid sigma parameter as suggested @alexdesiqueira?

@ashbrin on Oct 21, 2021 I haven't had a chance to play around with the sigma parameter but will do so soon. Thanks for all your efforts.