Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hough circle transform to circular shadow

Tags:

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()
like image 909
Sam Avatar asked Jul 25 '17 10:07

Sam


1 Answers

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

enter image description here

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...

like image 140
ljetibo Avatar answered Sep 25 '22 11:09

ljetibo