search
HomeBackend DevelopmentPython TutorialHow to achieve the effect of dragging virtual squares with Python+OpenCV

1. Project effect

2. Core process

1. OpenCV reads the video stream and draws a rectangle on each frame of the picture.

2. Use mediapipe to obtain finger key point coordinates.

3. Based on the coordinate position of the finger and the coordinate position of the rectangle, determine whether the finger point is on the rectangle. If so, the rectangle will follow the finger movement.

3. Code process

Environment preparation:

python: 3.8.8

opencv: 4.2.0.32

mediapipe: 0.8 .10.1

Note:

1. If the opencv version is too high or too low, there may be some problems such as the camera not being able to open, crashing, etc. The python version affects the selectable version of opencv.

2. OpenCV may not be able to be used normally after pip install mediapipe. Uninstall it and download it again. Just get used to it.

1. Read the camera video and draw a rectangle

import cv2
import time
import numpy as np
 
 
# 调用摄像头 0 默认摄像头 
cap = cv2.VideoCapture(0)
 
# 初始方块数据
x = 100
y = 100
w = 100
h = 100
 
# 读取一帧帧照片
while True:
    # 返回frame图片
    rec,frame = cap.read()
    
    # 镜像
    frame = cv2.flip(frame,1)
    
    # 画矩形 
    cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 255), -1)
 
    # 显示画面
    cv2.imshow('frame',frame)
    
    # 退出条件
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
    
cap.release()
cv2.destroyAllWindows()

This is a very basic step. At this time, when we run this code and the camera is turned on, we will be surprised to see our handsome face. face, and there is a 100*100 purple rectangle in the upper left corner.

2. Import mediapipe to process finger coordinates

pip install mediapipe

Some problems may occur at this time, such as openCV suddenly becoming unavailable. It doesn’t matter, uninstall it and download it again.

mediapipe details: Hands - mediapipe (google.github.io)

How to achieve the effect of dragging virtual squares with Python+OpenCV

In short, it will return us 21 finger key points Coordinates, that is, its position ratio in the video screen (0~1), we multiply it by the width and height of the corresponding screen to get the coordinates corresponding to the finger.

This time I used the tips of my index finger and middle finger, which are numbers 8 and 12.

2.1 Configure some basic information

import cv2
import time
import numpy as np
import mediapipe as mp
 
 
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.hands
 
hands =  mp_hands.Hands(
    static_image_mode=True,
    max_num_hands=2,
    min_detection_confidence=0.5)

2.2 When processing each frame of image, add

    frame.flags.writeable = False
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    # 返回结果
    results = hands.process(frame)
 
    frame.flags.writeable = True
    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

When we are in When reading each frame of picture in the video stream, it is converted from BGR to RGB and supplied to the hands object generated by mediapipe for reading. It will return the information of the key points of the fingers in this picture. We only need to continue to draw on it. on every frame of the picture.

    # 如果结果不为空
    if results.multi_hand_landmarks:
 
        # 遍历双手(根据读取顺序,一只只手遍历、画画)
        for hand_landmarks in results.multi_hand_landmarks:
            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())

2.3 The complete code of this step

import cv2
import time
import numpy as np
import mediapipe as mp
 
 
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.hands
 
hands =  mp_hands.Hands(
    static_image_mode=True,
    max_num_hands=2,
    min_detection_confidence=0.5)
 
 
# 调用摄像头 0 默认摄像头 
cap = cv2.VideoCapture(0)
 
# 方块初始数组
x = 100
y = 100
w = 100
h = 100
 
 
# 读取一帧帧照片
while True:
    # 返回frame图片
    rec,frame = cap.read()
    
    # 镜像
    frame = cv2.flip(frame,1)
    
    
    
    frame.flags.writeable = False
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    # 返回结果
    results = hands.process(frame)
 
    frame.flags.writeable = True
    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
    
    
    # 如果结果不为空
    if results.multi_hand_landmarks:
 
        # 遍历双手(根据读取顺序,一只只手遍历、画画)
        # results.multi_hand_landmarks n双手
        # hand_landmarks 每只手上21个点信息
        for hand_landmarks in results.multi_hand_landmarks:
            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())
    
    
    # 画矩形 
    cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 255), -1)
 
    # 显示画面
    cv2.imshow('frame',frame)
    
    # 退出条件
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
    
cap.release()
cv2.destroyAllWindows()

3. Position calculation

Our experiment requires dragging the square, so there must be some that do not drag time, so we might as well obtain the positions of the index finger (8) and middle finger (12) tips according to the previous step. If they are close, we will change the coordinates of the block according to the position of the fingers when they coincide with the block.

How to achieve the effect of dragging virtual squares with Python+OpenCV

Full code

How to achieve the effect of dragging virtual squares with Python+OpenCV

import cv2
import time
import math
import numpy as np
import mediapipe as mp
 
# mediapipe配置
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.hands
hands =  mp_hands.Hands(
    static_image_mode=True,
    max_num_hands=2,
    min_detection_confidence=0.5)
 
 
# 调用摄像头 0 默认摄像头 
cap = cv2.VideoCapture(0)
 
