当前位置: 首页 > news >正文

亚博microros小车-原生ubuntu支持系列:11手指控制与手势识别

识别框架还是沿用之前的了MediaPipe Hand。

背景知识不摘重复,参见之前的:亚博microros小车-原生ubuntu支持系列:10-画笔-CSDN博客

手指控制

src/yahboom_esp32_mediapipe/yahboom_esp32_mediapipe/目录下新建文件10_HandCtrl.py,代码如下:

#!/usr/bin/env python3
# encoding: utf-8
import math
import time
import cv2 as cv
import numpy as np
import mediapipe as mp
import rclpy
from rclpy.node import Node
from cv_bridge import CvBridge
from sensor_msgs.msg import Image, CompressedImagefrom rclpy.time import Time
import datetimevolPer = value = index = 0
effect = ["color", "thresh", "blur", "hue", "enhance"]
volBar = 400
class handDetector:def __init__(self, mode=False, maxHands=2, detectorCon=0.5, trackCon=0.5):self.tipIds = [4, 8, 12, 16, 20]self.mpHand = mp.solutions.handsself.mpDraw = mp.solutions.drawing_utilsself.hands = self.mpHand.Hands(#模型初始化static_image_mode=mode,max_num_hands=maxHands,min_detection_confidence=detectorCon,min_tracking_confidence=trackCon)self.lmDrawSpec = mp.solutions.drawing_utils.DrawingSpec(color=(0, 0, 255), thickness=-1, circle_radius=15)self.drawSpec = mp.solutions.drawing_utils.DrawingSpec(color=(0, 255, 0), thickness=10, circle_radius=10)#距离计算def get_dist(self, point1, point2):x1, y1 = point1x2, y2 = point2return abs(math.sqrt(math.pow(abs(y1 - y2), 2) + math.pow(abs(x1 - x2), 2)))#计算角度def calc_angle(self, pt1, pt2, pt3):point1 = self.lmList[pt1][1], self.lmList[pt1][2]point2 = self.lmList[pt2][1], self.lmList[pt2][2]point3 = self.lmList[pt3][1], self.lmList[pt3][2]a = self.get_dist(point1, point2)b = self.get_dist(point2, point3)c = self.get_dist(point1, point3)try:#余弦定理radian = math.acos((math.pow(a, 2) + math.pow(b, 2) - math.pow(c, 2)) / (2 * a * b))angle = radian / math.pi * 180#弧度转角度except:angle = 0return abs(angle)def findHands(self, frame, draw=True):img = np.zeros(frame.shape, np.uint8)img_RGB = cv.cvtColor(frame, cv.COLOR_BGR2RGB)#图像格式转换self.results = self.hands.process(img_RGB)#检测if self.results.multi_hand_landmarks:for handLms in self.results.multi_hand_landmarks:#输出关键点if draw: self.mpDraw.draw_landmarks(img, handLms, self.mpHand.HAND_CONNECTIONS)return imgdef findPosition(self, frame, draw=True):self.lmList = []if self.results.multi_hand_landmarks:for id, lm in enumerate(self.results.multi_hand_landmarks[0].landmark):# print(id,lm)h, w, c = frame.shapecx, cy = int(lm.x * w), int(lm.y * h)# print(id, lm.x, lm.y, lm.z)self.lmList.append([id, cx, cy])#记录指点序号与坐标if draw: cv.circle(frame, (cx, cy), 15, (0, 0, 255), cv.FILLED)return self.lmListdef frame_combine(slef,frame, src):if len(frame.shape) == 3:frameH, frameW = frame.shape[:2]srcH, srcW = src.shape[:2]dst = np.zeros((max(frameH, srcH), frameW + srcW, 3), np.uint8)dst[:, :frameW] = frame[:, :]dst[:, frameW:] = src[:, :]else:src = cv.cvtColor(src, cv.COLOR_BGR2GRAY)frameH, frameW = frame.shape[:2]imgH, imgW = src.shape[:2]dst = np.zeros((frameH, frameW + imgW), np.uint8)dst[:, :frameW] = frame[:, :]dst[:, frameW:] = src[:, :]return dstclass MY_Picture(Node):def __init__(self, name):super().__init__(name)self.bridge = CvBridge()self.sub_img = self.create_subscription(CompressedImage, '/espRos/esp32camera', self.handleTopic, 1) #获取esp32传来的图像self.hand_detector = handDetector()self.volPer = self.value = self.index = 0self.effect = ["color", "thresh", "blur", "hue", "enhance"]self.volBar = 400self.last_stamp = Noneself.new_seconds = 0self.fps_seconds = 1def handleTopic(self, msg):self.last_stamp = msg.header.stamp  if self.last_stamp:total_secs = Time(nanoseconds=self.last_stamp.nanosec, seconds=self.last_stamp.sec).nanosecondsdelta = datetime.timedelta(seconds=total_secs * 1e-9)seconds = delta.total_seconds()*100if self.new_seconds != 0:self.fps_seconds = seconds - self.new_secondsself.new_seconds = seconds#保留这次的值start = time.time()frame = self.bridge.compressed_imgmsg_to_cv2(msg)frame = cv.resize(frame, (640, 480))action = cv.waitKey(1) & 0xFFimg  = self.hand_detector.findHands(frame)lmList = self.hand_detector.findPosition(frame, draw=False)if len(lmList) != 0:angle = self.hand_detector.calc_angle(4, 0, 8)#计算拇指,0点,食指尖的角度x1, y1 = lmList[4][1], lmList[4][2]x2, y2 = lmList[8][1], lmList[8][2]cx, cy = (x1 + x2) // 2, (y1 + y2) // 2cv.circle(img, (x1, y1), 15, (255, 0, 255), cv.FILLED)cv.circle(img, (x2, y2), 15, (255, 0, 255), cv.FILLED)cv.line(img, (x1, y1), (x2, y2), (255, 0, 255), 3)cv.circle(img, (cx, cy), 15, (255, 0, 255), cv.FILLED)if angle <= 10: cv.circle(img, (cx, cy), 15, (0, 255, 0), cv.FILLED)self.volBar = np.interp(angle, [0, 70], [400, 150])self.volPer = np.interp(angle, [0, 70], [0, 100])self.value = np.interp(angle, [0, 70], [0, 255])# print("angle: {},self.value: {}".format(angle, self.value))print(f'mode:{self.effect[self.index]}')# 进行阈值二值化操作,大于阈值value的,使用255表示,小于阈值value的,使用0表示if self.effect[self.index]=="thresh":gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)frame = cv.threshold(gray, self.value, 255, cv.THRESH_BINARY)[1]# 进行高斯滤波,(21, 21)表示高斯矩阵的长与宽都是21,标准差取valueelif self.effect[self.index]=="blur":frame = cv.GaussianBlur(frame, (21, 21), np.interp(self.value, [0, 255], [0, 11]))# 色彩空间的转化,HSV转换为BGRelif self.effect[self.index]=="hue":frame = cv.cvtColor(frame, cv.COLOR_BGR2HSV)frame[:, :, 0] += int(self.value)frame = cv.cvtColor(frame, cv.COLOR_HSV2BGR)# 调节对比度elif self.effect[self.index]=="enhance":enh_val = self.value / 40clahe = cv.createCLAHE(clipLimit=enh_val, tileGridSize=(8, 8))lab = cv.cvtColor(frame, cv.COLOR_BGR2LAB)lab[:, :, 0] = clahe.apply(lab[:, :, 0])frame = cv.cvtColor(lab, cv.COLOR_LAB2BGR)if action == ord('f'):self.index += 1if self.index >= len(self.effect): self.index = 0end = time.time()fps = 1 / ((end - start)+self.fps_seconds)text = "FPS : " + str(int(fps))cv.putText(frame, text, (20, 30), cv.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 1)cv.rectangle(img, (50, 150), (85, 400), (255, 0, 0), 3)cv.rectangle(img, (50, int(self.volBar)), (85, 400), (0, 255, 0), cv.FILLED)cv.putText(img, f'{int(self.volPer)}%', (40, 450), cv.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 3)dst = self.hand_detector.frame_combine(frame, img)cv.imshow('dst', dst)def main():print("start it")rclpy.init()esp_img = MY_Picture("My_Picture")try:rclpy.spin(esp_img)except KeyboardInterrupt:passfinally:esp_img.destroy_node()rclpy.shutdown()

订阅esp32传出来的图像后,通过MediaPipe去做相关的识别后,再通过记录手指的点坐标,计算角4-0-8之间度数。本节与之前不同,增加了opencv输出的格式,"color", "thresh", "blur", "hue", "enhance"。默认是color,还有阈值化输出,高斯模糊等其他效果。按F键切换

构建后运行:

ros2 run yahboom_esp32_mediapipe HandCtrl

效果如下:

手势识别

src/yahboom_esp32_mediapipe/yahboom_esp32_mediapipe/目录下新建文件11_GestureRecognition.py,代码如下

#!/usr/bin/env python3
# encoding: utf-8
import math
import time
import cv2 as cv
import numpy as np
import mediapipe as mp
import rclpy
from rclpy.node import Node
from cv_bridge import CvBridge
from sensor_msgs.msg import Image, CompressedImagefrom rclpy.time import Time
import datetimeclass handDetector:def __init__(self, mode=False, maxHands=2, detectorCon=0.5, trackCon=0.5):self.tipIds = [4, 8, 12, 16, 20]self.mpHand = mp.solutions.handsself.mpDraw = mp.solutions.drawing_utilsself.hands = self.mpHand.Hands(static_image_mode=mode,max_num_hands=maxHands,min_detection_confidence=detectorCon,min_tracking_confidence=trackCon)self.lmList = []self.lmDrawSpec = mp.solutions.drawing_utils.DrawingSpec(color=(0, 0, 255), thickness=-1, circle_radius=6)self.drawSpec = mp.solutions.drawing_utils.DrawingSpec(color=(0, 255, 0), thickness=2, circle_radius=2)def get_dist(self, point1, point2):x1, y1 = point1x2, y2 = point2return abs(math.sqrt(math.pow(abs(y1 - y2), 2) + math.pow(abs(x1 - x2), 2)))def calc_angle(self, pt1, pt2, pt3):point1 = self.lmList[pt1][1], self.lmList[pt1][2]point2 = self.lmList[pt2][1], self.lmList[pt2][2]point3 = self.lmList[pt3][1], self.lmList[pt3][2]a = self.get_dist(point1, point2)b = self.get_dist(point2, point3)c = self.get_dist(point1, point3)try:radian = math.acos((math.pow(a, 2) + math.pow(b, 2) - math.pow(c, 2)) / (2 * a * b))angle = radian / math.pi * 180except:angle = 0return abs(angle)def findHands(self, frame, draw=True):self.lmList = []img = np.zeros(frame.shape, np.uint8)img_RGB = cv.cvtColor(frame, cv.COLOR_BGR2RGB)self.results = self.hands.process(img_RGB)if self.results.multi_hand_landmarks:for i in range(len(self.results.multi_hand_landmarks)):if draw: self.mpDraw.draw_landmarks(frame, self.results.multi_hand_landmarks[i], self.mpHand.HAND_CONNECTIONS, self.lmDrawSpec, self.drawSpec)self.mpDraw.draw_landmarks(img, self.results.multi_hand_landmarks[i], self.mpHand.HAND_CONNECTIONS, self.lmDrawSpec, self.drawSpec)for id, lm in enumerate(self.results.multi_hand_landmarks[i].landmark):h, w, c = frame.shapecx, cy = int(lm.x * w), int(lm.y * h)self.lmList.append([id, cx, cy])return frame, imgdef frame_combine(slef,frame, src):if len(frame.shape) == 3:frameH, frameW = frame.shape[:2]srcH, srcW = src.shape[:2]dst = np.zeros((max(frameH, srcH), frameW + srcW, 3), np.uint8)dst[:, :frameW] = frame[:, :]dst[:, frameW:] = src[:, :]else:src = cv.cvtColor(src, cv.COLOR_BGR2GRAY)frameH, frameW = frame.shape[:2]imgH, imgW = src.shape[:2]dst = np.zeros((frameH, frameW + imgW), np.uint8)dst[:, :frameW] = frame[:, :]dst[:, frameW:] = src[:, :]return dstdef fingersUp(self):fingers=[]# Thumbif (self.calc_angle(self.tipIds[0],self.tipIds[0] - 1,self.tipIds[0] - 2) > 150.0) and (self.calc_angle(self.tipIds[0] - 1,self.tipIds[0] - 2,self.tipIds[0] - 3) > 150.0): fingers.append(1)else:fingers.append(0)# 4 fingerfor id in range(1, 5):if self.lmList[self.tipIds[id]][2] < self.lmList[self.tipIds[id] - 2][2]:fingers.append(1)else:fingers.append(0)return fingersdef get_gesture(self):gesture = ""fingers = self.fingersUp()if self.lmList[self.tipIds[0]][2] > self.lmList[self.tipIds[1]][2] and \self.lmList[self.tipIds[0]][2] > self.lmList[self.tipIds[2]][2] and \self.lmList[self.tipIds[0]][2] > self.lmList[self.tipIds[3]][2] and \self.lmList[self.tipIds[0]][2] > self.lmList[self.tipIds[4]][2] : gesture = "Thumb_down"elif self.lmList[self.tipIds[0]][2] < self.lmList[self.tipIds[1]][2] and \self.lmList[self.tipIds[0]][2] < self.lmList[self.tipIds[2]][2] and \self.lmList[self.tipIds[0]][2] < self.lmList[self.tipIds[3]][2] and \self.lmList[self.tipIds[0]][2] < self.lmList[self.tipIds[4]][2] and \self.calc_angle(self.tipIds[1] - 1, self.tipIds[1] - 2, self.tipIds[1] - 3) < 150.0 : gesture = "Thumb_up"if fingers.count(1) == 3 or fingers.count(1) == 4:if fingers[0] == 1 and (self.get_dist(self.lmList[4][1:], self.lmList[8][1:])<self.get_dist(self.lmList[4][1:], self.lmList[5][1:])): gesture = "OK"elif fingers[2] == fingers[3] == 0: gesture = "Rock"elif fingers.count(1) == 3: gesture = "Three"else: gesture = "Four"elif fingers.count(1) == 0: gesture = "Zero"elif fingers.count(1) == 1: gesture = "One"elif fingers.count(1) == 2:if fingers[0] == 1 and fingers[4] == 1: gesture = "Six"elif fingers[0] == 1 and self.calc_angle(4, 5, 8) > 90: gesture = "Eight"elif fingers[0] == fingers[1] == 1 and self.get_dist(self.lmList[4][1:], self.lmList[8][1:]) < 50: gesture = "Heart_single"else: gesture = "Two"elif fingers.count(1)==5:gesture = "Five"if self.get_dist(self.lmList[4][1:], self.lmList[8][1:]) < 60 and \self.get_dist(self.lmList[4][1:], self.lmList[12][1:]) < 60 and \self.get_dist(self.lmList[4][1:], self.lmList[16][1:]) < 60 and \self.get_dist(self.lmList[4][1:], self.lmList[20][1:]) < 60 : gesture = "Seven"if self.lmList[self.tipIds[0]][2] < self.lmList[self.tipIds[1]][2] and \self.lmList[self.tipIds[0]][2] < self.lmList[self.tipIds[2]][2] and \self.lmList[self.tipIds[0]][2] < self.lmList[self.tipIds[3]][2] and \self.lmList[self.tipIds[0]][2] < self.lmList[self.tipIds[4]][2] and \self.calc_angle(self.tipIds[1] - 1, self.tipIds[1] - 2, self.tipIds[1] - 3) > 150.0 : gesture = "Eight"return gestureclass MY_Picture(Node):def __init__(self, name):super().__init__(name)self.bridge = CvBridge()self.sub_img = self.create_subscription(CompressedImage, '/espRos/esp32camera', self.handleTopic, 1) #获取esp32传来的图像self.hand_detector = handDetector(detectorCon=0.75)self.last_stamp = Noneself.new_seconds = 0self.fps_seconds = 1def handleTopic(self, msg):self.last_stamp = msg.header.stamp  if self.last_stamp:total_secs = Time(nanoseconds=self.last_stamp.nanosec, seconds=self.last_stamp.sec).nanosecondsdelta = datetime.timedelta(seconds=total_secs * 1e-9)seconds = delta.total_seconds()*100if self.new_seconds != 0:self.fps_seconds = seconds - self.new_secondsself.new_seconds = seconds#保留这次的值start = time.time()frame = self.bridge.compressed_imgmsg_to_cv2(msg)frame = cv.resize(frame, (640, 480))cv.waitKey(1) frame, img = self.hand_detector.findHands(frame, draw=False)if len(self.hand_detector.lmList) != 0:totalFingers = self.hand_detector.get_gesture()cv.rectangle(frame, (0, 430), (230, 480), (0, 255, 0), cv.FILLED)cv.putText(frame, str(totalFingers), (10, 470), cv.FONT_HERSHEY_PLAIN, 2, (255, 0, 0), 2)end = time.time()fps = 1 / ((end - start)+self.fps_seconds)text = "FPS : " + str(int(fps))cv.putText(frame, text, (20, 30), cv.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 1)dist = self.hand_detector.frame_combine(frame, img)cv.imshow('dist', dist)'''
Zero One Two Three Four Five Six Seven Eight
Ok: OK
Rock: rock
Thumb_up : 点赞
Thumb_down: 拇指向下
Heart_single: 单手比心
'''def main():print("start it")rclpy.init()esp_img = MY_Picture("My_Picture")try:rclpy.spin(esp_img)except KeyboardInterrupt:passfinally:esp_img.destroy_node()rclpy.shutdown()

网上有不少这个例子,差异点可能在手势识别哪里,前面的hand模型都是一样的。

根据你预计的指点判断角度或者漏出的手指组合判断含义。有的也不太准确,大部分能识别。

构建后运行:ros2 run yahboom_esp32_mediapipe GestureRecognition

相关文章:

亚博microros小车-原生ubuntu支持系列:11手指控制与手势识别

识别框架还是沿用之前的了MediaPipe Hand。 背景知识不摘重复&#xff0c;参见之前的&#xff1a;亚博microros小车-原生ubuntu支持系列&#xff1a;10-画笔-CSDN博客 手指控制 src/yahboom_esp32_mediapipe/yahboom_esp32_mediapipe/目录下新建文件10_HandCtrl.py&#xff…...

JAVA-快速排序

目录 一、快速排序基本思想 二、快速排序的实现 1.Hoare法找基准值 2.挖坑法 3.前后指针法(了解) 三、快速排序的优化 1.三数取中法 2.递归到小的子区间时&#xff0c;可以考虑使用插入排序 四、非递归的写法 五、时间空间复杂度 一、快速排序基本思想 快速排序是 H…...

日志收集Day003

1.索引模板 查看所有索引模板 GET 10.0.0.101:9200/_template 2.查看单个索引模板 GET 10.0.0.101:9200/_template/.monitoring-es 3.创建索引模板 POST 10.0.0.101:9200/_template/lxctp {"aliases": {"DBA": {},"SRE": {},"K8S&qu…...

基于quartz,刷新定时器的cron表达式

文章目录 前言基于quartz&#xff0c;刷新定时器的cron表达式1. 先看一下测试效果2. 实现代码 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&…...

数学大模型MAmmoTH:通过混合说明调整建立数学通才模型

向悦和陈文虎是该项目的主要作者。他们这个项目推出 MAmmoTH&#xff0c;这是一系列专为解决一般数学问题而定制的开源大型语言模型 (LLM)。 MAmmoTH 模型在 MathInstruct 上进行训练&#xff0c;MathInstruct 是我们精心策划的指令调整数据集。 MathInstruct 已编译 来自 13 个…...

Opencv学习

Long time no see!哈哈&#xff0c;假期终于有时间做一点自己喜欢的东西了 还是想说&#xff0c;每天花一点时间投在自己喜欢的事情上&#xff0c;或者专攻一些平时不学的方向&#xff0c;真的很酷&#xff01; 图片绘制 对于图像绘制&#xff0c;可以分为&#xff1a;图像创…...

python生成图片和pdf,快速

1、下载安装 pip install imgkit pip install pdfkit2、wkhtmltopdf工具包&#xff0c;下载安装 下载地址&#xff1a;https://wkhtmltopdf.org/downloads.html 3、生成图片 import imgkit path_wkimg rD:\app\wkhtmltopdf\bin\wkhtmltoimage.exe # 工具路径&#xff0c;安…...

剑指Offer|LCR 044.在每个树行中找最大值

LCR 044.在每个树行中找最大值 给定一棵二叉树的根节点 root &#xff0c;请找出该二叉树中每一层的最大值。 示例 1&#xff1a; 输入: root [1,3,2,5,3,null,9] 输出: [1,3,9] 解释:1/ \3 2/ \ \ 5 3 9 示例 2&#xff1a; 输入: root [1,2,3] 输出: [1,3] 解…...

PWM信号概述

什么是PWM信号&#xff1f; PWM&#xff08;Pulse-width modulation&#xff09;是脉冲宽度调制的缩写。 脉冲宽度调制是一种模拟信号电平数字编码方法。 脉冲宽度调制PWM是通过将有效的电信号分散成离散形式从而来降低电信号所传递的平均功率的一种方式。所以根据面积等效法…...

关于BAR(PCIE BAR或AXI BAR)的解释

假设某BAR的默认值是xxxx_0000&#xff08;这里表示8个比特位&#xff09;&#xff0c;其中低4位不可写&#xff0c;可操作的最低位是4&#xff0c;所以该BAR的大小是2^416字节&#xff1b; 1、系统软件向BAR写0xFF 2、系统软件读BAR&#xff0c;读到的值是0xF0&#xff0c;于是…...

计算机的错误计算(二百二十一)

摘要 利用一个数学解题器化简计算 实验表明&#xff0c;即使是数学解题器&#xff0c;也是一派胡言。 有一读者来信&#xff0c;询问数学大模型的推理事宜。现就前面的案例继续做一讨论。 例1. 化简计算摘要中算式。 下面是与一个数学解题器的对话。 点评&#xff1a; &am…...

【力扣Hot 100】矩阵1

矩阵置零&#xff1a;1. 开两个数组判断该行/该列是否有0&#xff1b;2. 用第0行/第0列分别判断该列/该行是否有0 螺旋矩阵&#xff1a;记录方向&#xff0c;一直按某方向前进&#xff0c;遇到障碍方向就变一下 1. 矩阵置零 给定一个 *m* x *n* 的矩阵&#xff0c;如果一个元…...

移动端VR处理器和传统显卡的不同

骁龙 XR 系列芯片 更多地依赖 AI 技术 来优化渲染过程&#xff0c;而传统的 GPU 渲染 则倾向于在低画质下运行以减少负载。这种设计是为了在有限的硬件资源下&#xff08;如移动端 XR 设备&#xff09;实现高性能和低功耗的平衡。以下是具体的分析&#xff1a; 1. AI 驱动的渲染…...

「 机器人 」利用数据驱动模型替代仿真器:加速策略训练并降低硬件依赖

前言 在强化学习(Reinforcement Learning, RL)中,策略训练需要大量的交互数据(状态、动作、奖励、下一状态),而这些数据通常来自仿真器或真实硬件。传统高保真仿真器虽然能在一定程度上模拟飞行器的动力学,但往往计算量大、开发成本高,且仍可能与真实环境存在差距。为此…...

MATLAB 如何避免复杂shp文件对inpolygon的影响

**任务描述&#xff1a;**当我想用inpolygon函数将属于非洲的pixel选出来时&#xff0c;发现因为周边小岛的影响&#xff0c;pixel选取有问题&#xff0c;如下图。 第一种解决办法&#xff1a; 首先将复杂shp文件查分成简单的shp文件&#xff0c;即将不相交的元素分离开 [QGIS…...

【2024年华为OD机试】 (C卷,200分)- 贪吃的猴子(JavaScriptJava PythonC/C++)

一、问题描述 题目解析 问题描述 一只猴子来到果园&#xff0c;发现许多串香蕉排成一行&#xff0c;每串香蕉上有若干根香蕉。每串香蕉的根数由数组 numbers 给出。猴子每次只能从行的开头或末尾获取香蕉&#xff0c;并且只能获取 N 次。求猴子最多能获取多少根香蕉。 输入…...

PostgreSQL中级专家是什么意思?

数据库技术领域&#xff0c;PostgreSQL 作为一种广泛使用的开源关系型数据库管理系统&#xff0c;吸引了众多技术人员深入学习和研究。“PostgreSQL 中级专家” 是对掌握该数据库特定技能层次的一种描述。 知识储备 中级专家深入理解 PostgreSQL 的体系结构&#xff0c;包括进程…...

从根源分析,调试,定位和解决MacOS ld: unsupported tapi file type ‘!tapi-tbd‘ in YAML file

你要是遇到同样错误&#xff0c;找一圈都没有解决&#xff0c;建议认真读一下本文&#xff0c;这个应该是最终极的解决办法&#xff0c;从原理上剖析了产生的原因&#xff0c;同时给出来了调试和定位的办法。 maccos使用brew安装了一个gcc14, 结果编译一个最简单的程序都报错&a…...

【Uniapp-Vue3】previewImage图片预览

如果我们想要实现点击一张图片放大&#xff0c;并能够左右滑动&#xff0c;就要使用previewImage这个API。 uni.previewImage({ current:xxx, // 当前图片下标 urls:xxx, // 图片路径组 // 其他参数 }) 我们先编写一个点击图片的事件&#xff0c;并传递当前点击图片的下标&…...

doris:Insert Into Values

INSERT INTO VALUES 语句支持将 SQL 中的值导入到 Doris 的表中。INSERT INTO VALUES 是一个同步导入方式&#xff0c;执行导入后返回导入结果。可以通过请求的返回判断导入是否成功。INSERT INTO VALUES 可以保证导入任务的原子性&#xff0c;要么全部导入成功&#xff0c;要么…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...