计算机视觉 | OpenCV 实现手势虚拟控制亮度和音量

Hi,大家好,我是半亩花海。在当今科技飞速发展的时代,我们身边充斥着各种智能设备,然而,如何更便捷地与这些设备进行交互却是一个不断被探索的课题。本文将主要介绍一个基于 OpenCV 手势识别项目,通过手势来控制电脑屏幕亮度音量大小,为用户提供了一种全新的交互方式。


目录

一、代码拆解

1. 导入必要库

2. 手部关键点类

3. 数据格式转换

4. 画手势关键点

5. 手势状态缓冲处理

6. 画直线

7. 屏幕亮度和音量控制

8. 初始化摄像头和手部关键点识别器

9. Pygame 界面初始化和事件监听

二、实战演示

1. 亮度——light

2. 音量——voice

3. 菜单——menu

三、完整代码


一、代码拆解

1. 导入必要库

在开始介绍项目的实现细节之前,我们首先需要导入项目所需的必要库。这些库包括:

  • OpenCV:用于处理图像和视频数据。
  • Mediapipe:提供了对手部关键点的识别和跟踪功能。
  • Pygame:用于创建图形界面和显示摄像头捕获的图像。
  • WMI:用于调节电脑屏幕亮度。
  • pycaw:用于控制电脑的音量。
# 导入必要库
import math
import sys
import numpy as np
import cv2
import pygame
import wmi
import mediapipe as mp
from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
import warnings  # 忽略警告
warnings.filterwarnings("ignore")

2. 手部关键点类

首先创建一个 HandKeyPoint 类,用于初始化手部关键点检测器,并提供对图像进行处理的方法。

# 手部关键点类
class HandKeyPoint:def __init__(self,static_image_mode=False,max_num_hands=2,model_complexity=1,min_detection_confidence=0.5,min_tracking_confidence=0.5):# 手部识别apiself.mp_hands = mp.solutions.hands# 获取手部识别类self.hands = self.mp_hands.Hands(static_image_mode=static_image_mode,max_num_hands=max_num_hands,model_complexity=model_complexity,min_detection_confidence=min_detection_confidence,min_tracking_confidence=min_tracking_confidence)def process(self, image):# 将BGR转换为RGBimg = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)# 识别图像中的手势,并返回结果results = self.hands.process(img)# numpy格式的数据np_arr = landmarks_to_numpy(results)return results, np_arr

3. 数据格式转换

手部关键点的检测结果(将 landmarks 格式的数据)转换为 numpy 数组,以便后续的处理和分析。

# 将landmarks格式的数据转换为numpy格式的数据
def landmarks_to_numpy(results):"""将landmarks格式的数据转换为numpy格式的数据numpy shape:(2, 21, 3):param results::return:"""shape = (2, 21, 3)landmarks = results.multi_hand_landmarksif landmarks is None:# 没有检测到手return np.zeros(shape)elif len(landmarks) == 1:# 检测出一只手,先判断是左手还是右手label = results.multi_handedness[0].classification[0].labelhand = landmarks[0]# print(label)if label == "Left":return np.array([np.array([[hand.landmark[i].x, hand.landmark[i].y, hand.landmark[i].z] for i in range(21)]),np.zeros((21, 3))])else:return np.array([np.zeros((21, 3)),np.array([[hand.landmark[i].x, hand.landmark[i].y, hand.landmark[i].z] for i in range(21)])])elif len(landmarks) == 2:# print(results.multi_handedness)lh_idx = 0rh_idx = 0for idx, hand_type in enumerate(results.multi_handedness):label = hand_type.classification[0].labelif label == 'Left':lh_idx = idxif label == 'Right':rh_idx = idxlh = np.array([[landmarks[lh_idx].landmark[i].x, landmarks[lh_idx].landmark[i].y, landmarks[lh_idx].landmark[i].z] for iin range(21)])rh = np.array([[landmarks[rh_idx].landmark[i].x, landmarks[rh_idx].landmark[i].y, landmarks[rh_idx].landmark[i].z] for iin range(21)])return np.array([lh, rh])else:return np.zeros((2, 21, 3))

