OpenCV实现手势虚拟拖拽

前言: Hello大家好,我是Dream。 今天来学习一下如何使用OpenCV实现手势虚拟拖拽,欢迎大家一起前来探讨学习~

一、主要步骤及库的功能介绍

1.主要步骤

要实现本次实验,主要步骤如下:

  1. 导入OpenCV库。
  2. 通过OpenCV读取摄像头的视频流。
  3. 使用肤色检测算法(如色彩空间转换和阈值分割)来识别手部区域。
  4. 对手部区域进行轮廓检测,找到手的轮廓。
  5. 根据手的轮廓,获取手指关键点的像素坐标。对于拖拽手势,可以关注食指和中指的位置。
  6. 计算食指和中指指尖之间的距离并判断是否满足条件触发拖拽动作。
  7. 如果满足条件,可以使用勾股定理计算距离,并将矩形区域变色以示触发拖拽。
  8. 根据手指的位置更新矩形的坐标,使矩形跟随手指运动。
  9. 当手指放开时停止矩形的移动。

2.需要的库介绍

导入的库在实现手势虚拟拖拽的代码中起着重要的作用,下面是对每个库的简要介绍:

  1. OpenCV (cv2): OpenCV是一个开源的计算机视觉库,提供了丰富的图像和视频处理功能,使用OpenCV来读取摄像头视频流、进行图像处理和计算

  2. mediapipe (mp): mediapipe提供一系列预训练的机器学习模型和工具,用于实现计算机视觉和机器学习任务。我们使用mediapipe来进行手部关键点检测和姿势估计

  3. time: 我们使用time库来计时和进行时间相关的操作。

  4. math: 在本次实验我们使用math库来计算距离和角度

二、导入所需要的模块

# 导入OpenCV
import cv2
# 导入mediapipe
import mediapipe as mp# 导入其他依赖包
import time
import math

三、方块管理类

(SquareManager)是一个方块管理器,用于创建、显示、更新和处理方块的相关操作。

1.初始化方块管理器

初始化方块管理器,传入方块的长度(rect_width)作为参数,并初始化方块列表、距离、激活状态和激活的方块ID等属性。

class SquareManager:def __init__(self, rect_width):# 方框长度self.rect_width = rect_width# 方块列表self.square_count = 0self.rect_left_x_list = []self.rect_left_y_list = []self.alpha_list = []# 中指与矩形左上角点的距离self.L1 = 0self.L2 = 0# 激活移动模式self.drag_active = False# 激活的方块IDself.active_index = -1

2.创建一个方块

创建一个方块,将方块的左上角坐标和透明度添加到相应的列表中。

# 创建一个方块,但是没有显示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

3.更新显示方块的位置

根据方块的状态,在图像上绘制方块,并使用透明度将叠加图像叠加到原始图像上。

 # 更新显示方块的位置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)# 使用透明度将叠加图像叠加到原始图像上class_obj.image = cv2.addWeighted(overlay, alpha, class_obj.image, 1 - alpha, 0)

4.判断落点方块

判断给定的坐标是否在方块内,并返回方块的ID。

    # 判断落在哪个方块上,返回方块的IDdef 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)):# 保存被激活的方块IDself.active_index = ireturn ireturn -1

5.计算距离、更新位置

​​setLen​ 方法:计算激活方块与指尖的距离。
​​updateSquare​ 方法:根据给定的新坐标更新激活方块的位置。

    # 计算与指尖的距离def setLen(self, check_x, check_y):# 计算距离self.L1 = check_x - self.rect_left_x_list[self.active_index]self.L2 = check_y - self.rect_left_y_list[self.active_index]# 更新方块位置def updateSquare(self, new_x, new_y):self.rect_left_x_list[self.active_index] = new_x - self.L1self.rect_left_y_list[self.active_index] = new_y - self.L2

三、识别控制类

1.初始化识别控制类

class HandControlVolume:def __init__(self):# 初始化mediapipeself.mp_drawing = mp.solutions.drawing_utilsself.mp_drawing_styles = mp.solutions.drawing_stylesself.mp_hands = mp.solutions.hands# 中指与矩形左上角点的距离self.L1 = 0self.L2 = 0# image实例,以便另一个类调用self.image = None

