Gestenerkennung basierend auf opencv

Hallo zusammen, ich bin ein Bachelor-Student und meine Hauptstudienrichtung ist Computer Vision und künstliche Intelligenz. Nach dem aktuellen Lernfortschritt bin ich nur Xiaobai. Ich schreibe hier meine eigenen Programme auf, teile sie mit Ihnen und dokumentiere mein Wachstum.
Fügen Sie hier eine Bildbeschreibung ein

Was ich heute mit Ihnen teile, ist die Gestenerkennung basierend auf OpenCv.

Ideenanalyse

Nehmen Sie das Bild auf, finden Sie die Hand im Bild und führen Sie dann eine Reihe geschlossener Operationen durch: Rauschunterdrückung und Glättung, Kontursuche und Erkennung konvexer Fehler. (Wenn Sie diese Vorgänge nicht ganz verstehen, machen Sie sich keine Sorgen, ich werde versuchen, sie im folgenden Quellcode zu erklären.)
Beurteilen Sie dann die Anzahl der Finger anhand der Anzahl der konvexen Hüllendefekte.

Probleme vorliegen

Der obige Prozess kann mit Hilfe der OpenCV-Bibliothek leicht realisiert werden, bereitet jedoch bei der Umsetzung Kopfschmerzen.

Das Auffinden der Hand im Bild ist sehr mühsam. Zu Beginn wird gemäß der Methode im Buch das eingelesene Bild vom BGR- in den HSV-Modus konvertiert und der Hautfarbbereich der Hand anhand des HSV bestimmt Die Hand wird vom Bild getrennt. Der Code lautet wie folgt:

//设置肤色范围,该范围的数值是百度出来的人体肤色范围
lower_skin = np.array([0,28,70],dtype = np.uint8)
upper_skin = np.array([20,255,255],dtype = np.uint8)
//根据肤色范围进行手的查找,
//cv2.inRange函数会将图像内不在该范围区域设置为黑色
mask = cv2.inRange(img_hsv,lower_skin,upper_skin)
//但是该方法的效果不理想,找出的手部不准确

Ich habe noch einmal im Internet gesucht und eine bessere Methode als HSV gefunden: Ellipsen-Hautfarbenerkennung

//这里我写成了一个类
class check_skin():
    def __init__(self):
        // 创建椭圆模型
        self.ellipse_mode = np.zeros((256, 256), dtype=np.uint8)
        /// 在图像上绘制白色椭圆
        cv2.ellipse(self.ellipse_mode, (113, 155), (23, 15), 43, 0, 360, (255, 255, 255), -1)
    def check_finger(self,path):
        img = cv2.imread(path, cv2.IMREAD_COLOR)
        // 图像皮肤掩膜创建
        skin_mask = np.zeros(img.shape[:2], dtype=np.uint8)
        // 将图像转换为YCBCR
        img_ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCR_CB)
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
                cr = img_ycrcb[i, j][1]
                cb = img_ycrcb[i, j][2]
                if self.ellipse_mode[cr, cb] > 0:
                    skin_mask[i, j] = 255
        img = cv2.bitwise_and(img,img,mask = skin_mask)
        return img

Diese Methode ist viel besser als der von HSV erkannte Handeffekt und die Renderings werden nicht angezeigt. Wenn Sie interessiert sind, können Sie selbst experimentieren.
Weitere Methoden zur Erkennung der Hautfarbe: Klicken Sie bitte hier

Nachdem das Problem der Handerkennung gelöst ist, möchte ich über den Prozess der Gestenerkennung sprechen.
Verstehen Sie zunächst die konvexe Hülle und die konvexen Defekte.