4. 画手势关键点

# 画手势关键点
def draw_landmark(img, results):if results.multi_hand_landmarks:for hand_landmark in results.multi_hand_landmarks:mp.solutions.drawing_utils.draw_landmarks(img,hand_landmark,mp.solutions.hands.HAND_CONNECTIONS,mp.solutions.drawing_styles.get_default_hand_landmarks_style(),mp.solutions.drawing_styles.get_default_hand_connections_style())return img

5. 手势状态缓冲处理

为了平滑处理手势状态的变化,我们实现了一个 Buffer 类,用于缓存手势状态的变化,并提供了添加正例和负例的方法。

# 缓冲区类
class Buffer:def __init__(self, volume=20):self.__positive = 0self.state = Falseself.__negative = 0self.__volume = volumeself.__count = 0def add_positive(self):self.__count += 1if self.__positive >= self.__volume:# 如果正例个数大于容量,将状态定为Trueself.state = Trueself.__negative = 0self.__count = 0else:self.__positive += 1if self.__count > self.__volume:# 如果大于容量次操作后还没有确定状态self.__positive = 0self.__count = 0def add_negative(self):self.__count += 1if self.__negative >= self.__volume:# 如果负例个数大于容量,将状态定为Falseself.state = Falseself.__positive = 0else:self.__negative += 1if self.__count > self.__volume:# 如果大于容量次操作后还没有确定状态self.__positive = 0self.__count = 0# print(f"pos:{self.__positive} neg:{self.__negative} count:{self.__count}")def clear(self):self.__positive = 0self.state = Falseself.__negative = 0self.__count = 0

6. 画直线

# 画线函数
def draw_line(frame, p1, p2, color=(255, 127, 0), thickness=3):"""画一条直线:param p1::param p2::return:"""return cv2.line(frame, (int(p1[0] * CAM_W), int(p1[1] * CAM_H)), (int(p2[0] * CAM_W), int(p2[1] * CAM_H)), color,thickness)

7. 屏幕亮度和音量控制

# 控制屏幕亮度
def screen_change(percent):  # percent/2即为亮度百分比SCREEN = wmi.WMI(namespace='root/WMI')a = SCREEN.WmiMonitorBrightnessMethods()[0]a.WmiSetBrightness(Brightness=percent, Timeout=500)# 初始化音量控制
def init_voice():devices = AudioUtilities.GetSpeakers()interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)volume = cast(interface, POINTER(IAudioEndpointVolume))volume.SetMute(0, None)volume_range = volume.GetVolumeRange()min_volume = volume_range[0]max_volume = volume_range[1]return (min_volume, max_volume), volume

8. 初始化摄像头和手部关键点识别器

在项目的初始化阶段,我们需要加载摄像头实例和手部关键点识别实例,以便后续对手势进行识别和处理。

# 加载摄像头实例
cap = cv2.VideoCapture(0)
CAM_W = 640
CAM_H = 480
CAM_SCALE = CAM_W / CAM_H# 加载手部关键点识别实例
hand = HandKeyPoint()

9. Pygame 界面初始化和事件监听

为了展示手势控制效果,并提供交互界面,我们使用了 Pygame 库。在初始化阶段,我们创建了一个窗口,并设置了标题。同时,我们实现了事件监听功能,以便在需要时退出程序

具体来说,我们使用 Pygame 创建了一个窗口,并将摄像头捕获的图像显示在窗口中。同时,我们利用 Pygame 的事件监听功能,监听用户的键盘事件,例如按下"q"键时退出程序。这样,用户就可以通过手势控制屏幕亮度和音量大小,同时在 Pygame 窗口中观察手势识别效果。

# 初始化pygame
pygame.init()
# 设置窗口全屏
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("virtual_control_screen")
# 获取当前窗口大小
window_size = list(screen.get_size())# 主循环
while True:
······# 事件监听 若按q则退出程序for event in pygame.event.get():if event.type == pygame.KEYDOWN:if event.key == pygame.K_q:sys.exit(0)

二、实战演示

1. 亮度——light

