Python 如何从手部图像中提取特征向量

Python 如何从手部图像中提取特征向量,python,python-3.x,opencv,machine-learning,computer-vision,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):

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

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()
导入cv2
将numpy作为np导入
导入副本
输入数学
#导入图像\u进程\u实用程序
#输入频率滤波器
#常数
模糊值=41
阈值=70
def removeBG(帧):
fgmask=bgModel.apply(帧,learningRate=learningRate)
#kernel=cv2.getStructuringElement(cv2.morp_ELLIPSE,(3,3))
#res=cv2.morphologyEx(fgmask,cv2.MORPH_OPEN,kernel)
内核=np.ones((3,3),np.uint8)
fgmask=cv2.腐蚀(fgmask,内核,迭代次数=1)
res=cv2.按位_和(帧,帧,掩码=fgmask)
返回res
def calculateFingers(res,绘图):#->完成的布尔,cnt:手指计数
#凸性缺陷
外壳=cv2.凸形外壳(res,返回点=False)
如果长度(船体)>3:
缺陷=cv2.凸面缺陷(res,外壳)
如果类型(缺陷)!=类型(无):#避免碰撞。(未找到错误)
cnt=0
打印(缺陷。形状[0])
对于范围内的i(缺陷形状[0]):#计算角度
s、 e,f,d=缺陷[i][0]
start=tuple(res[s][0])
end=元组(res[e][0])
far=元组(res[f][0])
a=数学.sqrt((结束[0]-开始[0])**2+(结束[1]-开始[1])**2)
b=math.sqrt((远[0]-start[0])**2+(远[1]-start[1])**2)
c=数学sqrt((end[0]-far[0])**2+(end[1]-far[1])**2)
角度=数学.acos((b**2+c**2-a**2)/(2*b*c))#余弦定理
如果角度为0:
对于范围内的i(长度):
温度=等高线[i]
面积=cv2。轮廓面积(温度)
如果面积>最大面积:
最大面积=面积
ci=i
res=等高线[ci]
图纸=np.0(img.shape,np.uint8)
cv2.等高线图(图纸[res],0,(0,255,0),2)
isFinishCal,cnt=计算型参数(res,图纸)
cv2.imshow(“输出”,图纸)
cv2.等待键(0)
cv2.destroyAllWindows()
我需要计算图像中每个手指的长度,这将是我提取的特征


您可以通过
approxPolyDP
而不是
converxhull
converxitydefects
使用轮廓简化:

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)
导入cv2
将numpy作为np导入
img=cv2.imread('zBs8Vm.jpg',0)
#使图像黑白
ret,img=cv2。阈值(img,90255,0)
#获取最大轮廓
_,等高线,继承权=cv2.找到的轮廓(img,cv2.RETR\u外部,cv2.CHAIN\u近似值\u无)
c=最大值(轮廓,关键点=cv2.轮廓面积)
#连续简化
tmp=np.zero(img.shape,dtype=“uint8”)
ε=0.005*cv2.弧长(c,真)
近似值=cv2.approxPolyDP(c,ε,真)
cv2.等高线图(tmp,[近似值],-1255,3)
#快速而肮脏的锐角检测
手指点=[]
对于范围(0,len(近似))内的p:
#获取轮廓上的下一个和上一个点
如果p-1>=0,则p_pnt=约[p-1][0],否则约[len(约)-1][0]
c_pnt=约[p][0]
n_pnt=约[p+1][0],如果p+1 c_pnt[0]和n_pnt[0]>c_pnt[0]和c_pnt[0]
这就是StanislavIvanov bur的响应,我只想测量每个手指的长度和宽度。你能帮我们吗?