Der rote Punkt ist die konvexe Hülle, der blaue Punkt ist der tiefste Punkt des konvexen Defekts (d. h. der Punkt mit dem größten Abstand vom Randpunkt zur konvexen Hülle) und der grüne Punkt ist die Kontur. Der Bereich zwischen Rot und Grün ist ein konvexer Defekt. Fügen Sie hier eine Bildbeschreibung ein
Dann verwenden wir die Funktion: cv2.convexityDefects, convexityDefects: Ausgabeparameter, das Endergebnis der Erkennung, ein Array zurückgeben, wobei jede Zeile den Wert [Startpunkt, Endpunkt, am weitesten entfernter Punkt, ungefährer Abstand zum am weitesten entfernten Punkt] enthält. Die ersten drei Punkte sind alles Konturindizes. Die Bedeutung der ersten drei Werte ist: der Startpunkt des konvexen Defekts, der Endpunkt des konvexen Defekts, der tiefste Punkt des konvexen Defekts (d. h. der Punkt mit dem größten Abstand vom Randpunkt zum Die konvexe Hülle ist der blaue Punkt in der obigen Abbildung. Anschließend wird das Array entsprechend der
Konvexität zurückgegebenDefekte Die ersten drei Werte in jeder Zeile bilden ein Dreieck, da der Winkel des Dreiecks, das beim Strecken des menschlichen Fingers gebildet wird, immer kleiner ist als 90 Grad, um konvexe Defekte zu entfernen, die nicht zu den Fingern gehören, und dann die Anzahl der konvexen Defekte unter 90 Grad zu zählen, plus 1 ist die Anzahl der Finger.
Es ist nicht möglich, konvexe Defekte zu zählen, wenn die Anzahl der hervorstehenden Finger eins und null beträgt, wie in der Abbildung gezeigt: Zu
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
diesem Zeitpunkt sollten die Kontur und die Fläche der konvexen Hülle gezählt werden und die proportionale Beziehung sollte bestehen eingestellt, um die Situation zu beurteilen, in der die Finger 1 und 0 sind.

der Code

import numpy as np
import cv2
import time
import math
#将肤色检测的椭圆模型设计为类
class check_skin():
    def __init__(self):
        # 创建椭圆模型
        self.ellipse_mode = np.zeros((256, 256), dtype=np.uint8)
        # 在图像上绘制白色椭圆
        cv2.ellipse(self.ellipse_mode, (113, 155), (23, 15), 43, 0, 360, (255, 255, 255), -1)
    def check_finger(self,path):
        img = cv2.imread(path, cv2.IMREAD_COLOR)
        # 图像皮肤掩膜创建
        skin_mask = np.zeros(img.shape[:2], dtype=np.uint8)
        # 将图像转换为YCBCR
        img_ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCR_CB)
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
                cr = img_ycrcb[i, j][1]
                cb = img_ycrcb[i, j][2]
                if self.ellipse_mode[cr, cb] > 0:
                    skin_mask[i, j] = 255
        img = cv2.bitwise_and(img,img,mask = skin_mask)
        return img
 #将类初始化为对象
check_finger = check_skin()
#这个列表储存图片名称
img_path = ['zero','one','two','three','four','five']

for path in img_path:
	#图片地址合成以及椭圆模型检测
    finger_img = check_finger.check_finger(path+'.JPG')

    #转换为灰度图像
    finger_img_gray = cv2.cvtColor(finger_img,cv2.COLOR_BGR2GRAY)
    #阈值函数转化为二值图像
    _,finger_img_binary = cv2.threshold(finger_img_gray,50,255,cv2.THRESH_BINARY)
    #进行闭运算
    kernel = np.ones((4,4),dtype = np.uint8)
    finger_img_binary = cv2.morphologyEx(finger_img_binary,cv2.MORPH_CLOSE,kernel,iterations = 2)
    #高斯滤波进行去噪平滑
    finger_img_binary = cv2.GaussianBlur(finger_img_binary,(3,3),50)
    #轮廓查找
    contours, hierarchy = cv2.findContours(finger_img_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    area_cont = cv2.contourArea(contours[0])
    #凸缺陷检测
    hull1 = cv2.convexHull(contours[0])
    area_hull = cv2.contourArea(hull1)
    #根据轮廓面积和轮廓凸包面积的比例来确定zero和one
    percentage = (area_hull-area_cont)/area_cont
    print(percentage)
    hull = cv2.convexHull(contours[0], returnPoints=False)
    convex = cv2.convexityDefects(contours[0],hull)
    #用来统计小于90的角的个数
    count = 0
    for i in range(convex.shape[0]):
        s,e,f,d = convex[i][0]
        start = contours[0][s][0]
        end = contours[0][e][0]
        far = contours[0][f][0]
        #计算三角形的三边的长度
        a = math.sqrt((start[0]-far[0])**2+(start[1]-far[1])**2)
        b = math.sqrt((end[0]-far[0])**2+(end[1]-far[1])**2)
        c = math.sqrt((start[0]-end[0])**2+(start[1]-end[1])**2)
        #计算角度
        angle = math.acos((a**2+b**2-c**2)/(2*a*b))*57
        #画出角度
        cv2.line(finger_img,start,far,(0,255,0),2)
        cv2.line(finger_img,end,far,(0,255,0),2)
        # #在角上放上角的度数
        # cv2.putText(finger_img,str(angle),far,cv2.FONT_HERSHEY_COMPLEX,1,(0,255,0),1)
        #判断角度小于九十度的角的个数
        if angle<90:
            count += 1
    if count == 0 :
        if percentage < 0.2 :
            cv2.putText(finger_img,str(count),(50,20),cv2.FONT_HERSHEY_COMPLEX,1,(0,255,0),1)
        else:
            cv2.putText(finger_img, str(count+1), (50,20), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 1)
    else:
        cv2.putText(finger_img, str(count+1), (50,20), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 1)

    cv2.imshow(path,finger_img)
    cv2.waitKey(0)

cv2.destroyAllWindows()

Ende

Später habe ich zufällig die Gestenerkennungsbibliothek Mediapipe im Internet entdeckt und diese Bibliothek dann verwendet, um ein Gestenerkennungsprogramm neu zu schreiben. Wenn Sie mehr wissen möchten, lesen Sie bitte meinen nächsten Artikel.

Schließlich ist die Schöpfung nicht einfach, bitte unterstützen Sie mich. Ich bin auch ein Neuling und begrüße die Anleitung und Kommunikation aller.
Fügen Sie hier eine Bildbeschreibung ein

Supongo que te gusta

Origin blog.csdn.net/m0_59151709/article/details/128990444
Recomendado
Clasificación