我有一个经过处理的手形图像,我需要计算每个手指的长度和宽度。请在下面找到我的代码。我已经附上了手部图像的样本。我已经能够将图像转换为灰度并删除背景。
import cv2
import numpy as np
import copy
import math
#import image_process_utils
#import frequency_filters
# Constants
blurValue = 41
threshold = 70
def removeBG(frame):
fgmask = bgModel.apply(frame,learningRate=learningRate)
# kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
# res = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
kernel = np.ones((3, 3), np.uint8)
fgmask = cv2.erode(fgmask, kernel, iterations=1)
res = cv2.bitwise_and(frame, frame, mask=fgmask)
return res
def calculateFingers(res,drawing): # -> finished bool, cnt: finger count
# convexity defect
hull = cv2.convexHull(res, returnPoints=False)
if len(hull) > 3:
defects = cv2.convexityDefects(res, hull)
if type(defects) != type(None): # avoid crashing. (BUG not found)
cnt = 0
print(defects.shape[0])
for i in range(defects.shape[0]): # calculate the angle
s, e, f, d = defects[i][0]
start = tuple(res[s][0])
end = tuple(res[e][0])
far = tuple(res[f][0])
a = math.sqrt((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2)
b = math.sqrt((far[0] - start[0]) ** 2 + (far[1] - start[1]) ** 2)
c = math.sqrt((end[0] - far[0]) ** 2 + (end[1] - far[1]) ** 2)
angle = math.acos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c)) # cosine theorem
if angle <= math.pi / 2: # angle less than 90 degree, treat as fingers
cnt += 1
cv2.circle(drawing, far, 8, [211, 84, 0], -1)
return True, cnt
return False, 0
#Reading the image
img = cv2.imread("images/3.jpg")
img = cv2.resize(img, (0,0), fx=0.5, fy=0.5)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (blurValue, blurValue), 0)
ret, thresh = cv2.threshold(blur, threshold, 255, cv2.THRESH_BINARY)
thresh1 = copy.deepcopy(thresh)
_, contours, heirarchy = cv2.findContours(thresh1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
length = len(contours)
maxArea = -1
if length >0:
for i in range(length):
temp = contours[i]
area = cv2.contourArea(temp)
if area> maxArea:
maxArea = area
ci = i
res = contours[ci]
drawing = np.zeros(img.shape, np.uint8)
cv2.drawContours(drawing, [res], 0, (0, 255, 0), 2)
isFinishCal,cnt = calculateFingers(res,drawing)
cv2.imshow('out', drawing)
cv2.waitKey(0)
cv2.destroyAllWindows()
我需要计算图像中的每个手指长度,这将是我提取的特征。
答案 0 :(得分:1)
您可以使用approxPolyDP
代替convexHull
和convexityDefects
使用轮廓简化:
import cv2
import numpy as np
img = cv2.imread('zBs8Vm.jpg',0)
#make image black and white
ret,img = cv2.threshold(img,90,255,0)
#getting max contour
_, contours, heirarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
c = max(contours, key = cv2.contourArea)
# Contnour simplification
tmp = np.zeros(img.shape, dtype = "uint8")
epsilon = 0.005*cv2.arcLength(c,True)
approx = cv2.approxPolyDP(c,epsilon,True)
cv2.drawContours(tmp, [approx], -1, 255, 3)
#Quick and dirty sharp corner detection
finger_points = []
for p in range(0,len(approx)):
#getting next and previous point at contour
p_pnt = approx[p-1][0] if p-1 >= 0 else approx[len(approx)-1][0]
c_pnt = approx[p][0]
n_pnt = approx[p+1][0] if p+1 <= len(approx)-1 else approx[0][0]
# is left corner (and not on wrist)?
if p_pnt[0] > c_pnt[0] and n_pnt[0] > c_pnt[0] and c_pnt[0] < img.shape[0]*0.8:
point = list(c_pnt)
#finger length as max of left and right side line
length = max( ((c_pnt[0]-p_pnt[0])**2+(c_pnt[1]-p_pnt[1])**2)**0.5,
((c_pnt[0]-n_pnt[0])**2+(c_pnt[1]-n_pnt[1])**2)**0.5 )
finger_points.append(point + [length])
cv2.circle(img, tuple(approx[p][0]), 15, 128)
cv2.circle(tmp, tuple(approx[p][0]), 15, 128)
#sort in finger order
finger_points.sort(key=lambda x: x[1])
print(finger_points)
#Simplified contour
cv2.imwrite('simpcon.bmp', tmp)
#Finger ends points
cv2.imwrite('fp.bmp', img)