百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

从图像分类到对象检测,OpenCV彻底改变图像处理领域

suiw9 2024-11-12 14:13 25 浏览 0 评论

前言:

OpenCV 彻底改变了整个图像处理领域。从图像分类到对象检测,我们不仅可以使用 OpenCV 库做一些很酷的事情,而且还可以构建一流的应用程序。本文将用OpenCV实现虚拟缩放,需要的可以参考一下

介绍

OpenCV 彻底改变了整个图像处理领域。从图像分类到对象检测,我们不仅可以使用 OpenCV 库做一些很酷的事情,而且还可以构建一流的应用程序。

今天我们要实现一个有趣的东西,它是手机或电脑中的一种功能,即图像缩放。但在这里,它将是实时对帧上所需的图像进行虚拟缩放。

要求

对于这个项目,我们将使用 OpenCV 库和另一个名为 Cvzone 的库来使用虚拟缩放。

CVZone

它是一个建立在 OpenCV 和 MediaPipe 之上的库。它使事情变得容易得多。

CVZone 具有一些非常有用的内置功能,例如手部跟踪、面部标志检测、姿势估计等等。这些都可以通过几行代码来完成。

让我们编写一段代码来看看使用 CVZone 的手部检测器的演示。首先,安装 requirements 。你可以使用以下命令安装它,也可以逐个安装。

– pip install -r requirements.txt

– pip install opencv-python==3.4.11.43

– pip install cvzone==1.5.3

现在让我们检测手。

import cv2
from cvzone.HandTrackingModule import HandDetector
# Input from webcam
frame = cv2.VideoCapture(0)
frame.set(3, 1280)
frame.set(4, 720)
 
# initialize hand detector module with some confidence
handDetector = HandDetector(detectionCon=0.8)
 
# loop
while True:
# Read the frames from webcam
res, img = frame.read()
 
# detect the hands, by default it will detect two hands
hands = handDetector.findHands(img)
 
# show the output
cv2.imshow(“Sample CVZone output”, img)
cv2.waitKey(1)

首先,让我们导入所需的模块,cv2,以及从 cvzone.HandTrackingModule 导入HandDetector*。*

然后我们将使用 OpenCV 的 Videocapture 功能从网络摄像头获取输入。设置窗口的高度和宽度,并以一定的检测置信度初始化手部检测器模块。

然后在循环内部从网络摄像头读取输入帧并将其传递给手部检测器模块内部的方法,即 findHands。显示图像。

与此类似,我们也可以使用 CVZone 实现面部地标检测、姿势估计等。

目标

我们的目标是构建一个屏幕上有图像的项目,使用 OpenCV 进行虚拟缩放,并使用我们的手势,即如果双手的食指和拇指向上并且两根手指彼此远离,就放大,如果双手的食指和拇指向上并且两根手指彼此靠近,则缩小该图像或对象。牢记这一点,我们将制定一些步骤。

步骤

初始化来自网络摄像头的输入。

设置输出窗口的高度和宽度。

初始化手部检测器模块。

分别声明计算距离、缩放范围、中心X和中心Y的4个变量。

读取输入帧。

检测双手。

读取用于缩放操作的图像。

检查是否检测到两只手。

检查食指和拇指是否向上。

计算两只手之间的距离,并将图像调整到两只手的中心。

计算新的高度和宽度,然后调整图像大小。

显示输出。

构建

如上一节所述安装所需的库。现在让我们开始吧。

首先,导入所需的模块。这里我们只需要 cv2 和 cvzone 的手部检测器模块。

导入库后,使用 cv2.VideoCapture(0) 从网络摄像头获取输入,其中 0 是网络摄像头 ID。

然后设置输出窗口的宽度和高度。这里是 1280 x 720。

import cv2
from cvzone.HandTrackingModule import HandDetector
# Input from webcam
frame = cv2.VideoCapture(0)
frame.set(3, 1280)
frame.set(4, 720)

现在,我们将初始化手检测模块(handDetector),检测置信度为 0.8,并将在 while 循环中用于检测手。

声明 4 个变量,一个是初始存储距离,它是None,一个是缩放范围,初始是0,另外 2 个用于捕捉缩放对象的中心 X 和中心 Y,并设置一些随机值。

这里代码中的变量分别是 distStart、zoom_range、cx、cy。

