I am using openCV to draw a circle over an image(with the mouse) and then I use the radius and center of the circle to segment a portion of the image using the random_walker() method in skimage. I have an issue with the coordinates of the pixels extracted using the mouse click. Whenever a circle is drawn over the image with the mouse, the pixel coordinates of the circle shifts a little from the actual position of the circle drawn. Please see the images: Images
As you can see, first image is the circle drawn with the mouse and the second image is the pixel coordinates of the circle the random walker extracts(used to segment the vertebrae). Since the coordinates of the circle shifts, the part of the image segmented becomes wrong. This is my code:
import math
import matplotlib.pyplot as plt
import numpy as np
from skimage import io
from skimage.color import rgb2gray
from skimage import data
import skimage.segmentation as seg
import skimage.draw as draw
import cv2
#To store center and cicumference points
circle_center = (0,0)
circumference = (0,0)
def image_show(image, nrows=1, ncols=1, cmap='gray'):
fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=(8,8))
ax.imshow(image, cmap='gray')
ax.axis('off')
return fig, ax
def circle_points(resolution, center, radius):
#Generate points which define a circle on an image.Centre refers to the centre of the circle
radians = np.linspace(0, 2*np.pi, resolution)
c = center[1] + radius*np.cos(radians)#polar co-ordinates
r = center[0] + radius*np.sin(radians)
return np.array([c,r]).T
def drawCircle(event, x, y, flags, params):
#referencing global variables
global circle_center, circumference
#action to be taken when left mouse button is pressed
if(event == cv2.EVENT_LBUTTONDOWN):
circle_center = (x,y)
#draw the center
cv2.circle(imageClone, circle_center, 2, (0, 0, 255), 1, cv2.LINE_AA)
#action to be taken when left mouse button is released
elif event == cv2.EVENT_LBUTTONUP:
circumference = (x,y)
#calculate radius of the circle
radius1 = math.sqrt(math.pow(circle_center[0] - circumference[0], 2)+ math.pow(circle_center[1] - circumference[1], 2))
print(radius1)
#draw the circle
cv2.circle(imageClone, circle_center, int(radius1), (0, 0, 255), 1, cv2.LINE_AA)
cv2.imshow("image", imageClone)
points = circle_points(200, [y,x], radius1)[:-1]
image_labels = np.zeros((image_gray.shape), dtype=np.uint8)
indices = draw.circle_perimeter(y,x,5)
image_labels[indices] = 1
image_labels[points[:,1].astype(np.int), points[:,0].astype(np.int)] = 2
image_show(image_labels)
image_segmented = seg.random_walker(image_gray, image_labels, beta = 3500)
#Check our results
fig, ax = image_show(image)
ax.imshow(image_segmented == 1, alpha=0.3)
plt.show()
image = cv2.imread('image.png')
image_gray = rgb2gray(image)
#Create a clone of input image to work on
imageClone = image_gray.copy()
#displaying the image
cv2.imshow('image', image)
#setup callback for mouse event
cv2.setMouseCallback("image", drawCircle)
while True:
cv2.imshow('image', imageClone)
#wait for a widow to be closed
k = cv2.waitKey(100)
if k == 27:
print('ESC')
cv2.destroyAllWindows()
break
if cv2.getWindowProperty('image',cv2.WND_PROP_VISIBLE) < 1:
break
#close all the opened windows
cv2.destroyAllWindows()
Can someone tell me a proper solution to solve this?
It's subtle! You're drawing the second circle centered on mouse release (indices = draw.circle_perimeter(y,x,5)
, but the first circle on mouse down.