openCV实现拖拽虚拟方块

一、项目效果:

在这里插入图片描述

二、核心流程:

  1. openCV读取视频流、在每一帧图片上画一个矩形。
  2. 使用mediapipe获取手指关键点坐标。
  3. 根据手指坐标位置和矩形的坐标位置,判断手指点是否在矩形上,如果在则矩形跟随手指移动。

三、代码流程:

环境准备:

python: 3.8.8
opencv: 4.2.0.32
mediapipe: 0.8.10.1

注:

  • opencv版本过高或过低可能出现一些如摄像头打不开、闪退等问题,python版本影响opencv可选择的版本。
  • pip install mediapipe 后可能导致openCV无法正常使用,卸了重新下载,习惯了就好。

1. 读取摄像头视频,画矩形:

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'):breakcap.release()
cv2.destroyAllWindows() 

运行这段代码,摄像头打开,我们会惊讶地看到自己英俊的脸庞,且左上角有个100*100的紫色矩形。

2. 导入mediapipe处理手指坐标

pip install mediapipe

此时可能出现一些问题,比如openCV突然用不了了,没关系,卸载了重新下

mediapipe详细信息:Hands - mediapipe (google.github.io)

在这里插入图片描述

在这里插入图片描述

简单来说,它会返回给我们21个手指关键点的坐标,即它在视频画面的位置比例( 0~1 ),我们乘以对应画面的宽高,就能得到手指对应的坐标了。

本次用到食指和中指指尖,也就是8号和12号。

2.1 配置一些基础信息:

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

2.2 在处理每一帧图像时,加入:

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

当我们在视频流中读取每一帧图片时,将其从BGR转为RGB供给mediapipe生成的hands对象读取,它会返回这张图片中手指关键点的信息,我们只需要继续对其作画,画在每一帧图片上。

# 如果结果不为空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 至此步骤完整代码

import cv2
import time
import numpy as np
import mediapipe as mpmp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.handshands =  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 = Falseframe = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 返回结果results = hands.process(frame)frame.flags.writeable = Trueframe = 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'):breakcap.release()
cv2.destroyAllWindows() 

此时我们运行看一下还挺有意思的:

在这里插入图片描述

3. 位置计算

我们这个实验要求拖动方块,那肯定也有不拖动的时候,因此不妨根据上一步获取食指(8)中指(12)指尖的位置,如果这俩离得近,我们就在他与方块重合的时候,根据手指的位置改变方块的坐标。

在这里插入图片描述

完整代码:

首先配置环境

在这里插入图片描述

代码

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 = 100L1 = 0
L2 = 0on_square = False
square_color = (0, 255, 0)# 读取一帧帧照片
while True:# 返回frame图片rec,frame = cap.read()# 镜像frame = cv2.flip(frame,1)frame.flags.writeable = Falseframe = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 返回结果results = hands.process(frame)frame.flags.writeable = Trueframe = 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 - xL2 = index_finger_y - ysquare_color = (255, 0, 255)on_square = Trueelse:# 双指不合并/分开on_square = Falsesquare_color = (0, 255, 0)# 更新坐标if on_square:x = index_finger_x - L1y = 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('frame',frame)# 退出条件if cv2.waitKey(1) & 0xFF == ord('q'):breakcap.release()
cv2.destroyAllWindows() 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【系统架构师】-第3章-信息系统基础知识

1、信息系统的基本功能 输入&#xff1a;决定于系统所要达到的目的及系统的能力和信息环境的许可存储&#xff1a;存储各种信息资料和数据的能力处理&#xff1a;数据处理工具&#xff0c;利用OLAP、DM&#xff08;数据挖掘&#xff09;技术输出&#xff1a;保证最终实现最佳的…

AI人员入侵识别摄像机

AI人员入侵识别摄像机是一种智能监控设备&#xff0c;利用人工智能技术辨认并报警可能的入侵行为。这种摄像机利用深度学习算法实时分析监控画面&#xff0c;识别出普通行人和潜在入侵者之间的差异&#xff0c;从而更准确地预警可能发生的安全事件。 该摄像机通过对比数据库中存…

springboot项目学习-瑞吉外卖(1)

第一天任务如下&#xff1a; 建立基本架构完成登录、退出功能 注意&#xff1a;本博客没有使用网上教程里的mybatis-plus&#xff0c;使用的是mybatis&#xff1b;数据库连接池也没有使用教程里的druid&#xff0c;使用的是spring自带的连接池 基本架构 common包&#xff1a;存…

【Linux进程状态】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、直接谈论Linux的进程状态 看看Linux内核源代码怎么说 1.1、R状态 -----> 进程运行的状态 1.2、S状态 -----> 休眠状态(进程在等待“资源”就绪) 1.3、T状…

奇怪的比赛(Python,递归,状态压缩动态规划dp)

目录 前言&#xff1a;题目&#xff1a;思路&#xff1a;递归&#xff1a;代码及详细注释&#xff1a; 状态压缩dp&#xff1a;代码及详细注释&#xff1a; 总结&#xff1a; 前言&#xff1a; 这道题原本是蓝桥上的题&#xff0c;现在搜不到了&#xff0c;网上关于此题的讲解…

Python爬虫:原理与实战

引言 在当今的信息时代&#xff0c;互联网上的数据如同浩瀚的海洋&#xff0c;充满了无尽的宝藏。Python爬虫作为一种高效的数据抓取工具&#xff0c;能够帮助我们轻松地获取这些数据&#xff0c;并进行后续的分析和处理。本文将深入探讨Python爬虫的原理&#xff0c;并结合实战…