# initialize hand detector module
handDetector = HandDetector(detectionCon=0.8)
distStart = None
zoom_range = 0
cx, cy = 500, 500

开始一个while循环,从现在开始,一切操作都应该在这个循环中。

从网络摄像头读取输入,并使用上面初始化的手部检测器模块,我们可以调用方法 findHands 将帧作为输入传递。此方法会在框架中找到手,默认它可以检测框架中的两只手并返回手的列表。

我们可以从中访问每只检测到的手(这里:一只手为hands[0],另一只手为hands[1]),并且它还返回图像。然后我们将使用 OpenCV 的 imread() 函数读取屏幕上要缩放的图像。最好图像大小应低于 (250, 250),否则你可以使用 cv2.resize(img, (250,250)) 调整其大小。这里图像大小为 (225, 225)。

while True:
    # Read the input frame
    res, img = frame.read()
    # Detect the hands
    hands, img = handDetector.findHands(img)
    # Image to be zoomed
    new_img = cv2.imread('resized_test.jpg')

现在,我们需要检查框架中是否有两只手,然后我们将检查食指和拇指是否向上,这可以使用手检测模块中的 FingerUp() 方法轻松完成。

在下面的第一个 if 语句之后的代码中,我们将使用两个打印语句 print(handDetector.fingersUp(hands[0])) ,如果食指和拇指向上,则这将打印一个包含 5 个元素的列表,结果列表显示一只手将是 [1, 1, 0, 0, 0],另一只手类似地执行 print(handDetector.fingersUp(hands[1]))。

请参考下图。

# if two hands are detected
if len(hands) == 2:
    print("Start Zoom...")
    print(handDetector.fingersUp(hands[0]))
    print(handDetector.fingersUp(hands[1]))

然后是重要的部分,现在我们需要检查双手的食指和拇指是否向上。我们将再次使用 if 语句(在第一个 if 语句中:if handDetector.fingersUp(hands[0]) == [1, 1, 0, 0, 0] 和 handDetector.fingersUp(hands[1]) == [ 1, 1, 0, 0, 0]:) 然后求两只手之间的距离,具体来说就是食指两点之间的距离。

在下面的代码中,findDistance() 方法将找到距离,这里我们将两只手的中心作为参数与框架一起传递。findDistance() 方法将返回三个项目距离,一个包含位置 4 和 5 的中心 X 和中心 Y 的元组以及图像。

如果仅当 distStart 为 None 时才执行条件,则将获得的距离分配给我们之前声明的第三个变量 distStart。然后,计算新距离并从旧距离 distStart 中减去它,并执行除以 2 (向下取整)以获得缩放范围。然后将中心坐标分配给变量cx,cy。然后,如果框架中没有两只手,则将 distStart 变量重置为 None。

if handDetector.fingersUp(hands[0]) == [1, 1, 0, 0, 0] and handDetector.fingersUp(hands[1]) == [1, 1, 0, 0, 0]:
        # print("Start Zoom...")
        lmList1 = hands[0]['lmList']
        lmList2 = hands[1]['lmList']
        # point 8 is tip of the index finger
        if distStart is None:
            # length, info, img = handDetector.findDistance(lmList1[8], lmList2[8], img)
            # draw the connection points between right hand index and thum finger to left hand
            length, info, img = handDetector.findDistance(hands[0]['center'], hands[1]['center'], img)
            # print(length)
            distStart = length
