-1

I'm doing finger detection i.e. the fingertips using VGA camera. I have used HSV and image thresholding and I am able to detect the fingertips.

The Problem: I can now find the centroid of the white spot in a black and white image if there is only one white spot (if I place just one finger); but if I place multiple fingers more white spots will come in the final image. So I want to find each centroid separately.

I want to find all centroids of each of the white spots i.e. if I place more than one finger in front of the camera. Look at the code below

thresholded_img =  cv.CreateImage(cv.GetSize(hsv_img), 8, 1) 
cv.InRangeS(hsv_img, (0,0,200), (0,0,255), thresholded_img)
moments = cv.Moments(cv.GetMat(thresholded_img,1), 0) 
area = cv.GetCentralMoment(moments, 0, 0) 
x = cv.GetSpatialMoment(moments, 1, 0)/area 
y = cv.GetSpatialMoment(moments, 0, 1)/area 
posY=y
posX=x

Here thresholded_img is a black and white image where the fingertips alone is represented as white and all other in black.

In this code if the thresholded_img contains a single white spot then I can get the x and y coordinates of the centroid of that dot correctly!

But how to find centroid of each white dots in this image?

dd

But if there is multiple white dots in the thresholded image then it's finding wrong centroid!

How can I change the above code to find (x,y coordinates) separate centroid of each white dots in a single frame (image)?

Refer this image please. http://www.csksoft.net/data/pic/laserkbd/036.jpg

Alessandro Jacopson
  • 18,047
  • 15
  • 98
  • 153
user3429616
  • 371
  • 1
  • 4
  • 8

1 Answers1

2

I tested the following code with the image you uploaded.

I got the following textual output:

cv2 version: 2.4.4
centroids: [(580, 547), (437, 546), (276, 545), (115, 545), (495, 425), (334, 424), (174, 424), (24, 423), (581, 304), (437, 303), (277, 303), (117, 302), (495, 182), (334, 181), (174, 181), (25, 181), (581, 60), (438, 59), (277, 59), (117, 59)]

and this image:

enter image description here

#!/usr/bin/env python

import cv2

img = cv2.imread('HFOUG.jpg',cv2.CV_LOAD_IMAGE_GRAYSCALE)
_,img = cv2.threshold(img,0,255,cv2.THRESH_OTSU)
h, w = img.shape[:2]

contours0, hierarchy = cv2.findContours( img.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
moments  = [cv2.moments(cnt) for cnt in contours0]
# Nota Bene: I rounded the centroids to integer.
centroids = [( int(round(m['m10']/m['m00'])),int(round(m['m01']/m['m00'])) ) for m in moments]

print 'cv2 version:', cv2.__version__
print 'centroids:', centroids

for c in centroids:
    # I draw a black little empty circle in the centroid position
    cv2.circle(img,c,5,(0,0,0))

cv2.imshow('image', img)
0xFF & cv2.waitKey()
cv2.destroyAllWindows()

See also this answer https://stackoverflow.com/a/9059648/15485 to the question Python OpenCV - Find black areas in a binary image

Community
  • 1
  • 1
Alessandro Jacopson
  • 18,047
  • 15
  • 98
  • 153
  • 1
    Here it gives a float division by zero when it finds a spot... Note that my spot isn't 100% filled, maybe that's why. – Fusseldieb Jan 24 '20 at 12:19
  • @Fusseldieb I have tested the code only on the image of the question. According to `cv::Moments Class Reference` in Image Processing » Structural Analysis and Shape Descriptors https://docs.opencv.org/4.2.0/d8/d23/classcv_1_1Moments.html *Since the contour moments are computed using Green formula, you may get seemingly odd results for contours with self-intersections, e.g. a zero area (`m00`) for butterfly-shaped contours.* – Alessandro Jacopson Jan 24 '20 at 13:00