HandControlVolume用于初始化mediapipe以及存储中指与矩形左上角点的距离和image实例。

  • __init__ 方法:在初始化对象时,初始化mediapipe,包括drawing_utils、drawing_styles和hands。此外,还初始化了中指与矩形左上角点的距离和image实例。

通过mediapipe,可以进行手部关键点检测和姿势估计,进而进行手势识别和处理。为了使其他类能够调用image实例,将其作为该类的属性进行存储,方便地处理手势识别和控制操作。

2.主函数

这部分代码主要用于初始化和准备处理视频流以进行手势识别和交互。

    def recognize(self):# 计算刷新率fpsTime = time.time()# OpenCV读取视频流cap = cv2.VideoCapture(0)# 视频分辨率resize_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))resize_h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))# 画面显示初始化参数rect_percent_text = 0# 初始化方块管理器squareManager = SquareManager(150)# 创建多个方块for i in range(0, 5):squareManager.create(200 * i + 20, 200, 0.6)with self.mp_hands.Hands(min_detection_confidence=0.7,min_tracking_confidence=0.5,max_num_hands=2) as hands:while cap.isOpened():# 初始化矩形success, self.image = cap.read()self.image = cv2.resize(self.image, (resize_w, resize_h))if not success:print("空帧.")continue
  • resize_wresize_h:根据摄像头分辨率获取的视频帧的宽度和高度,并作为后续处理的图像尺寸进行缩放。

  • rect_percent_text:画面显示初始化参数,可能被用于屏幕上的文本显示。

  • squareManager:初始化了方块管理器类的实例,并设置方块的长度为150。

使用一个循环,创建了五个方块,并通过create方法将其添加到方块管理器中。进入循环,从视频流中读取帧图像,并将其调整为指定的尺寸。如果成功读取帧图像,则会进一步处理,否则将输出错误消息。

3.提高性能和处理图像

                self.image.flags.writeable = False# 转为RGBself.image = cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB)# 镜像self.image = cv2.flip(self.image, 1)# mediapipe模型处理results = hands.process(self.image)self.image.flags.writeable = Trueself.image = cv2.cvtColor(self.image, cv2.COLOR_RGB2BGR)
  • self.image.flags.writeable = False:设置图像为不可写,以提高性能并避免数据拷贝。

  • self.image = cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB):将BGR格式的图像转换为RGB格式,因为mediapipe模型处理的输入图像需要是RGB格式。

  • self.image = cv2.flip(self.image, 1):将图像进行镜像翻转,以与mediapipe模型期望的手部位置对应。

  • results = hands.process(self.image):将处理后的图像传递给mediapipe的hands模型,进行手势识别和处理。

  • self.image = cv2.cvtColor(self.image, cv2.COLOR_RGB2BGR):将图像从RGB格式转换回BGR格式,以便后续的显示和处理。

4.检测手掌,标记关键点和连接关系

                if results.multi_hand_landmarks:# 遍历每个手掌for hand_landmarks in results.multi_hand_landmarks:# 在画面标注手指self.mp_drawing.draw_landmarks(self.image,hand_landmarks,self.mp_hands.HAND_CONNECTIONS,self.mp_drawing_styles.get_default_hand_landmarks_style(),self.mp_drawing_styles.get_default_hand_connections_style())
  • if results.multi_hand_landmarks::检查是否检测到手掌。如果有检测到手掌,则进入下一步处理;否则跳过。

  • for hand_landmarks in results.multi_hand_landmarks::遍历检测到的每个手掌。

  • self.mp_drawing.draw_landmarks:使用mediapipe的draw_landmarks方法,在图像上标记手指的关键点和连接关系。

self.image:输入的图像。hand_landmarks:手掌的关键点。

self.mp_hands.HAND_CONNECTIONS:手指之间的连接关系。

5.解析检测到的手掌并提取手指的关键点

