I have an image in which I am trying to apply Hough circle transforms to the circular objects in view.
I am having difficulty finding a circle that fits the outer shadow of the cyclinder. What can be done to properly segment this shadow and easily fit a circle to it?
Code:
img = cv2.medianBlur(im,7)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
plt.imshow(cimg)
plt.show()
circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,20,
param1=50,param2=150,minRadius=100,maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
# draw the outer circle
cv2.circle(cimg,(i[0],i[1]),i[2],(255,0,0),10)
# draw the center of the circle
cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),20)
radius = i[2]
print 'radius', radius, 'px'
plt.imshow(cimg)
plt.show()
I'm just going to write out the code and not go through it because there's a lot of functions and I would hate to assume what you know or don't know and spend a long time doing the write-up. If you have any questions feel free to ask and I'll add them in the post.
You asked to fit a circle to the crescent shadows, so I've fitted circles to the shadows. It's important to realize that in some kind of production code which would, I imagine, have to process a lot of images of this nature it would be necessary to refine the circles fitted. In particular any kind of structural analysis of this type is just worried about fitting the given shape to the pixels, not that the object in question is what you're looking for.
I've intentionally left the wrongly-fitted circle in there. I would suggest going for the convexHull, or Haar detector or shape matching depending on what exactly you're interested in.
import cv2
import numpy as np
img = cv2.imread("orig.png", cv2.IMREAD_GRAYSCALE)
ret, thresh = cv2.threshold(img, 80, 255, cv2.THRESH_BINARY_INV)
ero = cv2.erode(thresh, np.ones((5,5)))
dil = cv2.dilate(ero, np.ones((5,5)))
img, contours, hierarchy = cv2.findContours(dil, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_NONE)
#just for drawing purposes, the cimg is not really required
cimg = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
for cnt in contours:
(x, y), radius = cv2.minEnclosingCircle(cnt)
center = (int(x), int(y))
radius = int(radius)
cv2.circle(cimg, center, radius, (255, 0, 0), 1)
The output image I got was
Both crescents are fitted to correctly with the bottom one matching the outside of the tank and not the crescent exactly. You could do a sort of hysteresis tracking and shift that circle until it's outer edge is precisely at the crescent fairly consistently though.
There's an additional circle that can be removed if you tune the parameters just right but filtering the exact circles you need is up to you. F.e. if you only want the top crescent ask for the smallest y
coordinate, if all the shadows are as big as these you can ask for only circles of radii larger than some threshold etc...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With