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

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

本文介绍使用 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 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。