检测到的手掌并提取手指的关键点,然后将手指的坐标存储起来。

                        landmark_list = []# 用来存储手掌范围的矩形坐标paw_x_list = []paw_y_list = []for landmark_id, finger_axis in enumerate(hand_landmarks.landmark):landmark_list.append([landmark_id, finger_axis.x, finger_axis.y,finger_axis.z])paw_x_list.append(finger_axis.x)paw_y_list.append(finger_axis.y)if landmark_list:# 比例缩放到像素ratio_x_to_pixel = lambda x: math.ceil(x * resize_w)ratio_y_to_pixel = lambda y: math.ceil(y * resize_h)# 设计手掌左上角、右下角坐标paw_left_top_x, paw_right_bottom_x = map(ratio_x_to_pixel,[min(paw_x_list), max(paw_x_list)])paw_left_top_y, paw_right_bottom_y = map(ratio_y_to_pixel,[min(paw_y_list), max(paw_y_list)])# 给手掌画框框cv2.rectangle(self.image, (paw_left_top_x - 30, paw_left_top_y - 30),(paw_right_bottom_x + 30, paw_right_bottom_y + 30), (0, 255, 0), 2)# 获取中指指尖坐标middle_finger_tip = landmark_list[12]middle_finger_tip_x = ratio_x_to_pixel(middle_finger_tip[1])middle_finger_tip_y = ratio_y_to_pixel(middle_finger_tip[2])# 获取食指指尖坐标index_finger_tip = landmark_list[8]index_finger_tip_x = ratio_x_to_pixel(index_finger_tip[1])index_finger_tip_y = ratio_y_to_pixel(index_finger_tip[2])# 中间点between_finger_tip = (middle_finger_tip_x + index_finger_tip_x) // 2, (middle_finger_tip_y + index_finger_tip_y) // 2thumb_finger_point = (middle_finger_tip_x, middle_finger_tip_y)index_finger_point = (index_finger_tip_x, index_finger_tip_y)
  • landmark_list:一个列表,用于存储手指的关键点信息。

  • paw_x_listpaw_y_list:用于存储手掌范围的矩形框的横纵坐标。

  • 在循环中,将每个手指的关键点的索引、x坐标、y坐标和z坐标存储在landmark_list中,同时将手掌范围的横纵坐标存储在paw_x_listpaw_y_list中。

如果landmark_list不为空,即有手指的关键点被检测到ratio_x_to_pixelratio_y_to_pixel:两个lambda函数,用于将相对比例转换为像素坐标的函数。根据手掌范围的矩形坐标,计算手掌区域的左上角和右下角坐标,并画出方框。使用landmark_list中的信息获取中指指尖坐标和食指指尖坐标,并将它们转换为像素坐标。计算中指指尖坐标和食指指尖坐标的中间点。将中指指尖的坐标和食指指尖的坐标存储在thumb_finger_pointindex_finger_point中。

解析检测到的手掌信息,并提取手指的关键点坐标,将手指坐标转换为像素坐标,并将中指指尖和食指指尖的位置标记在图像上。

6.绘制指尖圆圈和连接线,计算距离

                            circle_func = lambda point: cv2.circle(self.image, point, 10, (255, 0, 255), -1)self.image = circle_func(thumb_finger_point)self.image = circle_func(index_finger_point)self.image = circle_func(between_finger_tip)# 画2点连线self.image = cv2.line(self.image, thumb_finger_point, index_finger_point, (255, 0, 255), 5)# 勾股定理计算长度line_len = math.hypot((index_finger_tip_x - middle_finger_tip_x),(index_finger_tip_y - middle_finger_tip_y))# 将指尖距离映射到文字rect_percent_text = math.ceil(line_len)
  • cv2.line函数,在图像上绘制中指指尖和食指指尖之间的连接线。

  • math.hypot函数计算直角三角形斜边的长度。

  • 将指尖之间的距离映射到rect_percent_text变量中,用作后续文本显示的参数。

7.跟踪手指之间的距离

                            if squareManager.drag_active:# 更新方块squareManager.updateSquare(between_finger_tip[0], between_finger_tip[1])if (line_len > 100):# 取消激活squareManager.drag_active = FalsesquareManager.active_index = -1elif (line_len < 100) and (squareManager.checkOverlay(between_finger_tip[0],between_finger_tip[1]) != -1) and (squareManager.drag_active == False):# 激活squareManager.drag_active = True# 计算距离squareManager.setLen(between_finger_tip[0], between_finger_tip[1])