kkview远程控制: 内网远程桌面控制软件

内网远程桌面控制软件&#xff1a;高效、安全的远程管理方案 在信息技术日新月异的今天&#xff0c;内网远程桌面控制软件已成为许多企业和个人用户不可或缺的工具。这类软件允许用户通过内部网络&#xff0c;实现对其他计算机的远程访问和控制&#xff0c;从而大大提高工作效…

[Windows] Win11 常用快捷键

文章目录 &#x1f680; [Windows] Win11 常用快捷键&#x1f310; Windows 操作系统&#x1f525; Windows 11 &#x1f310; Windows 11 快捷键概览&#x1f525; 基本快捷键&#x1f525; 窗口快捷键&#x1f525; 功能快捷键 &#x1f4dd; 小结 &#x1f680; [Windows] W…

“技多不压身”是什么意思?看完这篇文章你会明白:有了手艺,走遍天下都不怕!

“技多不压身”是什么意思&#xff1f;看完这篇文章你会明白&#xff1a;有了手艺&#xff0c;走遍天下都不怕&#xff01; 咱们的老祖宗流传一句话&#xff1a;“一招鲜&#xff0c;吃遍天。”这话说得直白&#xff0c;却道出了学一门手艺或技术对于人生的重要性。“李秘书讲…

使用Loadrunner进行性能测试

一、确定性能测试的范围、要求、配置、工具等 明确测试的系统&#xff1a; 本文档主要指的是web应用。 明确测试要求&#xff1a; 用户提出性能测试&#xff0c;例如&#xff0c;网站首页页面响应时间在3S之内&#xff0c;主要的业务操作时间小于10s&#xff0c;支持300用户在…

Android Studio实现内容丰富的安卓宠物用品商店管理系统

获取源码请点击文章末尾QQ名片联系&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动。 项目编号128 1.开发环境android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.系统公告 3.宠物社区&#xff08;可发布宠物帖子&#…

this是什么?为什么要改变this?怎么改变 this 指向?

目录 this 是什么&#xff1f; 箭头函数中的 this 为什么要改变 this 指向&#xff1f; 改变 this 指向的三种方法 call(无数个参数) apply(两个参数) bind(无数个参数) this 是什么&#xff1f; 在对象方法中&#xff0c;this 指的是所有者对象&#xff08;方法的拥有者…

提升口才表达能力的重要性与途径

提升口才表达能力的重要性与途径 口才表达能力&#xff0c;即一个人通过口头语言准确、流畅、生动地传达思想、情感和观点的能力&#xff0c;是现代社会中不可或缺的一项基本技能。无论是在职场沟通、人际交往还是公共场合发言&#xff0c;优秀的口才表达能力都能为我们带来诸…

力扣hot100:416.分割等和子集(组合/动态规划/STL问题)

组合数问题 我们思考一下&#xff0c;如果要把数组分割成两个子集&#xff0c;并且两个子集的元素和相等&#xff0c;是否等价于在数组中寻找若干个数使之和等于所有数的一半&#xff1f;是的&#xff01; 因此我们可以想到&#xff0c;两种方式&#xff1a; ①回溯的方式找到t…

vanna:基于RAG的text2sql框架

文章目录 vanna简介及使用vanna的原理vanna的源码理解总结参考资料 vanna简介及使用 vanna是一个开源的利用了RAG的SQL生成python框架&#xff0c;在2024年3月已经有了5.8k的star数。 Vanna is an MIT-licensed open-source Python RAG (Retrieval-Augmented Generation) fram…

探讨大世界游戏的制作流程及技术——大场景制作技术概况篇

接上文&#xff0c;我们接下来了解一下大世界场景制作技术有哪些&#xff0c;本篇旨在给大家过一遍目前业界的做法&#xff0c;能让大家有一个宏观的知识蓝图。实际上&#xff0c;针对不同的游戏类型和美术风格&#xff0c;制作技术在细节上有着非常大的不同&#xff0c;业界目…

HarmonyOS NEXT应用开发—自定义视图实现Tab效果

介绍 本示例介绍使用Text、List等组件&#xff0c;添加点击事件onclick,动画&#xff0c;animationTo实现自定义Tab效果。 效果预览图 使用说明 点击页签进行切换&#xff0c;选中态页签字体放大加粗&#xff0c;颜色由灰变黑&#xff0c;起到强调作用&#xff0c;同时&…

手撕算法-队列实现栈And栈实现队列

手撕算法-队列实现栈And栈实现队列 两个栈实现队列两个队列实现栈包含min函数的栈 两个栈实现队列 分析&#xff1a;转换数据方向&#xff0c;第一个栈写&#xff0c;第二个栈读。 代码&#xff1a; import java.util.*; import java.util.Stack;public class Solution {Sta…

PyCharm中如何使用不同的虚拟环境

1. 简介 有些项目用老的运行环境&#xff0c;而有些项目用新的运行环境&#xff0c;那么我们在运行这些代码&#xff08;比如跑对比实验的时候&#xff09;如何进行切换呢&#xff0c;这时候就可以使用虚拟环境啦 2. 虚拟环境的创建 首先启动Anaconda Prompt 并在其中执行如…

调皮的String及多种玩法(下部)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;&#x1f468;&#x1f3fb;‍&#x1f393;告别&#xff0c;今天 &#x1f4d4;高质量专栏 &#xff1a;☕java趣味之旅 欢迎&#x1f64f;点赞&#x1f5e3;️评论&#x1f4e5;收藏&#x1f493;关注 &#x1f496;衷心的希…