AI计算机视觉笔记八:基于mediapipe的虚拟绘画

简介: 该项目利用MediaPipe手部关键点识别技术,实现了隔空绘画功能。用户可以通过手势控制绘画工具,选择颜色或橡皮擦。环境配置基于`mediapipe_env`,在PyCharm中运行。项目包括两个文件:`AiVirtualPainter.py`负责绘画逻辑,`HandTrackingModule.py`用于手部关键点检测。此项目展示了AI技术在互动应用中的潜力,适合初学者实践与学习。

一、项目介绍

随着人工智能时代的到来,许多技术得到了空前的发展,让人们更加认识到了线上虚拟技术的强大。

通过mediapipe识别手的关键点,检测中指,实现隔空画画的操作。

通过两个手指的间距,实现点击选择颜色或橡皮檫。
image.png

二、运行

1、环境

环境搭建使用的是上一篇搭建的环境mediapipe_env

打开终端,输入下面命令,激活环境:

conda activate mediapipe
这次使用的是pycharm,软件自行安装,安装社区版本。

建立一个目录,把项目导入到pycharm里,然后设置环境

点击Add New Interpreter
image.png
选择环境的python.exeimage.png

终端选择,一定要powershell.exe
image.png
设置好可以在pycharm里的终端操作
image.png

2、运行

导入代码,右键运行
image.png

3 、结果

image.png

三、代码

这里不介绍原理及过程,想学习的人不会因为这些而去不学习,所以需要自行了解,项目难度不大,代码也相对的不复杂。直接上源码

一共两个文件,AiVirtualPainter.py和HandTrackingModule.py

AiVirtualPainter.py实现的是绘画功能,HandTrackingModule.py实现的是手关键点识别。

AiVirtualPainter.py

import cv2
import HandTrackingModule as htm
import os
import numpy as np


folderPath = "PainterImg/"
mylist = os.listdir(folderPath)
overlayList = []
for imPath in mylist:
    image = cv2.imread(f'{folderPath}/{imPath}')
    overlayList.append(image)
header = overlayList[0]
color = [255, 0, 0]
brushThickness = 15
eraserThickness = 40

cap = cv2.VideoCapture(0)  # 若使用笔记本自带摄像头则编号为0  若使用外接摄像头 则更改为1或其他编号
cap.set(3, 1280)
cap.set(4, 720)
# cap.set(3, 800)
# cap.set(4, 500)
detector = htm.handDetector()
xp, yp = 0, 0
imgCanvas = np.zeros((720, 1280, 3), np.uint8)  # 新建一个画板
# imgCanvas = np.zeros((500, 800, 3), np.uint8)  # 新建一个画板

while True:
    # 1.import image
    success, img = cap.read()
    img = cv2.flip(img, 1)  # 翻转

    # 2.find hand landmarks
    img = detector.findHands(img)
    lmList = detector.findPosition(img, draw=True)

    if len(lmList) != 0:
        x1, y1 = lmList[8][1:]
        x2, y2 = lmList[12][1:]

        # 3. Check which fingers are up
        fingers = detector.fingersUp()

        # 4. If Selection Mode – Two finger are up
        if fingers[1] and fingers[2]:
            if y1 < 153:
                if 0 < x1 < 320:
                    header = overlayList[0]
                    color = [50, 128, 250]
                elif 320 < x1 < 640:
                    header = overlayList[1]
                    color = [0, 0, 255]
                elif 640 < x1 < 960:
                    header = overlayList[2]
                    color = [0, 255, 0]
                elif 960 < x1 < 1280:
                    header = overlayList[3]
                    color = [0, 0, 0]
        img[0:1280][0:153] = header

        # 5. If Drawing Mode – Index finger is up
        if fingers[1] and fingers[2] == False:
            cv2.circle(img, (x1, y1), 15, color, cv2.FILLED)
            print("Drawing Mode")
            if xp == 0 and yp == 0:
                xp, yp = x1, y1

            if color == [0, 0, 0]:
                cv2.line(img, (xp, yp), (x1, y1), color, eraserThickness)  # ??
                cv2.line(imgCanvas, (xp, yp), (x1, y1), color, eraserThickness)
            else:
                cv2.line(img, (xp, yp), (x1, y1), color, brushThickness)   # ??
                cv2.line(imgCanvas, (xp, yp), (x1, y1), color, brushThickness)

        xp, yp = x1, y1
        # Clear Canvas when all fingers are up
        # if all (x >= 1 for x in fingers):
        #     imgCanvas = np.zeros((720, 1280, 3), np.uint8)

    # 实时显示画笔轨迹的实现
    imgGray = cv2.cvtColor(imgCanvas, cv2.COLOR_BGR2GRAY)
    _, imgInv = cv2.threshold(imgGray, 50, 255, cv2.THRESH_BINARY_INV)
    imgInv = cv2.cvtColor(imgInv, cv2.COLOR_GRAY2BGR)
    img = cv2.bitwise_and(img, imgInv)
    img = cv2.bitwise_or(img, imgCanvas)
    img[0:1280][0:153] = header

    cv2.imshow("Image", img)
    # cv2.imshow("Canvas", imgCanvas)
    # cv2.imshow("Inv", imgInv)
    cv2.waitKey(1)