# length, info, img = handDetector.findDistance(lmList1[8], lmList2[8], img)
length, info, img = handDetector.findDistance(hands[0][‘center'], hands[1][‘center'], img)
# info gives center x and center y
# calculate the zoom range
zoom_range = int((length – distStart) // 2)
# calculate the center point so that we can place the zooming image at the center
cx, cy = info[4:] print(zoom_range)
 
else:
distStart = None

然后获取要放大的图像的高度和宽度,并计算图像的新高度和宽度。这有点棘手,要获得新的高度和宽度,我们需要将图像之前的高度和宽度添加到缩放范围并执行向下取整除法,然后乘以 2。

然后我们可以动态找到放置缩放的位置图像(这里:img[cy – newH // 2:cy + newH // 2, cx – newW // 2:cx + newW // 2])。

但是还有一个问题,如果缩放后的图像低于窗口边距,则会出错,为了解决这个问题,我们将使用 try 和 except。然后显示输出。

try:
    h, w, _ = new_img.shape
# new height and new width
newH, newW = ((h + zoom_range) // 2) * 2, ((w + zoom_range) // 2) * 2
new_img = cv2.resize(new_img, (newW, newH))
 
# we want the zooming image to be center and place it approx at the center
img[cy – newH // 2:cy + newH // 2, cx – newW // 2:cx + newW // 2] = new_img
 
except:
pass
 
# display output
cv2.imshow(‘output', img)
cv2.waitKey(1)

完整的代码也可以在这个 GitHub 中找到

结论

这就是这篇关于使用 OpenCV 进行虚拟缩放的博客的内容。如果你想即兴发挥,让它更有趣,你可以在屏幕上保留一些图像,每次选择一个并放大它,或者你可以创建不同的形状,使用不同的手势来让它变大或变小。这就是我们如何使用 OpenCV 实现虚拟缩放。

相关推荐

10款超实用JavaScript音频库(js播放音频代码)

HTML5提供了一种新的音频标签实现和规范用一个简单的HTML对象而无需音频插件来控制音频。这只是一个简单的整合这些新的HTML5音频特征及使用JavaScript来创建各种播放控制。下面将介绍10款...

Howler.js,一款神奇的 JavaScript 开源网络音频工具库

o...

PROFINET转Modbus网关——工业协议融合的智能枢纽

三格电子SG-PNh750-MOD-221,无缝连接Profinet与Modbus,赋能工业物联产品概述...

简单实用的Modbus类库,支持从站和DTU

一、简介...

[西门子PLC] S7-200 SMART PROFINET :通过GSD组态PLC设备

从S7-200SMARTV2.5版本开始,S7-200SMART开始支持做PROFINETIO通信的智能设备。从而,两个S7-200SMART之间可以进行PROFINETI...

Modbus(RTU / TCP)有什么异同(modbus tcp和tcp)

Modbus是一种广泛使用的工业自动化通信协议,它支持设备之间的数据交换。Modbus协议有两个主要的变体:ModbusRTU(二进制模式)和ModbusTCP(基于TCP/IP网络的模式)。尽管...

Modbus通信调试步骤详解(modbus调试工具怎么用)

Modbus通信调试步骤详解  Modbus通信分为串口和以太网,无论是串口还是以太网,只要是标准Modbus,就可以用Modbus模拟器进行调试。按以下几步进行调试。...

理解Intel手册汇编指令(intel 汇编指令手册)

指令格式...

「西门子PLC」S7-200 SMART的Modbus RTU通讯

S7-200SMART集成的RS485端口(端口0)以及SBCM01RS485/232信号板(端口1)两个通信端口可以同时做MODBUSRTU主站,或者一个做MODBUSRTU主站一个做MO...

InfiniBand网络运维全指南:从驱动安装到故障排查

一、InfiniBand网络概述InfiniBand(直译为“无限带宽”技术,缩写为IB)是一种用于高性能计算的计算机网络通信标准,具有极高的吞吐量和极低的延迟,用于计算机与计算机之间的数据互连。它...

一加回归 OPPO,背后的秘密不可告人

有这样一个手机品牌,它诞生于互联网品牌。在大众群体看来,它的身世似乎模糊不清,许多人以为它是国外品牌。它的产品定位是极客群体,深受国内发烧友,甚至国外极客玩家喜爱。...

[西门子PLC] S7-200SMART快速高效的完成Modbus通信程序的设计

一、导读Modbus通信是一种被广泛应用的通信协议,在变频器、智能仪表还有其他一些智能设备上都能见到它的身影。本文呢,就把S7-200SMART系列PLC当作Modbus主站,把...

狂肝10个月手搓GPU,他们在我的世界中玩起我的世界,梦想成真

梦晨衡宇萧箫发自凹非寺量子位|公众号QbitAI自从有人在《我的世界》里用红石电路造出CPU,就流传着一个梗:...

[西门子PLC] 博途TIA portal SCL编程基础入门:1-点动与自锁

一、S7-SCL编程语言简介...

工作原理系列之:Modbus(modbus工作过程)

MODBUS是一种在自动化工业中广泛应用的高速串行通信协议。该协议是由Modion公司(现在由施耐德电气公司获得)于1979年为自己的可编程逻辑控制器开发的。该协议充当了PLCS和智能自动化设备之间的...

取消回复欢迎 发表评论: