OpenCV 是一个用于计算机视觉应用程序的库。在 OpenCV 的帮助下,我们可以构建大量实时运行更好的应用程序。主要用于图像和视频处理。
可以在此处获取有关 OpenCV 的更多信息 (https://opencv.org/)
除了 OpenCV,我们将使用 MediaPipe 库。
1.MediaPipe简介
MediaPipe是一个主要用于构建音频、视频或任何时间序列数据的框架。在 MediaPipe 框架的帮助下,我们可以为不同的媒体处理功能构建管道。
MediaPipe 的一些主要应用。
-
多手追踪
-
人脸检测
-
对象检测和跟踪
-
Objection:3D 对象检测和跟踪
-
AutoFlip:自动视频裁剪管道等。
MediaPipe 使用单次手掌检测模型,一旦完成,它会对检测到的手部区域中的 21 个 3D 手掌坐标执行精确的关键点定位。
MediaPipe 管道使用多个模型,例如,从完整图像返回定向手边界框的手掌检测模型。裁剪后的图像区域被馈送到由手掌检测器定义的手部标志模型,并返回高保真 3D 手部关键点。
现在让我们实现手部跟踪模型。
安装所需的模块
–> pip install opencv-python
–> pip install mediapipe
注意:这里的python版本尽量在3.8以上,不然会报各种错误!!
首先,让我们检查网络摄像头的工作情况。
import cv2
import mediapipe as mp
import time
cap = cv2.VideoCapture(0)
mpHands = mp.solutions.hands
hands = mpHands.Hands(static_image_mode=False,
max_num_hands=2,
min_detection_confidence=0.5,
min_tracking_confidence=0.5)
mpDraw = mp.solutions.drawing_utils
pTime = 0
cTime = 0
while True:
success, img = cap.read()
img = cv2.flip(img, 1)
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
results = hands.process(imgRGB)
#print(results.multi_hand_landmarks)
if results.multi_hand_landmarks:
for handLms in results.multi_hand_landmarks:
for id, lm in enumerate(handLms.landmark):
#print(id,lm)
h, w, c = img.shape
cx, cy = int(lm.x *w), int(lm.y*h)
#if id ==0:
cv2.circle(img, (cx,cy), 3, (255,0,255), cv2.FILLED)
mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
cTime = time.time()
fps = 1/(cTime-pTime)
pTime = cTime
cv2.putText(img,str(int(fps)), (10,70), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,255), 3)
cv2.imshow("Image", img)
cv2.waitKey(1)
结果见图示:

2.mediapipe实现手掌拖拽屏幕中的方块
效果如示:



源码如下:
"""
功能:手势虚拟拖拽
1、使用OpenCV读取摄像头视频流;
2、识别手掌关键点像素坐标;
3、根据食指和中指指尖的坐标,利用勾股定理计算距离,当距离较小且都落在矩形内,则触发拖拽(矩形变色);
4、矩形跟着手指动;
5、两指放开,则矩形停止移动
"""
# 导入OpenCV
import cv2
# 导入mediapipe
import mediapipe as mp
# 导入其他依赖包
import time
import math
# 方块管理类
class SquareManager:
def __init__(self, rect_width):
# 方框长度
self.rect_width = rect_width
# 方块list
self.square_count = 0
self.rect_left_x_list = []
self.rect_left_y_list = []
self.alpha_list = []
# 中指与矩形左上角点的距离
self.L1 = 0
self.L2 = 0
# 激活移动模式
self.drag_active = False
# 激活的方块ID
self.active_index = -1
# 创建一个方块,但是没有显示
def create(self,rect_left_x,rect_left_y,alpha=0.4):
self.rect_left_x_list.append(rect_left_x)
self.rect_left_y_list.append(rect_left_y)
self.alpha_list.append(alpha)
self.square_count+=1
# 更新位置
def display(self,class_obj):
for i in range(0,self.square_count):
x= self.rect_left_x_list[i]
y= self.rect_left_y_list[i]
alpha = self.alpha_list[i]
overlay = class_obj.image.copy()
if(i == self.active_index):
cv2.rectangle(overlay,(x,y),(x+self.rect_width,y+self.rect_width),(255, 0, 255),-1)
else:
cv2.rectangle(overlay,(x,y),(x+self.rect_width,y+self.rect_width),(255, 0, 0),-1)
# Following line overlays transparent rectangle over the self.image
class_obj.image = cv2.addWeighted(overlay, alpha, class_obj.image, 1 - alpha, 0)
# 判断落在哪个方块上,返回方块的ID
def checkOverlay(self,check_x,check_y):
for i in range(0,self.square_count):
x= self.rect_left_x_list[i]
y= self.rect_left_y_list[i]
if (x < check_x < (x+self.rect_width) ) and ( y < check_y < (y+self.rect_width)):
# 保存被激活的方块ID
self.active_index = i
return i
&n

最低0.47元/天 解锁文章
708

被折叠的 条评论
为什么被折叠?



