Reputation: 11
using edge detection using hough detection
I'm using Hough circle detection to detect a circle over a binary optic cup region. Using the code below, I can fill in the circle but the lines of canny edge detection shows up inside the filled image. How do I fix that?
import numpy as np
import matplotlib.pyplot as plt
from skimage import data, color
from skimage.transform import hough_circle, hough_circle_peaks
from skimage.feature import canny
from skimage.draw import circle_perimeter
from skimage.util import img_as_ubyte
# Read the image
cimage = cv2.imread("cupcluster.jpg")
# Convert the image to grayscale
image = cv2.cvtColor(cimage, cv2.COLOR_BGR2GRAY)
# Perform edge detection using Canny
edges = canny(image, sigma=10, low_threshold=5, high_threshold=50)
# Detect circles using Hough Circle Transform
hough_radii = np.arange(78, 100, 2)
hough_res = hough_circle(edges, hough_radii)
accums, cy, cx, radii = hough_circle_peaks(hough_res, hough_radii, total_num_peaks=1)
# Create an RGB image from the grayscale image
image_rgb = color.gray2rgb(image)
# Iterate over each pixel in the image
for y in range(image.shape[0]):
for x in range(image.shape[1]):
# Check if the pixel is inside any of the detected circles
inside_circle = False
for center_y, center_x, radius in zip(cy, cx, radii):
if (x - center_x)**2 + (y - center_y)**2 <= radius**2:
inside_circle = True
break
# If the pixel is inside a circle and is black, set it to white
if inside_circle and image[y, x] == 0:
image_rgb[y, x] = (255, 255, 255)
# If the pixel is outside a circle and is white, set it to black
elif not inside_circle and image[y, x] == 255:
image_rgb[y, x] = (0, 0, 0)
# Display the result
plt.imshow(image_rgb)
plt.title('Image with Filled Circles')
plt.axis('off')
plt.show()
This is the code I've used to transform and fill in. and this is the input I'm getting filled Image with edge lines
Upvotes: 1
Views: 83
Reputation: 1419
Pay attention on your checks of whether the pixel is inside a circle.
image[y, x] == 0
and image[y, x] == 255
conditions are redundant causing the bug, just remove them, i.e.
# If the pixel is inside a circle and is black, set it to white
if inside_circle:
image_rgb[y, x] = (255, 255, 255)
# If the pixel is outside a circle and is white, set it to black
elif not inside_circle:
image_rgb[y, x] = (0, 0, 0)
Since, in that conditions, your are comparing grayscale version of your original image, it is not necessary true that the pixel in that location will have 0 or 255 values.
Alternatively, to draw the circles you can use skimage
built-in draw.disk
function like this:
# Create an RGB blank image from the original image
image_rgb = np.zeros_like(cimage)
# Iterating over each detected circles and drawing them
for center_y, center_x, radius in zip(cy, cx, radii):
rr, cc = disk((center_y, center_x), radius, shape=blank.shape)
image_rgb[rr, cc] = 255
Or, if you want "to draw of your own", you can use numpy indexing, described here, like this:
# Create an RGB blank image from the original image
image_rgb = np.zeros_like(cimage)
# Iterating over each detected circles and drawing them
nrows, ncols = image.shape
row, col = np.ogrid[:nrows, :ncols]
for center_y, center_x, radius in zip(cy, cx, radii):
mask = ((row - center_y)**2 + (col - center_x)**2 <= radius**2)
image_rgb[mask] = 255
Below are full versions.
Version 1 (skimage.draw.disk):
import numpy as np
import matplotlib.pyplot as plt
from skimage import data, color
from skimage.transform import hough_circle, hough_circle_peaks
from skimage.feature import canny
from skimage.draw import circle_perimeter
from skimage.util import img_as_ubyte
from skimage.draw import disk
# Read the image
cimage = cv2.imread("cupcluster.jpg")
# Convert the image to grayscale
image = cv2.cvtColor(cimage, cv2.COLOR_BGR2GRAY)
# Perform edge detection using Canny
edges = canny(image, sigma=10, low_threshold=5, high_threshold=50)
# Detect circles using Hough Circle Transform
hough_radii = np.arange(78, 100, 2)
hough_res = hough_circle(edges, hough_radii)
accums, cy, cx, radii = hough_circle_peaks(hough_res, hough_radii, total_num_peaks=1)
# Create an RGB blank image from the original image
image_rgb = np.zeros_like(cimage)
# Iterating over each detected circles and drawing them
for center_y, center_x, radius in zip(cy, cx, radii):
rr, cc = disk((center_y, center_x), radius, shape=blank.shape)
image_rgb[rr, cc] = 255
# Display the result
plt.imshow(image_rgb)
plt.title('Image with Filled Circles')
plt.axis('off')
plt.show()
Version 2 (numpy indexing):
import numpy as np
import matplotlib.pyplot as plt
from skimage import data, color
from skimage.transform import hough_circle, hough_circle_peaks
from skimage.feature import canny
from skimage.draw import circle_perimeter
from skimage.util import img_as_ubyte
# Read the image
cimage = cv2.imread("cupcluster.jpg")
# Convert the image to grayscale
image = cv2.cvtColor(cimage, cv2.COLOR_BGR2GRAY)
# Perform edge detection using Canny
edges = canny(image, sigma=10, low_threshold=5, high_threshold=50)
# Detect circles using Hough Circle Transform
hough_radii = np.arange(78, 100, 2)
hough_res = hough_circle(edges, hough_radii)
accums, cy, cx, radii = hough_circle_peaks(hough_res, hough_radii, total_num_peaks=1)
# Create an RGB blank image from the original image
image_rgb = np.zeros_like(cimage)
# Iterating over each detected circles and drawing them
nrows, ncols = image.shape
row, col = np.ogrid[:nrows, :ncols]
for center_y, center_x, radius in zip(cy, cx, radii):
mask = ((row - center_y)**2 + (col - center_x)**2 <= radius**2)
image_rgb[mask] = 255
# Display the result
plt.imshow(image_rgb)
plt.title('Image with Filled Circles')
plt.axis('off')
plt.show()
Both versions have better time complexity.
Upvotes: 0