如果squareManagerdrag_active属性为True,即矩形的移动模式已经激活,使用squareManager.updateSquare方法更新矩形的位置。如果两个手指之间的距离大于100,即手指之间的距离超过了阈值,取消矩形的激活模式,将drag_active设置为False,将active_index设置为-1。

否则,如果两个手指之间的距离小于100,且手指之间存在重叠的矩形,并且矩形的移动模式未激活。激活矩形的移动模式,将drag_active设置为True。根据手指之间的距离,计算并设置矩形的长度,使用squareManager.setLen方法。

8.显示图像

                squareManager.display(self)# 显示距离cv2.putText(self.image, "Distance:" + str(rect_percent_text), (10, 120), cv2.FONT_HERSHEY_PLAIN, 3,(255, 0, 0), 3)# 显示当前激活cv2.putText(self.image, "Active:" + ("None" if squareManager.active_index == -1 else str(squareManager.active_index)), (10, 170),cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 0), 3)# 显示刷新率FPScTime = time.time()fps_text = 1 / (cTime - fpsTime)fpsTime = cTimecv2.putText(self.image, "FPS: " + str(int(fps_text)), (10, 70),cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 0), 3)# 显示画面cv2.imshow('virtual drag and drop', self.image)if cv2.waitKey(5) & 0xFF == 27:breakcap.release()control = HandControlVolume()
control.recognize()

主函数(recognize)的结尾部分,用于显示图像、矩形的状态和刷新率,并等待按键响应。使用squareManager.display方法显示矩形。cv2.waitKey函数等待按键输入,如果按下的键是ESC键(对应的ASCII码为27),则退出循环。

在屏幕上显示处理后的图像、矩形的状态和刷新率,并等待按键响应。这样可以实现交互式的虚拟拖放功能。接下来我们看一下实际的操作效果。

四、实战演示

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

通过演示我们可以实现通过手部对方块进行拖拽,效果可以达到良好的状态。

五、源码分享

