如何从手图像获取特征向量

时间:2018-10-29 10:10:56

标签: python python-3.x opencv machine-learning computer-vision

我有一个经过处理的手形图像,我需要计算每个手指的长度和宽度。请在下面找到我的代码。我已经附上了手部图像的样本。我已经能够将图像转换为灰度并删除背景。

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()

我需要计算图像中的每个手指长度,这将是我提取的特征。

enter image description here

1 个答案:

答案 0 :(得分:1)

您可以使用approxPolyDP代替convexHullconvexityDefects使用轮廓简化:

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)