Reputation: 99
Say I want to detect an object of unknown size or rotation but I know what the object is, how would I go about detecting and outlining them in the image. For my example, I want to detect all the hearts in the following image.
How would I go about detecting these objects? I have tried using the following code, but it doesn't detect the hearts properly.
r=200
img=cv2.imread("hearts.jpg",0)
h,w=img.shape
r//=3
Y,X,R=np.mgrid[:2*r,:2*r,:r]
cone=1-(R-np.hypot(X-r,Y-r))**2
cone[cone<0]=0
votes=np.zeros((h+2*r,w+2*r,r),dtype=np.float64)
I= cv2.Canny(img,10,50)
show(I)
y,x=np.where(I>128)
for i,j in zip(x,y):
votes[j:j+2*r,i:i+2*r]+=cone
i=0
votes[:,:,:10]=0
R=np.mgrid[:r]
R=R[None,None,:]
votes[:,:,10:]/=R[:,:,10:]
maxValue=votes.max()
y,x,z=np.where(votes>maxValue*.75)
img=cv2.imread("hearts.jpg")
for i,j,k in zip(x,y,z):
i=int((i-r)*3)
j=int((j-r)*3)
k=int((k)*3)
cv2.circle(img,(i,j),k,(0,255,0),5)
show(img)
How would I go about detecting the hearts, no matter the scale or rotation, using Hough Object Detection?
Upvotes: 1
Views: 421
Reputation: 10682
If you are after simple shapes like hearts in your sample image, try Hu moments. Hu moments are invariant w.r.t translation, rotation and scaling. See the Wiki page on image moments for details. You can easily do shape matching with Hu moments in opencv using matchShapes.
EDIT:
But this does not answer your question of using Hough transform. To use the Hough approach, you can use Hu moments as the feature space and perform the voting, then find the local maxima. So, in my opinion, the feature space you have chosen for your task is inadequate to address your requirements. Using a different space, like the Hu moments, you can achieve this if you do want to go with the Hough approach, but this would be a bit tougher because now you have 7 dimensions.
This is just a demo of finding matches using the first approach, but it isn't relevant if your interest is in Hough approach.
For simplicity, in the code below I'm using a hardcoded threshold to find matches knowing that contour1 is a heart.
im = cv.imread('hearts.png', 0)
_, bw = cv.threshold(im, 0, 255, cv.THRESH_OTSU | cv.THRESH_BINARY_INV)
contours, _ = cv.findContours(bw, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE)
matches = np.zeros((im.shape[0], im.shape[1], 3), dtype=np.uint8)
for i in range(len(contours)):
ret = cv.matchShapes(contours[i], contours[1], cv.CONTOURS_MATCH_I1, 0.0)
if ret < 0.015:
cv.drawContours(matches, contours, i, (255, 255, 255), -1)
Thresholded:
Matches:
Upvotes: 2