import cv2
import mediapipe as mp
import time
import math
class SquareManager:def __init__(self, rect_width):# 方框长度self.rect_width = rect_width# 方块listself.square_count = 0self.rect_left_x_list = []self.rect_left_y_list = []self.alpha_list = []# 中指与矩形左上角点的距离self.L1 = 0self.L2 = 0# 激活移动模式self.drag_active = False# 激活的方块IDself.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.imageclass_obj.image = cv2.addWeighted(overlay, alpha, class_obj.image, 1 - alpha, 0)# 判断落在哪个方块上,返回方块的IDdef 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)):# 保存被激活的方块IDself.active_index = ireturn ireturn -1# 计算与指尖的距离def setLen(self, check_x, check_y):# 计算距离self.L1 = check_x - self.rect_left_x_list[self.active_index]self.L2 = check_y - self.rect_left_y_list[self.active_index]# 更新方块    def updateSquare(self, new_x, new_y):# print(self.rect_left_x_list[self.active_index])self.rect_left_x_list[self.active_index] = new_x - self.L1self.rect_left_y_list[self.active_index] = new_y - self.L2# 识别控制类
class HandControlVolume:def __init__(self):# 初始化medialpipeself.mp_drawing = mp.solutions.drawing_utilsself.mp_drawing_styles = mp.solutions.drawing_stylesself.mp_hands = mp.solutions.hands# 中指与矩形左上角点的距离self.L1 = 0self.L2 = 0# image实例,以便另一个类调用self.image = None# 主函数def recognize(self):# 计算刷新率fpsTime = time.time()# OpenCV读取视频流cap = cv2.VideoCapture(0)# 视频分辨率resize_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))resize_h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))# 画面显示初始化参数rect_percent_text = 0# 初始化方块管理器squareManager = SquareManager(150)# 创建多个方块for i in range(0, 5):squareManager.create(200 * i + 20, 200, 0.6)with self.mp_hands.Hands(min_detection_confidence=0.7,min_tracking_confidence=0.5,max_num_hands=2) as hands:while cap.isOpened():# 初始化矩形success, self.image = cap.read()self.image = cv2.resize(self.image, (resize_w, resize_h))if not success:print("空帧.")continue# 提高性能self.image.flags.writeable = False# 转为RGBself.image = cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB)# 镜像self.image = cv2.flip(self.image, 1)# mediapipe模型处理results = hands.process(self.image)self.image.flags.writeable = Trueself.image = cv2.cvtColor(self.image, cv2.COLOR_RGB2BGR)# 判断是否有手掌if results.multi_hand_landmarks:# 遍历每个手掌for hand_landmarks in results.multi_hand_landmarks:# 在画面标注手指self.mp_drawing.draw_landmarks(self.image,hand_landmarks,self.mp_hands.HAND_CONNECTIONS,self.mp_drawing_styles.get_default_hand_landmarks_style(),self.mp_drawing_styles.get_default_hand_connections_style())# 解析手指,存入各个手指坐标landmark_list = []# 用来存储手掌范围的矩形坐标paw_x_list = []paw_y_list = []for landmark_id, finger_axis in enumerate(hand_landmarks.landmark):landmark_list.append([landmark_id, finger_axis.x, finger_axis.y,finger_axis.z])paw_x_list.append(finger_axis.x)paw_y_list.append(finger_axis.y)if landmark_list:# 比例缩放到像素ratio_x_to_pixel = lambda x: math.ceil(x * resize_w)ratio_y_to_pixel = lambda y: math.ceil(y * resize_h)# 设计手掌左上角、右下角坐标paw_left_top_x, paw_right_bottom_x = map(ratio_x_to_pixel,[min(paw_x_list), max(paw_x_list)])paw_left_top_y, paw_right_bottom_y = map(ratio_y_to_pixel,[min(paw_y_list), max(paw_y_list)])# 给手掌画框框cv2.rectangle(self.image, (paw_left_top_x - 30, paw_left_top_y - 30),(paw_right_bottom_x + 30, paw_right_bottom_y + 30), (0, 255, 0), 2)# 获取中指指尖坐标middle_finger_tip = landmark_list[12]middle_finger_tip_x = ratio_x_to_pixel(middle_finger_tip[1])middle_finger_tip_y = ratio_y_to_pixel(middle_finger_tip[2])# 获取食指指尖坐标index_finger_tip = landmark_list[8]index_finger_tip_x = ratio_x_to_pixel(index_finger_tip[1])index_finger_tip_y = ratio_y_to_pixel(index_finger_tip[2])# 中间点between_finger_tip = (middle_finger_tip_x + index_finger_tip_x) // 2, (middle_finger_tip_y + index_finger_tip_y) // 2# print(middle_finger_tip_x)thumb_finger_point = (middle_finger_tip_x, middle_finger_tip_y)index_finger_point = (index_finger_tip_x, index_finger_tip_y)# 画指尖2点circle_func = lambda point: cv2.circle(self.image, point, 10, (255, 0, 255), -1)self.image = circle_func(thumb_finger_point)self.image = circle_func(index_finger_point)self.image = circle_func(between_finger_tip)# 画2点连线self.image = cv2.line(self.image, thumb_finger_point, index_finger_point, (255, 0, 255), 5)# 勾股定理计算长度line_len = math.hypot((index_finger_tip_x - middle_finger_tip_x),(index_finger_tip_y - middle_finger_tip_y))# 将指尖距离映射到文字rect_percent_text = math.ceil(line_len)# 激活模式,需要让矩形跟随移动if squareManager.drag_active:# 更新方块squareManager.updateSquare(between_finger_tip[0], between_finger_tip[1])if (line_len > 100):# 取消激活squareManager.drag_active = FalsesquareManager.active_index = -1elif (line_len < 100) and (squareManager.checkOverlay(between_finger_tip[0],between_finger_tip[1]) != -1) and (squareManager.drag_active == False):# 激活squareManager.drag_active = True# 计算距离squareManager.setLen(between_finger_tip[0], between_finger_tip[1])# 显示方块,传入本实例,主要为了半透明的处理squareManager.display(self)# 显示距离cv2.putText(self.image, "Distance:" + str(rect_percent_text), (10, 120), cv2.FONT_HERSHEY_PLAIN, 3,(255, 0, 0), 3)# 显示当前激活cv2.putText(self.image, "Active:" + ("None" if squareManager.active_index == -1 else str(squareManager.active_index)), (10, 170),cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 0), 3)# 显示刷新率FPScTime = time.time()fps_text = 1 / (cTime - fpsTime)fpsTime = cTimecv2.putText(self.image, "FPS: " + str(int(fps_text)), (10, 70),cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 0), 3)# 显示画面cv2.imshow('virtual drag and drop', self.image)if cv2.waitKey(5) & 0xFF == 27:breakcap.release()control = HandControlVolume()
control.recognize()

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

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

