Python OpenCV 实现手势识别:肤色检测与轮廓提取实战

季宁
季宁
发布时间:2026-10-15 | 7人浏览过
原创

本文介绍使用 Python 和 OpenCV 实现基础手势识别的方法。核心步骤包括通过摄像头获取视频流,利用 YCrCb 颜色空间进行椭圆肤色模型检测以分割手部区域,并结合高斯模糊与 Otsu 阈值处理优化图像。随后通过 findContours 提取轮廓,利用 sorted 函数按面积排序筛选最大轮廓作为手部,最终绘制轮廓完成识别。

前言:

网络上存在多种手势处理的实验案例,本文旨在简要演示其实现过程。主要依赖的技术栈包括 OpenCV 库、Python 基础语法以及图像处理的基础知识。

获取视频(摄像头)

该部分功能较为直接,主要任务是初始化并获取摄像头视频流。

cap = cv2.VideoCapture("C:/Users/lenovo/Videos/1.mp4")#读取文件
#cap = cv2.VideoCapture(0)#读取摄像头
while(True):
    ret, frame = cap.read()    key = cv2.waitKey(50) & 0xFF
    if key == ord('q'):
      break
cap.release()
cv2.destroyAllWindows()

肤色检测

本方案采用椭圆肤色检测模型进行手部区域的初步分割。

在 RGB 色彩空间中,人脸及手部的肤色受环境亮度影响显著,导致肤色像素与非肤色像素难以有效分离。处理后的图像中,肤色点往往呈离散分布,夹杂大量非肤色噪声,这给后续的肤色区域标定(如人脸或眼睛定位)带来困难。若将 RGB 空间转换为 YCrCb 空间,则可忽略亮度分量 Y 的影响,因为该空间对亮度变化不敏感,肤色像素会呈现良好的聚类特性。此时,三维空间问题简化为二维 CrCb 平面上的分布,肤色点会形成特定的几何形状,例如人脸区域或手臂形态,从而便于后续处理。

def A(img):
    YCrCb = cv2.cvtColor(img, cv2.COLOR_BGR2YCR_CB) #转换至YCrCb空间
    (y,cr,cb) = cv2.split(YCrCb) #拆分出Y,Cr,Cb值
    cr1 = cv2.GaussianBlur(cr, (5,5), 0)
    _, skin = cv2.threshold(cr1, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) #Ostu处理
    res = cv2.bitwise_and(img,img, mask = skin)
    return res

轮廓处理

轮廓处理主要涉及两个核心函数:cv2.findContours 用于查找轮廓,cv2.drawContours 用于绘制轮廓。具体用法可参考官方文档,此处不再赘述。该步骤的关键难点在于视频帧中通常存在多个轮廓,而我们需要准确提取出手部轮廓。为此,需利用 sorted 函数对提取到的所有轮廓按面积进行排序,并选取面积最大的轮廓作为手部目标。

def B(img):
    #binaryimg = cv2.Canny(Laplacian, 50, 200) #二值化,canny检测
    h = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE) #寻找轮廓
    contour = h[0]
    contour = sorted(contour, key = cv2.contourArea, reverse=True)#已轮廓区域面积进行排序
    #contourmax = contour[0][:, 0, :]#保留区域面积最大的轮廓点坐标
    bg = np.ones(dst.shape, np.uint8) *255#创建白色幕布
    ret = cv2.dra
wContours(bg,contour[0],-1,(0,0,0),3) #绘制黑色轮廓
    return ret

全部代码:

""" 从视频读取帧保存为图片"""
import cv2
import numpy as np
cap = cv2.VideoCapture("C:/Users/lenovo/Videos/1.mp4")#读取文件
#cap = cv2.VideoCapture(0)#读取摄像头
#皮肤检测
def A(img):

    YCrCb = cv2.cvtColor(img, cv2.COLOR_BGR2YCR_CB) #转换至YCrCb空间
    (y,cr,cb) = cv2.split(YCrCb) #拆分出Y,Cr,Cb值
    cr1 = cv2.GaussianBlur(cr, (5,5), 0)
    _, skin = cv2.threshold(cr1, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) #Ostu处理
    res = cv2.bitwise_and(img,img, mask = skin)
    return res
def B(img):
    #binaryimg = cv2.Canny(Laplacian, 50, 200) #二值化,canny检测
    h = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE) #寻找轮廓
    contour = h[0]
    contour = sorted(contour, key = cv2.contourArea, reverse=True)#已轮廓区域面积进行排序
    #contourmax = contour[0][:, 0, :]#保留区域面积最大的轮廓点坐标
    bg = np.ones(dst.shape, np.uint8) *255#创建白色幕布
    ret = cv2.drawContours(bg,contour[0],-1,(0,0,0),3) #绘制黑色轮廓
    return ret
while(True):
    ret, frame = cap.read()
    #下面三行可以根据自己的电脑进行调节
    src = cv2.resize(frame,(400,350), interpolation=cv2.INTER_CUBIC)#窗口大小
    cv2.rectangle(src, (90, 60), (300, 300 ), (0, 255, 0))#框出截取位置
    roi = src[60:300 , 90:300]  # 获取手势框图

    res = A(roi)  # 进行肤色检测
    cv2.imshow("0",roi)
    gray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY)
    dst = cv2.Laplacian(gray, cv2.CV_16S, ksize = 3)
    Laplacian = cv2.convertScaleAbs(dst)
    contour = B(Laplacian)#轮廓处理
    cv2.imshow("2",contour)

    key = cv2.waitKey(50) & 0xFF
    if key == ord('q'):
            break
cap.release()
cv2.destroyAllWindows()

到此这篇关于 Python 如何利用 opencv 实现手势识别的文章就介绍到这了,更多相关 Python手势识别内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表