HandTrackingModule.py

import cv2
import mediapipe as mp
import time
import math

class handDetector():
    def __init__(self, mode=False, maxHands=2, detectionCon=0.8, trackCon=0.8):
        self.mode = mode
        self.maxHands = maxHands
        self.detectionCon = detectionCon
        self.trackCon = trackCon

        self.mpHands = mp.solutions.hands
        self.hands = self.mpHands.Hands(self.mode, self.maxHands, self.detectionCon, self.trackCon)
        self.mpDraw = mp.solutions.drawing_utils
        self.tipIds = [4, 8, 12, 16, 20]

    def findHands(self, img, draw=True):
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        self.results = self.hands.process(imgRGB)

        print(self.results.multi_handedness)  # 获取检测结果中的左右手标签并打印

        if self.results.multi_hand_landmarks:
            for handLms in self.results.multi_hand_landmarks:
                if draw:
                    self.mpDraw.draw_landmarks(img, handLms, self.mpHands.HAND_CONNECTIONS)
        return img

    def findPosition(self, img, draw=True):
        self.lmList = []
        if self.results.multi_hand_landmarks:
            for handLms in self.results.multi_hand_landmarks:
                for id, lm in enumerate(handLms.landmark):
                    h, w, c = img.shape
                    cx, cy = int(lm.x * w), int(lm.y * h)
                    # print(id, cx, cy)
                    self.lmList.append([id, cx, cy])
                    if draw:
                        cv2.circle(img, (cx, cy), 12, (255, 0, 255), cv2.FILLED)
        return self.lmList

    def fingersUp(self):
        fingers = []
        # 大拇指
        if self.lmList[self.tipIds[0]][1] > self.lmList[self.tipIds[0] - 1][1]:
            fingers.append(1)
        else:
            fingers.append(0)

        # 其余手指
        for id in range(1, 5):
            if self.lmList[self.tipIds[id]][2] < self.lmList[self.tipIds[id] - 2][2]:
                fingers.append(1)
            else:
                fingers.append(0)

        # totalFingers = fingers.count(1)
        return fingers

    def findDistance(self, p1, p2, img, draw=True, r=15, t=3):
        x1, y1 = self.lmList[p1][1:]
        x2, y2 = self.lmList[p2][1:]
        cx, cy = (x1 + x2) // 2, (y1 + y2) // 2

        if draw:
            cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), t)
            cv2.circle(img, (x1, y1), r, (255, 0, 255), cv2.FILLED)
            cv2.circle(img, (x2, y2), r, (255, 0, 255), cv2.FILLED)
            cv2.circle(img, (cx, cy), r, (0, 0, 255), cv2.FILLED)
            length = math.hypot(x2 - x1, y2 - y1)

        return length, img, [x1, y1, x2, y2, cx, cy]


def main():
    pTime = 0
    cTime = 0
    cap = cv2.VideoCapture(0)
    detector = handDetector()
    while True:
        success, img = cap.read()
        img = detector.findHands(img)        # 检测手势并画上骨架信息

        lmList = detector.findPosition(img)  # 获取得到坐标点的列表
        if len(lmList) != 0:
            print(lmList[4])

        cTime = time.time()
        fps = 1 / (cTime - pTime)
        pTime = cTime

        cv2.putText(img, 'fps:' + str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3)
        cv2.imshow('Image', img)
        cv2.waitKey(1)


if __name__ == "__main__":
    main()

源码网上有很多,有不懂可以联系博主,一起相互交流。

学习永无止境,AI是未来的发展方向,每天进步一点点,实现终身学习。