相关文章

做决策、定战略、带团队:顶级高手常用的16个思维模型

01 做决策 1.沃伦巴菲特的双目标清单系统&#xff08;Two-List System&#xff09; 弗林特当了巴菲特的私人飞行员十年之久&#xff0c;还曾为美国四任总统开过飞机&#xff0c;但他在事业上依然有更多追求。有一次&#xff0c;他和巴菲特在探讨他的职业生涯目标时&#xff0…

容器化nacos部署并实现服务发现(gradle)

1.如何容器化部署mysql 2. 如何容器化部署nacos 为不暴露我的服务器地址&#xff0c;本文全部使用localhost来代替服务器地址&#xff0c;所有的localhost都应该调整为你自己的服务器地址。 为不暴露我的服务器地址&#xff0c;本文全部使用localhost来代替服务器地址&#x…

Libra R-CNN: Towards Balanced Learning for Object Detection(2019.4)

文章目录 AbstractIntroduction引入问题1&#xff09; Sample level imbalance2) Feature level imbalance3) Objective level imbalance进行解决贡献 Related Work&#xff08;他人的work&#xff0c;捎带与我们的对比&#xff09;Model architectures for object detection&a…

突发!奥特曼宣布暂停ChatGPT Plus新用户注册!

大新闻&#xff01;就在刚刚&#xff01; OpenAI的CEO Sam Altman宣布暂停ChatGPT Plus 新用户注册&#xff01; Sam Altman对此解释道&#xff1a; 由于OpenAI开发日后ChatGPT使用量的激增超出了我们的承受能力&#xff0c;我们希望确保每个人都有良好的体验。 您仍然可以在a…

msvcp120.dll下载_msvcp120.dll文件丢失解决[dll系统文件修复]

msvcp120.dll是Microsoft Visual C库中的一个重要组件&#xff0c;属于Microsoft Visual C 2005 Redistributable Package。它提供了许多用于执行C程序所需的函数。Visual C是一款流行的集成开发环境&#xff08;IDE&#xff09;&#xff0c;广泛应用于游戏、视频和图形处理等领…

keepalived+haproxy配置集群和负载均衡

1、简介 1.1. Keepalived Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以利用其来避免单点故障。一个LVS服务会有2台服务器运行Keepalived,一台为主服务器(MASTER),一台为备份服务器(BACKUP),但是对外表现为一个虚拟IP,主服务器会发送特定的消息给备…

【PyQt小知识 - 2】:QTextEdit内容的更新和获取、隐藏或显示滚动条、光标插入文本、文本自适应移动

文章目录 QTextEdit更新和获取内容隐藏或显示滚动条光标插入文本文本自适应移动 QTextEdit 更新和获取内容 更新&#xff1a;QTextEdit().setText(text) 或 QTextEdit().setPlainText(text) 获取&#xff1a;QTextEdit().toPlainText() setText()和setPlainText()的区别&…

大文件分片上传、断点续传、秒传

小文件上传 后端&#xff1a;SpringBootJDK17 前端&#xff1a;JavaScriptsparkmd5.min.js 一、依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.2</ve…

1 Supervised Machine Learning Regression and Classification