如果 20 < angle < 90,那么“light ready”即手势控制亮度

2. 音量——voice

如果 -20 > angle > -50,那么“voice ready”即手势控制音量

3. 菜单——menu

上述两种情况除外,那么处于“menu”状态即进入菜单

通过演示可以发现,食指与大拇指在屏幕中的距离越远,亮度越高(音量越大),反之越小,实现了通过手势对亮度和音量的控制。


三、完整代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
@Project : virtual
@File    : virtual_control.py
@IDE     : PyCharm
@Author  : 半亩花海
@Date    : 2024:02:06 18:01
"""
# 导入模块
import math
import sys
import numpy as np
import cv2
import pygame
import wmi
import mediapipe as mp
from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
import warnings  # 忽略警告
warnings.filterwarnings("ignore")# 手部关键点类
class HandKeyPoint:def __init__(self,static_image_mode=False,max_num_hands=2,model_complexity=1,min_detection_confidence=0.5,min_tracking_confidence=0.5):# 手部识别apiself.mp_hands = mp.solutions.hands# 获取手部识别类self.hands = self.mp_hands.Hands(static_image_mode=static_image_mode,max_num_hands=max_num_hands,model_complexity=model_complexity,min_detection_confidence=min_detection_confidence,min_tracking_confidence=min_tracking_confidence)def process(self, image):# 将BGR转换为RGBimg = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)# 识别图像中的手势,并返回结果results = self.hands.process(img)# numpy格式的数据np_arr = landmarks_to_numpy(results)return results, np_arr# 将landmarks格式的数据转换为numpy格式的数据
def landmarks_to_numpy(results):"""将landmarks格式的数据转换为numpy格式的数据numpy shape:(2, 21, 3):param results::return:"""shape = (2, 21, 3)landmarks = results.multi_hand_landmarksif landmarks is None:# 没有检测到手return np.zeros(shape)elif len(landmarks) == 1:# 检测出一只手,先判断是左手还是右手label = results.multi_handedness[0].classification[0].labelhand = landmarks[0]# print(label)if label == "Left":return np.array([np.array([[hand.landmark[i].x, hand.landmark[i].y, hand.landmark[i].z] for i in range(21)]),np.zeros((21, 3))])else:return np.array([np.zeros((21, 3)),np.array([[hand.landmark[i].x, hand.landmark[i].y, hand.landmark[i].z] for i in range(21)])])elif len(landmarks) == 2:# print(results.multi_handedness)lh_idx = 0rh_idx = 0for idx, hand_type in enumerate(results.multi_handedness):label = hand_type.classification[0].labelif label == 'Left':lh_idx = idxif label == 'Right':rh_idx = idxlh = np.array([[landmarks[lh_idx].landmark[i].x, landmarks[lh_idx].landmark[i].y, landmarks[lh_idx].landmark[i].z] for iin range(21)])rh = np.array([[landmarks[rh_idx].landmark[i].x, landmarks[rh_idx].landmark[i].y, landmarks[rh_idx].landmark[i].z] for iin range(21)])return np.array([lh, rh])else:return np.zeros((2, 21, 3))# 画手势关键点
def draw_landmark(img, results):if results.multi_hand_landmarks:for hand_landmark in results.multi_hand_landmarks:mp.solutions.drawing_utils.draw_landmarks(img,hand_landmark,mp.solutions.hands.HAND_CONNECTIONS,mp.solutions.drawing_styles.get_default_hand_landmarks_style(),mp.solutions.drawing_styles.get_default_hand_connections_style())return img# 缓冲区类
class Buffer:def __init__(self, volume=20):self.__positive = 0self.state = Falseself.__negative = 0self.__volume = volumeself.__count = 0def add_positive(self):self.__count += 1if self.__positive >= self.__volume:# 如果正例个数大于容量,将状态定为Trueself.state = Trueself.__negative = 0self.__count = 0else:self.__positive += 1if self.__count > self.__volume:# 如果大于容量次操作后还没有确定状态self.__positive = 0self.__count = 0def add_negative(self):self.__count += 1if self.__negative >= self.__volume:# 如果负例个数大于容量,将状态定为Falseself.state = Falseself.__positive = 0else:self.__negative += 1if self.__count > self.__volume:# 如果大于容量次操作后还没有确定状态self.__positive = 0self.__count = 0# print(f"pos:{self.__positive} neg:{self.__negative} count:{self.__count}")def clear(self):self.__positive = 0self.state = Falseself.__negative = 0self.__count = 0# 画线函数
def draw_line(frame, p1, p2, color=(255, 127, 0), thickness=3):"""画一条直线:param p1::param p2::return:"""return cv2.line(frame, (int(p1[0] * CAM_W), int(p1[1] * CAM_H)), (int(p2[0] * CAM_W), int(p2[1] * CAM_H)), color,thickness)# 控制屏幕亮度
def screen_change(percent):  # percent/2即为亮度百分比SCREEN = wmi.WMI(namespace='root/WMI')a = SCREEN.WmiMonitorBrightnessMethods()[0]a.WmiSetBrightness(Brightness=percent, Timeout=500)# 初始化音量控制
def init_voice():devices = AudioUtilities.GetSpeakers()interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)volume = cast(interface, POINTER(IAudioEndpointVolume))volume.SetMute(0, None)volume_range = volume.GetVolumeRange()min_volume = volume_range[0]max_volume = volume_range[1]return (min_volume, max_volume), volume# 加载摄像头实例
cap = cv2.VideoCapture(0)
CAM_W = 640
CAM_H = 480
CAM_SCALE = CAM_W / CAM_H# 加载手部关键点识别实例
hand = HandKeyPoint()# 初始化pygame
pygame.init()
# 设置窗口全屏
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("virtual_control_screen")
# 获取当前窗口大小
window_size = list(screen.get_size())# 设置缓冲区
buffer_light = Buffer(10)
buffer_voice = Buffer(10)last_y = 0
last_2_y = 1
last_2_x = 0# 初始化声音控制
voice_range, volume = init_voice()# 设置亮度条参数
bright_bar_length = 300
bright_bar_height = 20
bright_bar_x = 50
bright_bar_y = 100# 设置音量条参数
vol_bar_length = 300
vol_bar_height = 20
vol_bar_x = 50
vol_bar_y = 50# 主循环 每次循环就是对每帧的处理
while True:img_menu = Nonelh_index = -1# 读取摄像头画面success, frame = cap.read()# 将opencv中图片格式的BGR转换为常规的RGBframe = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 镜面反转frame = cv2.flip(frame, 1)# 处理图像res, arr = hand.process(frame)frame = draw_landmark(frame, res)scale = math.hypot((arr[0, 7, 0] - arr[0, 8, 0]),(arr[0, 7, 1] - arr[0, 8, 1]),(arr[0, 7, 2] - arr[0, 8, 2]))# 计算tan值tan = (arr[0, 0, 1] - arr[0, 12, 1]) / (arr[0, 0, 0] - arr[0, 12, 0])# 计算角度angle = np.arctan(tan) * 180 / np.pi# print(angle)if 20 < angle < 90:path = 'resources/menu/light.png'buffer_light.add_positive()buffer_voice.add_negative()# 显示亮度条和亮度刻度值show_brightness = Trueshow_volume = Falseelif -20 > angle > -50:path = 'resources/menu/voice.png'buffer_voice.add_positive()buffer_light.add_negative()# 显示音量条和音量刻度值show_brightness = Falseshow_volume = Trueelse:path = 'resources/menu/menu.png'buffer_light.add_negative()buffer_voice.add_negative()# 不显示刻度值和百分比show_brightness = Falseshow_volume = False# 计算拇指与食指之间的距离dis = math.hypot(int((arr[1, 4, 0] - arr[1, 8, 0]) * CAM_W), int((arr[1, 4, 1] - arr[1, 8, 1]) * CAM_H))# 右手映射时的缩放尺度s = math.hypot((arr[1, 5, 0] - arr[1, 9, 0]), (arr[1, 5, 1] - arr[1, 9, 1]), (arr[1, 5, 2] - arr[1, 9, 2]))# 调节亮度if buffer_light.state:frame = cv2.putText(frame, 'light ready', (10, 35), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 127, 0))frame = draw_line(frame, arr[1, 4], arr[1, 8], thickness=5, color=(255, 188, 66))if dis != 0:# 线性插值,可以理解为将一个区间中的一个值映射到另一区间内light = np.interp(dis, [int(500 * s), int(3000 * s)], (0, 100))# 调节亮度screen_change(light)# 调节声音elif buffer_voice.state:frame = cv2.putText(frame, 'voice ready', (10, 35), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 127, 0))frame = draw_line(frame, arr[1, 4], arr[1, 8], thickness=5, color=(132, 134, 248))if dis != 0:vol = np.interp(dis, [int(500 * s), int(3000 * s)], voice_range)# 调节音量volume.SetMasterVolumeLevel(vol, None)# 将图片改为与窗口一样的大小frame = cv2.resize(frame, (int(window_size[1] * CAM_SCALE), window_size[1]))frame = cv2.transpose(frame)# 渲染图片frame = pygame.surfarray.make_surface(frame)screen.blit(frame, (int(0.5 * (CAM_W - CAM_H * CAM_SCALE)), 0))img_menu = pygame.image.load(path).convert_alpha()img_w, img_h = img_menu.get_size()img_menu = pygame.transform.scale(img_menu, (int(img_w * scale * 5), int(img_h * scale * 5)))x = (arr[0][9][0] + arr[0][13][0] + arr[0][0][0]) / 3y = (arr[0][9][1] + arr[0][13][1] + arr[0][0][1]) / 3x = int(x * window_size[0] - window_size[0] * scale * 3.5)y = int(y * window_size[1] - window_size[1] * scale * 12)# print(x, y)screen.blit(img_menu, (x, y))# 绘制音量条和亮度条的外框if show_volume:pygame.draw.rect(screen, (255, 255, 255), (vol_bar_x, vol_bar_y, vol_bar_length, vol_bar_height), 3)elif show_brightness:pygame.draw.rect(screen, (255, 255, 255), (bright_bar_x, bright_bar_y, bright_bar_length, bright_bar_height),3)# 计算当前音量和亮度在条上的位置和大小,并绘制已填充的条if show_volume:vol = volume.GetMasterVolumeLevel()vol_range = voice_range[1] - voice_range[0]vol_bar_fill_length = int((vol - voice_range[0]) / vol_range * vol_bar_length)pygame.draw.rect(screen, (0, 255, 0), (vol_bar_x, vol_bar_y, vol_bar_fill_length, vol_bar_height))# 显示音量刻度值和当前音量大小vol_text = f"Volume: {int((vol - voice_range[0]) / vol_range * 100)}%"vol_text_surface = pygame.font.SysFont(None, 24).render(vol_text, True, (255, 255, 255))screen.blit(vol_text_surface, (vol_bar_x + vol_bar_length + 10, vol_bar_y))elif show_brightness:brightness = wmi.WMI(namespace='root/WMI').WmiMonitorBrightness()[0].CurrentBrightnessbright_bar_fill_length = int(brightness / 100 * bright_bar_length)pygame.draw.rect(screen, (255, 255, 0), (bright_bar_x, bright_bar_y, bright_bar_fill_length, bright_bar_height))# 显示亮度刻度值和当前亮度大小bright_text = f"Brightness: {brightness}%"bright_text_surface = pygame.font.SysFont(None, 24).render(bright_text, True, (255, 255, 255))screen.blit(bright_text_surface, (bright_bar_x + bright_bar_length + 10, bright_bar_y))pygame.display.flip()# 事件监听 若按q则退出程序for event in pygame.event.get():if event.type == pygame.KEYDOWN:if event.key == pygame.K_q:sys.exit(0)

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

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

相关文章

30s速通String——从JVM内存 到相关方法

0.深度理解String&#xff08;初学者可后面再看&#xff09; 1.JVM理解两种初始化String方式 1.1直接初始化 栈中保存变量s1,s2&#xff0c;而变量保存“abc”在方法区的地址 这里当“abc”具有唯一性&#xff0c;字符串常量区无此字符串&#xff0c;我们就产生一个新内存“…

AI数字人训练数据集汇总

唇读&#xff08;Lip Reading&#xff09;&#xff0c;也称视觉语音识别&#xff08;Visual Speech Recognition&#xff09;&#xff0c;通过说话者口 型变化信息推断其所说的内容&#xff0c;旨在利用视觉信道信息补充听觉信道信息&#xff0c;在现实生活中有重要应用。例如&…

QT Linux下无法使用CTRL+ALT+P快捷键,不生效

文章目录 一、背景二、排查&#xff08;1&#xff09;检查创建&#xff0c;发现没问题。&#xff08;2&#xff09;查看 shortcutMap 是否注册&#xff08;3&#xff09;排查xcb有没有获取到该事件&#xff08;4&#xff09;排查是否是系统的问题&#xff08;5&#xff09;www.…

TCP 粘包/拆包

文章目录 概述粘包拆包发生场景解决TCP粘包和拆包问题的常见方法Netty对粘包和拆包问题的处理小结 概述 TCP的粘包和拆包问题往往出现在基于TCP协议的通讯中&#xff0c;比如RPC框架、Netty等 TCP 粘包/拆包 就是你基于 TCP 发送数据的时候&#xff0c;出现了多个字符串“粘”…

前端页面禁止debugger调试并跳转空白页面----文心一言官网实现方式

技术点&#xff1a;setInterval定时器Object.defineProperty 背景&#xff1a; 某天打开文心一言想看看接口返回结构是怎样的&#xff0c;熟练的打开浏览器开发者工具查看网络请求。 发现出现了以下debugger断点 这难不倒我&#xff0c;去掉断点调试&#xff0c;继续下一步不…

MyBatis多数据源以及动态切换实现(基于SpringBoot 2.7.x)

MyBatis多数据源以及动态切换实现可以实现不同功能模块可以对应到不同的数据库&#xff0c;现在就让我们来讲解一下。 目录 一、引入Maven二、配置文件三、实现多数据源四、动态切换数据源 一、引入Maven 注意&#xff1a;博主这边使用的springboot版本是2.7.14的 <!-- htt…

LeetCode:26.删除有序数组中的重复项

26. 删除有序数组中的重复项 - 力扣&#xff08;LeetCode&#xff09; 目录 题目&#xff1a; 思路&#xff1a; 代码注释&#xff1a; 每日表情包&#xff1a; 题目&#xff1a; 思路&#xff1a; 没啥特殊的&#xff0c;老老实实双指针遍历数组&#xff0c;&#xff0…

获取旁站 / C 段:第三方网站(附链接)

一、介绍 1.1 旁段 在网络安全的上下文中&#xff0c;"旁段"&#xff08;Pivot&#xff09;是指攻击者通过入侵一个网络中的一台计算机&#xff0c;然后利用该计算机作为跳板&#xff08;或者称之为“旁道”&#xff09;来访问其他计算机或网络资源的行为。 攻击者…

如何启动若依框架

Mysql安装 一、下载 链接&#xff1a;https://pan.baidu.com/s/1s8-Y1ooaRtwP9KnmP3rxlQ?pwd1234 提取码&#xff1a;1234 二、安装(解压) 下载完成后我们得到的是一个压缩包&#xff0c;将其解压&#xff0c;我们就可以得到MySQL 5.7.24的软件本体了(就是一个文件夹)&…

虚幻5源码版打包服务端

适用情况&#xff0c;windows系统&#xff0c;已经安装vs2022之类的&#xff0c;和UE5适配的版本 源码版使用 1.下载源码版&#xff0c;推荐下载 压缩包 tar.gz那个&#xff0c;zip和git clone我老是下载不下载来&#xff0c;只是这个压缩包要解压1个多小时… 2.点击 源码的…

【RT-DETR有效改进】利用SENetV1重构化网络结构 (ILSVRC冠军得主)

👑欢迎大家订阅本专栏,一起学习RT-DETR👑 一、本文介绍 本文给大家带来的改进机制是SENet(Squeeze-and-Excitation Networks)其是一种通过调整卷积网络中的通道关系来提升性能的网络结构。SENet并不是一个独立的网络模型,而是一个可以和现有的任何一个模型相结合…

自动暂停和恢复网页中的视频播放

序言 在日常开发中&#xff0c;有时候一级栏目可能是个H5页面&#xff0c;当切换到其他栏目的时候需要自动暂停H5中的视频&#xff0c;切换回来以后需要自动恢复播放。实现的思路是通过JS来操作&#xff0c;难点是感知fragment的可见状态。还有js代码的编写。 比如下面这个页…

PyTorch的10个基本张量操作

PyTorch是一个基于python的科学计算包。它的灵活性允许轻松集成新的数据类型和算法&#xff0c;并且框架也是高效和可扩展的&#xff0c;下面我们将介绍一些Pytorch的基本张量操作。 Tensors 张量Tensors是一个向量&#xff0c;矩阵或任何n维数组。这是深度学习的基本数据结构…

DevExpress WinForms中文教程 - 如何创建可访问的WinForms应用?(二)

为用户创建易访问的Windows Forms应用程序不仅是最佳实践的体现&#xff0c;还是对包容性和以用户为中心的设计承诺。在应用程序开发生命周期的早期考虑与可访问性相关的需求可以节省长期运行的时间(因为它将决定设计决策和代码实现)。 一个可访问的WinForms应用程序提供了各种…

20240202在Ubuntu20.04.6下使用whisper.cpp的显卡模式

20240202在Ubuntu20.04.6下使用whisper.cpp的显卡模式 2024/2/2 19:43 【结论&#xff1a;在Ubuntu20.04.6下&#xff0c;确认large模式识别7分钟中文视频&#xff0c;需要356447.78 ms&#xff0c;也就是356.5秒&#xff0c;需要大概5分钟&#xff01;效率太差&#xff01;】 …

CleanMyMac2024如何识别并清理垃圾文件?

CleanMyMac识别并清理垃圾文件的过程主要依赖于其强大的扫描功能和智能算法。以下是具体的步骤&#xff1a; 扫描垃圾文件&#xff1a;首先&#xff0c;用户需要打开CleanMyMac软件&#xff0c;并点击“智能扫描”功能。然后&#xff0c;软件将开始自动扫描Mac系统上的各种垃圾…

微信小程序(基本操作)

概念&#xff1a; 小程序&#xff1a;就是小程序&#xff0c;mini program。现在市面上有微信小程序&#xff0c;百度智能小程序等等。 微信小程序&#xff0c;简称小程序&#xff0c;英文名Mini Program&#xff0c;是一种不需要下载安装即可使用的应用&#xff0c;它实现了…

5-4、S加减单片机程序【51单片机+L298N步进电机系列教程】

↑↑↑点击上方【目录】&#xff0c;查看本系列全部文章 摘要&#xff1a;本节介绍实现步进电机S曲线运动的代码 一、目标功能 实现步进电机转动总角度720&#xff0c;其中加减速各90 加速段&#xff1a;加速类型&#xff1a;S曲线  加速角度&#xff1a;角度为90  起步速度…

CSS太极动态图

CSS太极动态图 1. 案例效果 我们今天学习用HTML和CSS实现动态的太极&#xff0c;看一下效果。 2. 分析思路 太极图是由两个旋转的圆组成&#xff0c;一个是黑圆&#xff0c;一个是白圆。实现现原理是使用CSS的动画和渐变背景属性。 首先&#xff0c;为所有元素设置默认值为0…

Topaz Photo AI for Mac v2.3.1 补丁版人工智能降噪软件无损放大

想要将模糊的图片变得更加清晰&#xff1f;不妨试试Topaz Photo AI for Mac 这款人工智能、无损放大软件。Topaz Photo AI for Mac 一款强大的人工智能降噪软件&#xff0c;允许用户使用复杂的锐化算法来提高图像清晰度&#xff0c;还包括肖像编辑选项&#xff0c;如面部重塑、…