相关文章
|
11月前
|
人工智能 Linux iOS开发
音乐人必看!OpenUtau:开源AI歌声合成神器,快速打造专业级虚拟歌手,中文日文无缝切换
OpenUtau是一款开源的歌声合成工具,兼容UTAU音源库和重采样器,支持多语言界面及预渲染功能,让音乐创作更加高效便捷。
3263 15
音乐人必看!OpenUtau:开源AI歌声合成神器,快速打造专业级虚拟歌手,中文日文无缝切换
|
5月前
|
人工智能 编解码 芯片
【AI绘画】你有多久没有打开SD了?
曾几何时,Stable Diffusion的复杂参数令人崩溃,如今即梦、可灵等AI工具已让生成图片变得轻而易举。哩布哩布发布2.0升级公告,看似迈向更易用的未来,却也悄然为那个钻研模型、拼接工作流的“拓荒时代”奏响终章。技术迭代飞快,但那份对创造的热爱与探索精神,永不褪色。
860 9
|
6月前
|
人工智能 机器人 计算机视觉
当AI有了“分身”:虚拟化身与情感交互的实战指南
当AI有了“分身”:虚拟化身与情感交互的实战指南
551 0
|
10月前
|
人工智能 API 开发者
用Qwen3+MCPs实现AI自动发布小红书笔记!支持图文和视频
魔搭自动发布小红书MCP,是魔搭开发者小伙伴实现的小红书笔记自动发布器,可以通过这个MCP自动完成小红书标题、内容和图片的发布。
3298 41
|
8月前
|
机器学习/深度学习 人工智能 机器人
Meta AI Research:虚拟/可穿戴/机器人三位一体的AI进化路径
本文阐述了我们对具身AI代理的研究——这些代理以视觉、虚拟或物理形式存在,使其能够与用户及环境互动。这些代理包括虚拟化身、可穿戴设备和机器人,旨在感知、学习并在其周围环境中采取行动。与非具身代理相比,这种特性使它们更接近人类的学习与环境交互方式。我们认为,世界模型的构建是具身AI代理推理与规划的核心,这使代理能够理解并预测环境、解析用户意图及社会背景,从而增强其自主完成复杂任务的能力。世界建模涵盖多模态感知的整合、通过推理进行行动规划与控制,以及记忆机制,以形成对物理世界的全面认知。除物理世界外,我们还提出需学习用户的心理世界模型,以优化人机协作。
686 3
|
人工智能 Linux iOS开发
exo:22.1K Star!一个能让任何人利用日常设备构建AI集群的强大工具,组成一个虚拟GPU在多台设备上并行运行模型
exo 是一款由 exo labs 维护的开源项目,能够让你利用家中的日常设备(如 iPhone、iPad、Android、Mac 和 Linux)构建强大的 AI 集群,支持多种大模型和分布式推理。
3193 101
|
10月前
|
Web App开发 人工智能 JSON
Windows版来啦!Qwen3+MCPs,用AI自动发布小红书图文/视频笔记!
上一篇用 Qwen3+MCPs实现AI自动发小红书的最佳实践 有超多小伙伴关注,同时也排队在蹲Windows版本的教程。
1849 1
|
12月前
|
机器学习/深度学习 人工智能 安全
Stable Diffusion 3.0 :一键开启你的AI绘画之旅
本文介绍了Stable Diffusion 3.0的主要优化,包括采用DiT架构提升多对象生成能力及“流匹配”技术加速采样。同时解决了部署复杂、显卡需求高等问题,可通过阿里云计算巢一键部署,实现即开即用。文章展示了人像、动漫风、科幻风等生成效果,并提供中文菜单设置与插件下载教程。无论是专业设计师还是普通用户,都能轻松开启智能创作新时代。 Flux模型支持即将上线,值得期待。
|
机器学习/深度学习 人工智能 UED
OOTDiffusion:开源AI虚拟试衣工具,智能适配性别和体型自动调整衣物
OOTDiffusion是一款开源的AI虚拟试衣工具,能够智能适配不同性别和体型,自动调整衣物尺寸和形状,生成自然贴合的试穿效果。该工具支持半身和全身试穿模式,操作简单,适合服装电商、时尚行业从业者及AI试穿技术爱好者使用。
1600 27
OOTDiffusion:开源AI虚拟试衣工具,智能适配性别和体型自动调整衣物

热门文章

最新文章