# cv2.namedWindow("frame", 0)
# cv2.resizeWindow("frame", 960, 640)
 
 
# 获取画面宽度、高度
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
 
 
# 方块初始数组
x = 100
y = 100
w = 100
h = 100
 
L1 = 0
L2 = 0
 
on_square = False
square_color = (0, 255, 0)
 
# 读取一帧帧照片
while True:
    # 返回frame图片
    rec,frame = cap.read()
    
    # 镜像
    frame = cv2.flip(frame,1)
    
    
    
    frame.flags.writeable = False
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    # 返回结果
    results = hands.process(frame)
 
    frame.flags.writeable = True
    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
    
    
    # 如果结果不为空
    if results.multi_hand_landmarks:
 
 
        # 遍历双手(根据读取顺序,一只只手遍历、画画)
        # results.multi_hand_landmarks n双手
        # hand_landmarks 每只手上21个点信息
        for hand_landmarks in results.multi_hand_landmarks:
            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())
            
            # 记录手指每个点的x y 坐标
            x_list = []
            y_list = []
            for landmark in hand_landmarks.landmark:
                x_list.append(landmark.x)
                y_list.append(landmark.y)
                
            
            # 获取食指指尖
            index_finger_x, index_finger_y = int(x_list[8] * width),int(y_list[8] * height)
 
            # 获取中指
            middle_finger_x,middle_finger_y = int(x_list[12] * width), int(y_list[12] * height)
 
 
            # 计算两指尖距离
            finger_distance = math.hypot((middle_finger_x - index_finger_x), (middle_finger_y - index_finger_y))
 
            # 如果双指合并(两之间距离近)
            if finger_distance < 60:
 
                # X坐标范围 Y坐标范围
                if (index_finger_x > x and index_finger_x < (x + w)) and (
                        index_finger_y > y and index_finger_y < (y + h)):
 
                    if on_square == False:
                        L1 = index_finger_x - x
                        L2 = index_finger_y - y
                        square_color = (255, 0, 255)
                        on_square = True
 
            else:
                # 双指不合并/分开
                on_square = False
                square_color = (0, 255, 0)
 
            # 更新坐标
            if on_square:
                x = index_finger_x - L1
                y = index_finger_y - L2
            
            
 
    # 图像融合 使方块不遮挡视频图片
    overlay = frame.copy()
    cv2.rectangle(frame, (x, y), (x + w, y + h), square_color, -1)
    frame = cv2.addWeighted(overlay, 0.5, frame, 1 - 0.5, 0)
    
 
    # 显示画面
    cv2.imshow(&#39;frame&#39;,frame)
    
    # 退出条件
    if cv2.waitKey(1) & 0xFF == ord(&#39;q&#39;):
        break
    
cap.release()
cv2.destroyAllWindows()

The above is the detailed content of How to achieve the effect of dragging virtual squares with Python+OpenCV. For more information, please follow other related articles on the PHP Chinese website!

Statement
This article is reproduced at:亿速云. If there is any infringement, please contact admin@php.cn delete
详细讲解Python之Seaborn(数据可视化)详细讲解Python之Seaborn(数据可视化)Apr 21, 2022 pm 06:08 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于Seaborn的相关问题,包括了数据可视化处理的散点图、折线图、条形图等等内容,下面一起来看一下,希望对大家有帮助。

详细了解Python进程池与进程锁详细了解Python进程池与进程锁May 10, 2022 pm 06:11 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于进程池与进程锁的相关问题,包括进程池的创建模块,进程池函数等等内容,下面一起来看一下,希望对大家有帮助。

Python自动化实践之筛选简历Python自动化实践之筛选简历Jun 07, 2022 pm 06:59 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于简历筛选的相关问题,包括了定义 ReadDoc 类用以读取 word 文件以及定义 search_word 函数用以筛选的相关内容,下面一起来看一下,希望对大家有帮助。

归纳总结Python标准库归纳总结Python标准库May 03, 2022 am 09:00 AM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于标准库总结的相关问题,下面一起来看一下,希望对大家有帮助。

Python数据类型详解之字符串、数字Python数据类型详解之字符串、数字Apr 27, 2022 pm 07:27 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于数据类型之字符串、数字的相关问题,下面一起来看一下,希望对大家有帮助。

分享10款高效的VSCode插件,总有一款能够惊艳到你!!分享10款高效的VSCode插件,总有一款能够惊艳到你!!Mar 09, 2021 am 10:15 AM

VS Code的确是一款非常热门、有强大用户基础的一款开发工具。本文给大家介绍一下10款高效、好用的插件,能够让原本单薄的VS Code如虎添翼,开发效率顿时提升到一个新的阶段。

详细介绍python的numpy模块详细介绍python的numpy模块May 19, 2022 am 11:43 AM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于numpy模块的相关问题,Numpy是Numerical Python extensions的缩写,字面意思是Python数值计算扩展,下面一起来看一下,希望对大家有帮助。

python中文是什么意思python中文是什么意思Jun 24, 2019 pm 02:22 PM

pythn的中文意思是巨蟒、蟒蛇。1989年圣诞节期间,Guido van Rossum在家闲的没事干,为了跟朋友庆祝圣诞节,决定发明一种全新的脚本语言。他很喜欢一个肥皂剧叫Monty Python,所以便把这门语言叫做python。

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools