用手势操控现实:OpenCV 音量控制与 AI 换脸技术解析

基于opencv的手势控制音量和ai换脸

HandTrackingModule.py

import cv2
import mediapipe as mp
import time



class handDetector():
    def __init__(self, mode = False, maxHands = 2, model_complexity = 1, detectionCon = 0.5, trackCon = 0.5):
        self.mode = mode
        self.maxHands = maxHands
        self.model_complexity = model_complexity
        self.detectionCon = detectionCon
        self.trackCon = trackCon
        self.mpHands = mp.solutions.hands
        self.hands = self.mpHands.Hands(self.mode, self.maxHands, self.model_complexity, self.detectionCon, self.trackCon)
        self.mpDraw = mp.solutions.drawing_utils

    def findHands(self, img, draw = True):
        # Hand类的对象只能使用RGB图像
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        self.results = self.hands.process(imgRGB)
        # print(results.multi_hand_landmarks)
        # 如果存在手
        if self.results.multi_hand_landmarks:
            # 如果存在多个手
            for handLms in self.results.multi_hand_landmarks:
                if draw:
                    # 设置连接线等属性
                    self.connection_drawing_spec = self.mpDraw.DrawingSpec(color=(0, 255, 0), thickness=2)
                    # 绘制
                    self.mpDraw.draw_landmarks(img, handLms, self.mpHands.HAND_CONNECTIONS, connection_drawing_spec=self.connection_drawing_spec)
        return img


    def findPosition(self, img, handNum=0, draw=True):
        lmList = []
        # 每个点的索引和它的像素比例,若知道窗口的宽度和高度可以计算位置
        if self.results.multi_hand_landmarks:
            myHand = self.results.multi_hand_landmarks[handNum]
            for id, lm in enumerate(myHand.landmark):
                # print(id, lm)
                h, w, c = img.shape
                cx, cy = int(lm.x * w), int(lm.y * h)
                # print(id, cx, cy)
                lmList.append([id, cx, cy])
                if draw:
                    cv2.circle(img, (cx, cy), 7, (255, 0, 0), cv2.FILLED)
            # 绘制每一只手
        return lmList

定义了一个名为 handDetector 的类,用于检测和跟踪手部。下面是代码的详细分析:

导入库

  • cv2: OpenCV 库,用于图像处理。
  • mediapipe as mp: 用于多媒体解决方案的库,在此用于手部检测。
  • time: 用于时间管理,但在给定的代码段中未使用。

handDetector

初始化方法 __init__

该方法用于初始化 handDetector 类的对象,并设置一些参数。

  • mode: 布尔值,控制 MediaPipe 手部解决方案的静态图像模式。默认值为 False
  • maxHands: 最大手部数量,控制同时检测的手的数量。默认值为 2
  • model_complexity: 模型复杂度,有 0、1、2 三个级别。默认值为 1
  • detectionCon: 检测置信度阈值。默认值为 0.5
  • trackCon: 跟踪置信度阈值。默认值为 0.5

此外,还创建了 MediaPipe 手部解决方案的实例,并初始化了绘图工具。

方法 findHands

该方法用于在给定图像中找到手,并根据需要绘制手部标记。

  • img: 输入图像。
  • draw: 布尔值,控制是否绘制手部标记。默认值为 True

该方法首先将图像从 BGR 转换为 RGB,然后处理图像以找到手部标记。如果找到了手部标记,并且 draw 参数为 True,则会在图像上绘制手部标记和连接线。

方法 findPosition

该方法用于在给定图像中找到手部标记的位置,并返回一个包含每个标记位置的列表。

  • img: 输入图像。
  • handNum: 手的索引,用于选择多个检测到的手中的特定一只。默认值为 0
  • draw: 布尔值,控制是否在图像上绘制每个标记的圆圈。默认值为 True

该方法遍历给定手的每个标记,并计算其在图像中的位置。如果 draw 参数为 True,则在每个标记的位置上绘制一个圆圈。

总结

handDetector 类是一个用于检测和跟踪手部的工具。它使用了 MediaPipe 的手部解决方案,并提供了在图像上绘制手部标记和连接线的功能。通过调用这些方法,你可以在视频流或静态图像中跟踪手部,甚至找到特定手部标记的位置。

VolumeHandControl.py

import cv2
import time
import numpy as np
import HandTrackingModule as htm
import math
from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
wCam, hCam = 640, 480
cap = cv2.VideoCapture(0)
# 设置摄像头的宽度
cap.set(3, wCam)
# 设置摄像头的高度
cap.set(4, hCam)
pTime = 0
tiga_img = cv2.imread("tiga.jpg", cv2.IMREAD_UNCHANGED)
detector = htm.handDetector(detectionCon=0.7)

