图像处理案例02

手指拖拽屏幕上的方块儿

1 步骤:

1.opencv获取视频流
2.获取手指关节关键点坐标
3.判断手指是否在方块上
4.如果在方块上,方块跟着手指移动

2 代码

import cv2
import numpy as np
import math
import mediapipe as mp

## 检测手掌参数设置
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.hands
# 获取手的21个关节
hands = mp_hands.Hands(
    model_complexity=0,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5)
# 获取摄像头的视频流
cap = cv2.VideoCapture(0)

# 获取画面宽度,高度
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 方块的相关参数
## box左上角坐标、宽度、颜色
box_x = 100
box_y = 100
box_width = 100
box_high  = 120
box_color = (255, 0, 255)
## 阈值,当食指和中指指尖距离大于阈值时,停止移动box
threth = 80
## 食指指尖与box左上角坐标的距离
d1 = 0
d2 = 0
## 食指指尖是否在方块上
on_box = False

while True:
    # 1. 读取每一帧
    ret, frame = cap.read()
    # 对图像进行处理
    # 镜像处理,对y轴进行翻转
    frame = cv2.flip(frame, 1)

    # mediapipe处理RGB通道的图像
    frame.flags.writeable = False
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    ## 2.手掌检测RGB图像
    results = hands.process(frame)

    frame.flags.writeable = True
    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
    # 判断是否检测到手掌
    if results.multi_hand_landmarks:
        # 遍历每一只手掌
        for hand_landmarks in results.multi_hand_landmarks:
            # 绘制手掌的21个关键点
            mp_drawing.draw_landmarks(
                frame,
                hand_landmarks,
                mp_hands.HAND_CONNECTIONS,
                mp_drawing_styles.get_default_hand_landmarks_style(),
                mp_drawing_styles.get_default_hand_connections_style()
            )
            # 保存手掌的21个x,y的坐标
            x_list = []
            y_list = []
            for landmark in hand_landmarks.landmark:  # 会循环21次把手的关节弄好
                # 添加x坐标
                x_list.append(landmark.x)  # append表示添加x坐标
                # 添加y坐标
                y_list.append(landmark.y)
            # 获取食指指尖xy坐标
            index_finger_x = int(x_list[8] * width)
            index_finger_y = int(y_list[8] * height)
            # 获取中指指尖,用于退出方块
            middle_finger_x = int(x_list[12] * width)
            middle_finger_y = int(y_list[12] * height)
            # 计算食指指尖和中指指尖的欧式距离
            finger_len = math.hypot((index_finger_x - middle_finger_x),
                                    (index_finger_y - middle_finger_y))

            if finger_len < threth:
                # 3. 判断指尖是否在方块上面
                if (box_x < index_finger_x < box_x + box_width and box_y < index_finger_y < box_y + box_high):
                    if on_box == False:
                        ## 如果食指在box内移动,则保持d1、d2不更新,即box与食指的相对位置不变
                        d1 = abs(index_finger_x - box_x)
                        d2 = abs(index_finger_y - box_y)
                        on_box = True
                        ## 如果食指在box上,则变换box为水红色
                        box_color = (255, 0, 255)
            else:
                on_box = False
                ## 如果食指不在box上,则变换box为蓝颜
                box_color = (255, 0, 0)

            if on_box:  # 如果手指在方块上面        
                box_x = index_finger_x - d1  # 根据算法
                box_y = index_finger_y - d2
    # 4. 画出box
    cv2.rectangle(frame, (box_x, box_y), (box_x + box_width, box_y + box_high), box_color, -1)
    frame = cv2.addWeighted(frame.copy(), 0.5, frame, 0.5, 0)  # 做一个半透明

    # 显示图像
    cv2.imshow('Box drag', frame)
    # 退出条件
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()
posted @   山居秋暝LS  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示