文章目录 Week1OverViewSupervised LearningUnsupervised LearningLinear Regression ModelCost functionGradient Descent Week2Muliple FeatureVectorizationGradient Descent for Multiple RegressionFeature ScalingGradient DescentFeature EngineeringPolynomial Regress…

UE5 - UI Material Lab 学习笔记

1、学习资料收集 UI Material Lab : https://www.unrealengine.com/marketplace/zh-CN/product/ui-material-lab 视频1&#xff1a;https://www.bilibili.com/video/BV1Hm4y1t7Kn/?spm_id_from333.337.search-card.all.click&vd_source707ec8983cc32e6e065d5496a7f79ee6 视…

记录一次 添加脚本的记录+改错记录

1.Update 和 Delete 一定要记得where条件 update 表名称 set 字段1‘修改的值’ &#xff08;单引号&#xff09; where 字段‘’ and Aid‘’; update jxkh22 set JXKH2200001 ,JXKH2201002 where B003 and JXKH22034;delete from table_name where condition delete from …

Linux控制---进程程序替换

前言&#xff1a;前面我们学洗了Linux进程退出的相关知识&#xff0c;了解了什么是进程退出&#xff0c;已经进程等待的相关话题&#xff0c;今天&#xff0c;我们来学习Linux中的进程程序替换&#xff0c;进程程序替换在Linux中可以用于实现新程序的启动、程序升级、多进程程序…

11.10 知识总结(数据的增删改查、如何创建表关系、Django框架的请求生命周期流程图)

一、 数据的增删改查 1.1 用户列表的展示 把数据表中得用户数据都给查询出来展示在页面上 添加数据 id username password gender age action 修改 删除 1.2 修…

【数据库开发】DataX开发环境的安装部署(Python、Java)

文章目录 1、简介1.1 DataX简介1.2 DataX功能1.3 支持的数据通道 2、DataX安装配置2.1 DataX2.2 Java2.3 Python 3、DataX Web安装配置3.1 mysql3.2 DataX Web3.2.1 简介3.2.2 架构图3.2.3 依赖环境3.2.4 安装 4、入门使用4.1 DataX自带打印示例测试4.2 DataX生成任务模板文件4…

kubernetes集群编排——istio

官网&#xff1a;https://istio.io/latest/zh/about/service-mesh/ 部署 [rootk8s2 ~]# tar zxf istio-1.19.3-linux-amd64.tar.gz [rootk8s2 ~]# cd istio-1.19.3/[rootk8s2 istio-1.19.3]# export PATH$PWD/bin:$PATH demo专为测试准备的功能集合 [rootk8s2 istio-1.19.3]# i…

Linux文件系统之inode

文章目录 1. 磁盘1.1 认识磁盘1.2 磁盘物理构造1.3 磁盘逻辑结构 2. 文件系统3. 如何理解目录 1. 磁盘 1.1 认识磁盘 文件 内容 属性&#xff0c;而文件是存储在磁盘上&#xff0c;那么可以理解为磁盘上存储的文件 存储的文件内容 存储的文件属性。 文件的内容采用的是块式…

kube-bench-CIS基准的自动化扫描工具学习

仓库地址&#xff1a;GitHub - aquasecurity/kube-bench: Checks whether Kubernetes is deployed according to security best practices as defined in the CIS Kubernetes Benchmark kube-bench,检查 Kubernetes 是否根据 CIS Kubernetes 基准中定义的安全最佳实践部署,下载…

应用协议安全:Rsync-common 未授权访问.

应用协议安全&#xff1a;Rsync-common 未授权访问. Rsync 是 Linux 下一款数据备份工具&#xff0c;支持通过 rsync 协议、ssh 协议进行远程文件传输。其中 rsync 协议默认监听 873 端口&#xff0c;如果目标开启了 rsync 服务&#xff0c;并且没有配置 ACL 或访问密码&#…

Redis05-集群方案

目录 Redis集群方案 主从复制 主从复制的基本原理 主从复制的工作流程 乐观复制 主从复制的优势 哨兵机制 哨兵的关键作用 服务状态监控 哨兵选举Master规则 分片集群 分片集群中的数据读写 数据写入 数据读取 一致性哈希和客户端分片 Redis集群方案 微服务时代…