face_Cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
devices = AudioUtilities.GetSpeakers()
interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
volume = cast(interface, POINTER(IAudioEndpointVolume))
# volume.GetMute()
# volume.GetMasterVolumeLevel()
# 音量范围
volRange = volume.GetVolumeRange()
print(volRange)
# 最小音量
minVol = volRange[0]
# 最大音量
maxVol = volRange[1]
vol = 0
volBar = 400
volPer = 0
def overlay_img(img, img_over, img_over_x, img_over_y):
    # 背景图像高宽
    img_w, img_h, img_c = img.shape
    # 覆盖图像高宽通道数
    img_over_h, img_over_w, img_over_c = img_over.shape
    # 转换成4通道
    if img_over_c == 3:
        img_over = cv2.cvtColor(img_over, cv2.COLOR_BGR2BGRA)
    # 遍历列
    for w in range(0, img_over_w):
        #遍历行
        for h in range(0, img_over_h):
            if img_over[h, w, 3] != 0:
                # 遍历三个通道
                for c in range(0, 3):
                    x = img_over_x + w
                    y = img_over_y + h
                    if x >= img_w or y >= img_h:
                        break
                    img[y-40, x, c] = img_over[h, w, c]
    return img


while True:
    success, img = cap.read()
    gray_frame = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    height, width, channel = img.shape
    faces = face_Cascade.detectMultiScale(gray_frame, 1.15, 5)
    for (x, y, w, h) in faces:
        gw = w
        gh = int(height * w / width)
        tiga_img = cv2.resize(tiga_img, (gw, gh+gh))
        print(gw, gh)
        if 0 <= x < img.shape[1] and 0 <= y < img.shape[0]:
            overlay_img(img, tiga_img, x, y)
    img = detector.findHands(img)
    lmList = detector.findPosition(img, draw=False)
    if len(lmList) != 0:
        # print(lmList[4], lmList[8])
        x1, y1 = lmList[4][1], lmList[4][2]
        x2, y2 = lmList[8][1], lmList[8][2]
        cv2.circle(img, (x1, y1), 15, (255, 0, 255), cv2.FILLED)
        cv2.circle(img, (x2, y2), 15, (255, 0, 255), cv2.FILLED)
        cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), 3)
        cx, cy = (x1+x2)//2, (y1+y2)//2
        cv2.circle(img, (cx, cy), 15, (255, 0, 255), cv2.FILLED)

        length = math.hypot(x2 - x1, y2 - y1)
        print(length)
        # Hand rang 130 25
        # Vomume Range -65 0
        vol = np.interp(length, [25, 175], [minVol, maxVol])
        volBar = np.interp(length, [25, 175], [400, 150])
        volPer = np.interp(length, [25, 175], [0, 100])
        print(int(length), vol)
        volume.SetMasterVolumeLevel(vol, None)
        if length<25:
            cv2.circle(img, (cx, cy), 15, (0, 255, 0), cv2.FILLED)

    cv2.rectangle(img, (50, 150), (85, 400), (255, 0, 0), 3)
    cv2.rectangle(img, (50, int(volBar)), (85, 400), (255, 0, 0), cv2.FILLED)
    cv2.putText(img, f'{int(volPer)} %', (40, 450), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 0, 0), 3)
    cTime = time.time()
    fps = 1/(cTime - pTime)
    pTime = cTime

    cv2.putText(img, f'FPS:{int(fps)}', (40, 50), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 0, 0), 3)
    cv2.imshow("img", img)
    cv2.waitKey(1)

1. 导入必要的库

  • OpenCV (cv2): 用于图像处理,例如读取图像、转换颜色空间、绘制形状等。
  • NumPy (np): 用于数值计算,特别是线性插值。
  • HandTrackingModule as htm: 导入自定义的手部检测模块。
  • math: 提供数学功能,例如计算两点间的距离。
  • ctypes, comtypes, pycaw.pycaw: 用于与操作系统的音量控制交互。

2. 初始化参数和对象

  • 摄像头大小 (wCam, hCam): 定义摄像头的宽度和高度。
  • 摄像头 (cap): 通过 OpenCV 初始化摄像头,并设置宽度和高度。
  • 时间 (pTime): 用于计算帧率。
  • 图像叠加 (tiga_img): 读取一个图像文件,稍后用于叠加。
  • 手部检测器 (detector): 使用自定义的手部检测模块创建检测器对象,设置检测置信度为 0.7。
  • 人脸检测 (face_Cascade): 加载 OpenCV 的 Haar 级联分类器来检测人脸。
  • 音量控制 (volume): 通过 pycaw 访问系统的音量控制,获取音量范围。

