Python项目||使用OpenCV和Python实现了对手部图像的轮廓检测和凸包缺陷分析

项目简介

本项目利用OpenCV和Python实现了对手部图像的轮廓检测和凸包缺陷分析。通过检测手部轮廓和计算凸包缺陷,可以估算手指的数量并绘制相关图形,适用于图像处理和计算机视觉中的手部识别和姿态分析。

项目特点

凸包和凸包缺陷检测: 使用OpenCV的函数快速计算手部轮廓的凸包,并识别可能的手指缺陷。
HSV色彩空间转换: 利用肤色掩膜提取手部轮廓,适应不同肤色和光照条件下的图像。
图像显示与交互: 提供图像显示和交互功能,方便用户观察和调整检测结果。

实现步骤

  • 图像加载与显示: 读取手部图像并显示原始图像。
  • 肤色提取: 将图像转换为HSV色彩空间,创建肤色掩膜以便于后续轮廓检测。
  • 轮廓检测: 使用OpenCV的轮廓查找函数检测手部轮廓。
  • 凸包计算与绘制: 计算手部轮廓的凸包,并在图像上绘制凸包。
  • 凸包缺陷检测: 计算凸包的缺陷点,并根据角度判断缺陷是否为手指。
  • 结果展示: 显示绘制了凸包和手指缺陷的最终图像,标注手指数量。

使用技术

  • Python: 编程语言,主要用于脚本开发和图像处理。
  • OpenCV: 开源计算机视觉库,用于图像处理、轮廓检测和凸包分析。
  • NumPy: 数值计算库,用于处理图像数据和数学运算。

项目用途

  • 手势识别: 可用于手势控制系统的初步识别,例如识别手指的数量和位置。
  • 生物识别: 在生物识别领域中,用于手部特征的分析和认证。

使用说明

环境配置:

确保已安装Python 3.x、OpenCV和NumPy库。
可通过 pip install opencv-python numpy 安装所需库。

运行项目:

import cv2
import os
import numpy as np

# 获取脚本的绝对路径
script_path = os.path.abspath(__file__)
# 获取脚本所在的目录
script_dir = os.path.dirname(script_path)
# 更改当前工作目录到脚本所在的目录
os.chdir(script_dir)

def show_img(img, WindowsName=None):
    """
    显示图片在窗口中,并等待用户关闭窗口。

    Args:
        img (numpy.ndarray): 要显示的图片,类型为numpy数组。
        WindowsName (str, optional): 窗口名称。默认为None,此时窗口名默认为'window'。

    Returns:
        None
    """

    cv2.imshow(WindowsName, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

def detect_hand_contours_and_defects(img_path):
    """
    检测手部轮廓和缺陷。
    Args:
        img_path (str): 图片路径。
    Returns:
        None
    """
    img = cv2.imread(img_path)
    if img is None:
        print(f"Error: 图像 {img_path} 读取失败。")
        return
    # 显示原始图片
    show_img(img, WindowsName="src_img")

    # 转换为HSV色彩空间
    hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    # 提取肤色
    lower = np.array([0, 30, 100], dtype="uint8")
    upper = np.array([128, 255, 255], dtype="uint8")
    # 创建肤色掩膜
    skin_mask_hsv = cv2.inRange(hsv_img, lower, upper)
    # show_img(skin_mask_hsv, WindowsName="skin_mask")
    blurred_skin_mask = cv2.blur(skin_mask_hsv, (2,2))
    # show_img(blurred_skin_mask, WindowsName="skin_mask")
    ret, thresh = cv2.threshold(blurred_skin_mask, 0, 255, cv2.THRESH_BINARY)
    show_img(thresh, WindowsName="skin_mask")

    # 查找轮廓
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    if contours:
        max_contour = max(contours, key=lambda x: cv2.contourArea(x))
        # 绘制最大轮廓
        cv2.drawContours(img, [max_contour], -1, (0, 0, 255), 2)
        # 在原图上展示轮廓
        # show_img(img, WindowsName="max_contours")

        # 对轮廓进行凸包检测
        hull = cv2.convexHull(max_contour)
        cv2.drawContours(img, [hull], -1, (0, 255, 0), 2)   # 绘制凸包
        show_img(img, WindowsName="hull")

        # 凸包缺陷检测
        hull_detect = cv2.convexHull(max_contour, returnPoints=False)   # 返回凸包缺陷
        defects = cv2.convexityDefects(max_contour, hull_detect)
        # 如果存在缺陷,则绘制
        if defects is not None:
            cnt = 0
            for i in range(defects.shape[0]):
                s, e, f, d = defects[i, 0]   # 获取缺陷信息, s, e, f分别表示起始点、终点、最远点, d表示距离
                start = tuple(max_contour[s][0])
                end = tuple(max_contour[e][0])
                far = tuple(max_contour[f][0])
                a = np.sqrt((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2) # 计算边长
                b = np.sqrt((far[0] - start[0]) ** 2 + (far[1] - start[1]) ** 2)  # 计算边长
                c = np.sqrt((end[0] - far[0]) ** 2 + (end[1] - far[1]) ** 2)     # 计算边长

                angle = np.arccos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c))     # 计算角度

                if angle <= np.pi / 2:  # 角度小于90度,认为为手指
                    cnt += 1
                    # 绘制手指缺陷相关的图形
                    cv2.line(img, start, end, [0, 255, 0], 1)     # 绘制缺陷的起始和结束点之间的线
                    cv2.circle(img, far, 5, [255, 0, 0], -1)    # 绘制缺陷的远点(蓝色)
            
            # 仅在检测到手指缺陷时,才显示手指数量和绘制相关图形
            if cnt > 0:
                cnt += 1
                cv2.putText(img, str(cnt), (0, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2, cv2.LINE_AA)    # 在原图上绘制手指数量
    show_img(img, WindowsName="defects")

def process_hand_image(img_path):
    """
    处理手部图像。
    Args:
        img_path (str): 图片路径。
    Returns:
        None
    """
    # 读取图片
    detect_hand_contours_and_defects(img_path)


if __name__ == '__main__':
    # 测试手部图像
    img_path = "./images/hand.jpg"
    process_hand_image(img_path)

脚本将显示原始图像、手部轮廓、绘制的凸包以及检测到的手指缺陷,同时标注手指数量。

原始图像
二值图像
手部轮廓与凸包

在这里插入图片描述

结语

本项目提供了一个基于OpenCV的简单但有效的手部图像处理方法,可以作为进一步研究和开发更复杂应用的基础。通过这些功能,可以在计算机视觉和图像处理的多个领域中应用和扩展。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_763061740

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值