3. 定义图像叠加函数 overlay_img

该函数负责将一个图像叠加到另一个图像上的特定位置。它遍历覆盖图像的每个像素,并将非透明像素复制到背景图像的相应位置。

4. 主循环

在无限循环中,代码执行以下任务:

a. 人脸检测和图像叠加

  • 读取图像: 从摄像头捕获图像。
  • 灰度转换: 将图像转换为灰度,以便进行人脸检测。
  • 人脸检测: 使用级联分类器检测人脸。
  • 调整叠加图像: 根据人脸大小调整叠加图像的大小。
  • 叠加图像: 调用 overlay_img 函数将图像叠加到人脸上。

b. 手部检测和音量控制

  • 检测手部: 调用 detector.findHands 在图像上检测并绘制手部。
  • 找到位置: 调用 detector.findPosition 获取手部标记的位置。
  • 计算距离: 计算手部标记 4 和 8 之间的距离。
  • 绘制形状: 在这两个点上绘制圆圈,并在它们之间绘制线条。
  • 音量映射: 使用 NumPy 的 np.interp 函数将手的距离映射到音量范围。
  • 设置音量: 调用 volume.SetMasterVolumeLevel 设置系统音量。

c. 可视化

  • 绘制音量条: 在图像上绘制一个表示音量级别的矩形条。
  • 计算帧率: 使用当前时间和上一帧的时间计算帧率。
  • 绘制帧率: 在图像上绘制帧率文本。

d. 显示结果

  • 显示图像: 使用 OpenCV 的 imshow 方法显示处理后的图像。
  • 等待: 通过 OpenCV 的 waitKey 方法等待 1 毫秒,这样可以实时更新图像。

总结

这个代码集成了多个功能:通过摄像头捕获图像,检测人脸并在人脸上叠加图像,检测手部并通过手指之间的距离控制系统音量,然后通过 OpenCV 实时显示结果。它结合了图像处理、人脸和手部检测、系统交互和实时可视化,展示了计算机视觉和人机交互的强大功能。

效果

image-20230821012535304
(B站演示视频)[https://www.bilibili.com/video/BV1Xu41177Gz/?spm_id_from=333.999.0.0]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/89389.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FFmpeg<第一篇>:环境配置

1、官网地址 http://ffmpeg.org/download.html2、linux下载ffmpeg 下载&#xff1a; wget https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2解压&#xff1a; tar xvf ffmpeg-snapshot.tar.bz23、FFmpeg ./configure编译参数汇总 解压 ffmpeg-snapshot.tar.bz2 之后&…

60.每日一练:回文数(力扣)

目录 问题描述 代码解决以及思想 解法&#xff08;一&#xff09; 知识点 解法&#xff08;二&#xff09; 问题描述 代码解决以及思想 解法&#xff08;一&#xff09; class Solution { public:bool isPalindrome(int x) {string arr to_string(x); // 将整数转换为…

如何自己实现一个丝滑的流程图绘制工具(一)vue如何使用

背景 项目需求突然叫我实现一个类似processOn一样的在线流程图绘制工具。 这可难倒我了&#xff0c;立马去做调研&#xff0c;在github上找了很多个开源的流程图绘制工具&#xff0c; 对比下来我还是选择了 bpmn-js 原因&#xff1a; 1、他的流程图是涉及到业务的&#xff0c…

element ui - el-select获取点击项的整个对象item

1.背景 在使用 el-select 的时候&#xff0c;经常会通过 change 事件来获取当前绑定的 value &#xff0c;即对象中默认的某个 value 值。但在某些特殊情况下&#xff0c;如果想要获取的是点击项的整个对象 item&#xff0c;该怎么做呢&#xff1f; 2.实例 elementUI 中是可…

Vue教程(五):样式绑定——class和style

1、样式代码准备 样式提前准备 <style>.basic{width: 400px;height: 100px;border: 1px solid black;}.happy{border: 4px solid red;background-color: rgba(255, 255, 0, 0.644);background: linear-gradient(30deg, yellow, pink, orange, yellow);}.sad{border: 4px …

Git基础——基本的 Git本地操作

本文涵盖了你在使用Git的绝大多数时间里会用到的所有基础命令。学完之后&#xff0c;你应该能够配置并初始化Git仓库、开始或停止跟踪文件、暂存或者提交更改。我们也会讲授如何让Git忽略某些文件和文件模式&#xff0c;如何简单快速地撤销错误操作&#xff0c;如何浏览项目版本…

【精品】基于VUE3的 电商详情 图片显示模块

效果 组件 <template><div class"goods-imgs"><div class"imgs-show"><img :src"mainImage" alt"大图" /></div><ul class"img-thumbnail"><li v-for"(item, index) in image…

【安装】MongoDB7安装MongoSH命令

MongoDB Shell Download | MongoDB 下载之后 解压 配置环境变量即可 以前使用 mongo命令 改为 mongosh 官方说明 安装mongosh MongoDB 中文手册 | MongoD Manual | 中文操作手册 | MongoDB 最新版 (whaleal.com) 安装 mongosh — MongoDB Shell

Java smslib包开发

上一篇文章我详细介绍RXTXcomm的安装方法和简单代码,如果小伙伴涉及到需要使用手机短信模块完成短信收发需求的话,可以使用到smslib进行开发。 首先还是同样的,将整个smslib包源码导入项目,并且将它所需依赖一起进行导入 导入完成之后,我们就可以对smslib包进行二次开发了 下面…

江西南昌电气机械三维测量仪机械零件3d扫描-CASAIM中科广电

精密机械零部件是指机械设备中起到特定功能的零件&#xff0c;其制造精度要求非常高。这些零部件通常由金属、塑料或陶瓷等材料制成&#xff0c;常见的精密机械零部件包括齿轮、轴承、螺丝、活塞、阀门等。精密机械零部件的制造需要高精度的加工设备和工艺&#xff0c;以确保其…

Ubuntu20.04搭建OpenGL环境(glfw+glad)

Ubuntu20.04搭建OpenGL环境(glfwglad) Linux环境搭建 本文在VMware安装Ubuntu20.04桌面版的环境下搭建OpenGL&#xff0c;按照本文搭建完成后可以执行LearnOpenGL网站上的demo。 关于VMware可自行到VMware Workstation Pro | CN下载 关于Ubuntu20.04桌面版可自行到官网或In…

Docker-Consul

Docker-Consul 一、介绍1.什么是服务注册与发现2.什么是consul3.consul提供的一些关键特性&#xff1a; 二、consul 部署1.环境准备2.consul服务器3.查看集群信息4.通过 http api 获取集群信息 三、registrator服务器1.安装 Gliderlabs/Registrator2.测试服务发现功能是否正常3…

wps 画项目进度甘特图

效果如上 步骤一&#xff1a; 创建excel 表格 步骤二&#xff1a; 选中开始时间和结束时间两列数据&#xff0c;右键设置单元格格式 步骤三&#xff1a; 选择数值&#xff0c;点击确定&#xff0c;将日期转成数值。 步骤四&#xff1a;插入图表 选中任务&#xff0c;开始时间…

ssm+vue毕业论文管理系统源码和论文

ssmvue毕业论文管理系统053 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 摘 要 高校规模越来越大&#xff0c;学生越来越多&#xff0c;每年都有大批的大学生完成学业。毕业之前&#xff0c;各大高校设立…

KiCad 已经打开 交错保存 错误

期望结果&#xff1a; 打开工程 .pro 文件后&#xff0c;双击工程文件列表中的的 原理图&#xff1a;*.kicad_sch 能够打开原理图。 实际结果&#xff1a; 打开工程 .pro 文件后&#xff0c;双击工程文件列表中的的 原理图&#xff0c;弹出错误提示框如下&#xff1a; 重现步…

Java | IDEA中Netty运行多个client的方法

想要运行多个client但出现这种提示&#xff1a; 解决方法 1、打开IDEA&#xff0c;右上角找到下图&#xff0c;并点击 2、勾选

msvcp120.dll文件缺失一键修复方法,靠谱的多种修复msvcp120.dll方案

msvcp120.dll文件的丢失&#xff0c;其实是比较常见的&#xff0c;msvcp120.dll是一个Microsoft Visual C Redistributable的关键文件&#xff0c;它包含了一些用于C编程的标准函数和类的定义。如果msvcp120.dll丢失了&#xff0c;那么你的一些与这个文件相关的程序是打不开的&…

在线设计APP ui的网站,分享这7款

在数字时代&#xff0c;用户界面&#xff08;UI&#xff09;设计变得非常重要&#xff0c;因为良好的UI设计可以改善用户体验&#xff0c;增强产品吸引力。随着科学技术的发展&#xff0c;越来越多的应用在线设计网站出现&#xff0c;为设计师和团队提供了一种新的创作方式。本…

AI 时代,程序员无需焦虑

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f…

腾讯云下一代CDN -- EdgeOne加速MinIO对象存储

省流 使用MinIO作为EdgeOne的源站。 背景介绍 项目中需要一个兼容S3协议的对象存储服务&#xff0c;腾讯云的COS虽然也兼容S3协议&#xff0c;但是也只是支持简单的上传下载&#xff0c;对于上传的时候同时打标签这种需求&#xff0c;就不兼容S3了。所以决定自建一个对象存储…