Python开源工具库使用之运动姿势追踪库mediapipe

文章目录

  • 前言
  • 一、姿势估计
    • 1.1 姿态关键点
    • 1.2 旧版 solution API
    • 1.3 新版 solution API
    • 1.4 俯卧撑计数
  • 二、手部追踪
    • 2.1 手部姿态
    • 2.2 API 使用
    • 2.3 识别手势含义
  • 参考

前言

Mediapipe 是谷歌出品的一种开源框架,旨在为开发者提供一种简单而强大的工具,用于实现各种视觉和感知应用程序。它包括一系列预训练的机器学习模型和用于处理多媒体数据的工具,可以用于姿势估计、手部追踪、人脸检测与跟踪、面部标志、对象检测、图片分割和语言检测等任务

Mediapipe 是支持跨平台的,可以部署在手机端(Android, iOS), web, desktop, edge devices, IoT 等各种平台,编程语言也支持C++, Python, Java, Swift, Objective-C, Javascript等

在本文中,我们将通过Python实现 Mediapipe 在姿势估计和手部追踪不同领域的应用

  • github 地址:https://github.com/google/mediapipe

一、姿势估计

1.1 姿态关键点

在这里插入图片描述

序号部位Pose Landmark
0鼻子PoseLandmark.NOSE
1左眼(内侧)PoseLandmark.LEFT_EYE_INNER
2左眼PoseLandmark.LEFT_EYE
3左眼(外侧)PoseLandmark.LEFT_EYE_OUTER
4右眼(内侧)PoseLandmark.RIGHT_EYE_INNER
5右眼PoseLandmark.RIGHT_EYE
6右眼(外侧)PoseLandmark.RIGHT_EYE_OUTER
7左耳PoseLandmark.LEFT_EAR
8右耳PoseLandmark.RIGHT_EAR
9嘴巴(左侧)PoseLandmark.MOUTH_LEFT
10嘴巴(右侧)PoseLandmark.MOUTH_RIGHT
11左肩PoseLandmark.LEFT_SHOULDER
12右肩PoseLandmark.RIGHT_SHOULDER
13左肘PoseLandmark.LEFT_ELBOW
14右肘PoseLandmark.RIGHT_ELBOW
15左腕PoseLandmark.LEFT_WRIST
16右腕PoseLandmark.RIGHT_WRIST
17左小指PoseLandmark.LEFT_PINKY
18右小指PoseLandmark.RIGHT_PINKY
19左食指PoseLandmark.LEFT_INDEX
20右食指PoseLandmark.RIGHT_INDEX
21左拇指PoseLandmark.LEFT_THUMB
22右拇指PoseLandmark.RIGHT_THUMB
23左臀PoseLandmark.LEFT_HIP
24右臀PoseLandmark.RIGHT_HIP
25左膝PoseLandmark.LEFT_KNEE
26右膝PoseLandmark.RIGHT_KNEE
27左踝PoseLandmark.LEFT_ANKLE
28右踝PoseLandmark.RIGHT_ANKLE
29左脚跟PoseLandmark.LEFT_HEEL
30右脚跟PoseLandmark.RIGHT_HEEL
31左脚趾PoseLandmark.LEFT_FOOT_INDEX
32右脚趾PoseLandmark.RIGHT_FOOT_INDEX

1.2 旧版 solution API

Mediapipe 提供 solution API 来实现快速检测, 不过这种方式在2023年5月10日停止更新了,不过目前还可以使用,可通过 mediapose.solutions.pose.Pose 来实现,配置参数如下

选项含义值范围默认值
static_image_mode如果设置为 False,会将输入图像视为视频流。它将尝试检测第一张图像中最突出的人,并在成功检测后进一步定位姿势。在随后的图像中,它只是跟踪这些标记,而不调用另一个检测,直到它失去跟踪,从而减少计算和延迟。如果设置为 True,则人员检测将运行每个输入图像,非常适合处理一批静态(可能不相关的)图像BooleanFalse
model_complexity模型的复杂度,准确性和推理延迟通常随着模型复杂性的增加而增加{0,1,2}1
smooth_landmarks如果设置为 True,则solution 过滤器会在不同的输入图像中设置标记以减少抖动,但如果 static_image_mode 也设置为 True,则忽略该筛选器BooleanTrue
enable_segmentation如果设置为 True,则除了姿态标记外,还会生成分割蒙版BooleanFalse
smooth_segmentation如果设置为 True,则会过滤不同输入图像中的分割掩码,以减少抖动。如果enable_segmentation为 false 或 static_image_mode为 True,则忽略BooleanTrue
min_detection_confidence人员检测模型的最小置信度值 ,用于将检测视为成功Float [0.0,1.0]0.5
min_tracking_confidence来自姿态跟踪模型的最小置信度值 , 用于将姿态标记视为成功跟踪,否则将在下一个输入图像上自动调用人员检测。将其设置为更高的值可以提高解决方案的可靠性,但代价是延迟更高。如果static_image_mode为 True,则忽略,其中人员检测仅对每个图像运行。Float [0.0,1.0]0.5
import cv2
import numpy as np
import mediapipe as mpdef main():FILE_PATH = 'data/1.png'img = cv2.imread(FILE_PATH)mp_pose = mp.solutions.posepose = mp_pose.Pose(static_image_mode=True,min_detection_confidence=0.5, min_tracking_confidence=0.5)res = pose.process(img)img_copy = img.copy()if res.pose_landmarks is not None:mp_drawing = mp.solutions.drawing_utils# mp_drawing.draw_landmarks(#     img_copy, res.pose_landmarks, mp.solutions.pose.POSE_CONNECTIONS)mp_drawing.draw_landmarks(img_copy,res.pose_landmarks,mp_pose.POSE_CONNECTIONS,  # frozenset,定义了哪些关键点要连接mp_drawing.DrawingSpec(color=(255, 255, 255),  # 姿态关键点thickness=2,circle_radius=2),mp_drawing.DrawingSpec(color=(174, 139, 45),   # 连线颜色thickness=2,circle_radius=2),)cv2.imshow('MediaPipe Pose Estimation', img_copy)cv2.waitKey(0)if __name__ == '__main__':main()

mediapipe_001

import cv2
import numpy as np
import mediapipe as mpdef video():# 读取摄像头# cap = cv2.VideoCapture(0)# 读取视频cap = cv2.VideoCapture('data/1.mp4')mp_pose = mp.solutions.posepose = mp_pose.Pose(static_image_mode=False,min_detection_confidence=0.5, min_tracking_confidence=0.5)while cap.isOpened():ret, frame = cap.read()if not ret:break# 摄像头# continue# 将 BGR 图像转换为 RGBrgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 进行姿势估计results = pose.process(rgb_frame)if results.pose_landmarks is not None:# 绘制关键点和连接线mp_drawing = mp.solutions.drawing_utilsmp_drawing.draw_landmarks(frame, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)# 显示结果cv2.imshow('MediaPipe Pose Estimation', frame)if cv2.waitKey(1) & 0xFF == ord('q'):break# 释放资源cap.release()cv2.destroyAllWindows()if __name__ == '__main__':video()

mediapipe_002.gif

1.3 新版 solution API

旧版 API 并不能检测多个姿态,新版 API 可以实现多个姿态检测

选项含义值范围默认值
running_mode设置任务的运行模式,有三种模式可选:
IMAGE: 单一照片输入.
VIDEO: 视频.
LIVE_STREAM: 输入数据(例如来自摄像机)为实时流。在此模式下,必须调用 resultListener 来设置侦听器以异步接收结果.
{IMAGE, VIDEO, LIVE_STREAM}IMAGE
num_poses姿势检测器可以检测到的最大姿势数Integer > 01
min_pose_detection_confidence姿势检测被认为是成功的最小置信度得分Float [0.0,1.0]0.5
min_pose_presence_confidence姿态检测中的姿态存在分数的最小置信度分数Float [0.0,1.0]0.5
min_tracking_confidence姿势跟踪被视为成功的最小置信度分数Float [0.0,1.0]0.5
output_segmentation_masks是否为检测到的姿势输出分割掩码BooleanFalse
result_callback将结果侦听器设置为在Pose Landmark处于LIVE_STREAM模式时异步接收Landmark结果。仅当运行模式设置为LIVE_STREAM时才能使用ResultListenerN/A
from mediapipe import solutions
from mediapipe.framework.formats import landmark_pb2
import cv2
import numpy as np
import mediapipe as mpmp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.posedef draw_landmarks_on_image(rgb_image, detection_result):pose_landmarks_list = detection_result.pose_landmarksannotated_image = np.copy(rgb_image)# Loop through the detected poses to visualize.for idx in range(len(pose_landmarks_list)):pose_landmarks = pose_landmarks_list[idx]# Draw the pose landmarks.pose_landmarks_proto = landmark_pb2.NormalizedLandmarkList()pose_landmarks_proto.landmark.extend([landmark_pb2.NormalizedLandmark(x=landmark.x, y=landmark.y, z=landmark.z) for landmark in pose_landmarks])solutions.drawing_utils.draw_landmarks(annotated_image,pose_landmarks_proto,solutions.pose.POSE_CONNECTIONS,solutions.drawing_styles.get_default_pose_landmarks_style())return annotated_imagedef newSolution():BaseOptions = mp.tasks.BaseOptionsPoseLandmarker = mp.tasks.vision.PoseLandmarkerPoseLandmarkerOptions = mp.tasks.vision.PoseLandmarkerOptionsVisionRunningMode = mp.tasks.vision.RunningModemodel_path = 'data/pose_landmarker_heavy.task'options = PoseLandmarkerOptions(base_options=BaseOptions(model_asset_path=model_path),running_mode=VisionRunningMode.IMAGE,num_poses=10)FILE_PATH = 'data/4.jpg'image = cv2.imread(FILE_PATH)img = mp.Image.create_from_file(FILE_PATH)with PoseLandmarker.create_from_options(options) as detector:res = detector.detect(img)image = draw_landmarks_on_image(image, res)cv2.imshow('MediaPipe Pose Estimation', image)cv2.waitKey(0)if __name__ == '__main__':newSolution()

mediapipe_003

1.4 俯卧撑计数

通过计算胳膊弯曲角度来判断状态,并计算俯卧撑个数

import cv2
import mediapipe as mp
import numpy as npmp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.posedef calculate_angle(a, b, c):radians = np.arctan2(c.y - b.y, c.x - b.x) - \np.arctan2(a.y - b.y, a.x - b.x)angle = np.abs(np.degrees(radians))return angle if angle <= 180 else 360 - angledef angle_of_arm(landmarks, shoulder, elbow, wrist):shoulder_coord = landmarks[mp_pose.PoseLandmark[shoulder].value]elbow_coord = landmarks[mp_pose.PoseLandmark[elbow].value]wrist_coord = landmarks[mp_pose.PoseLandmark[wrist].value]return calculate_angle(shoulder_coord, elbow_coord, wrist_coord)def count_push_up(landmarks, counter, status):left_arm_angle = angle_of_arm(landmarks, "LEFT_SHOULDER", "LEFT_ELBOW", "LEFT_WRIST")right_arm_angle = angle_of_arm(landmarks, "RIGHT_SHOULDER", "RIGHT_ELBOW", "RIGHT_WRIST")avg_arm_angle = (left_arm_angle + right_arm_angle) // 2if status:if avg_arm_angle < 70:counter += 1status = Falseelse:if avg_arm_angle > 160:status = Truereturn counter, statusdef main():cap = cv2.VideoCapture('data/test.mp4')counter = 0status = Falsewith mp_pose.Pose(min_detection_confidence=0.7, min_tracking_confidence=0.7) as pose:while cap.isOpened():success, image = cap.read()if not success:print("empty camera")breakresult = pose.process(image)if result.pose_landmarks:mp_drawing.draw_landmarks(image, result.pose_landmarks, mp_pose.POSE_CONNECTIONS)counter, status = count_push_up(result.pose_landmarks.landmark, counter, status)cv2.putText(image, text=str(counter), org=(100, 100), fontFace=cv2.FONT_HERSHEY_SIMPLEX,fontScale=4, color=(255, 255, 255), thickness=2, lineType=cv2.LINE_AA)cv2.imshow("push-up counter", image)key = cv2.waitKey(1)if key == ord('q'):breakcap.release()if __name__ == '__main__':main()

mediapipe_004

二、手部追踪

2.1 手部姿态

hand-landmarks

2.2 API 使用

照片

选项含义值范围默认值
static_image_mode如果设置为 False,会将输入图像视为视频流。它将尝试在第一个输入图像中检测手,并在成功检测后进一步定位手部标志。在随后的图像中,一旦检测到所有 max_num_hands 手并定位了相应的手部标志,它就会简单地跟踪这些标志,而不会调用其他检测,直到它失去对任何手的跟踪。这减少了延迟,是处理视频帧的理想选择。如果设置为 True,则对每个输入图像运行手动检测,非常适合处理一批静态(可能不相关的)图像BooleanFalse
max_num_hands要检测的最大手数Integer2
model_complexity模型的复杂度,准确性和推理延迟通常随着模型复杂性的增加而增加{0,1}1
min_detection_confidence检测模型的最小置信度值 ,用于将检测视为成功Float [0.0,1.0]0.5
min_tracking_confidence来自手部跟踪模型的最小置信度值 , 用于将手部标记视为成功跟踪,否则将在下一个输入图像上自动调用检测。将其设置为更高的值可以提高解决方案的可靠性,但代价是延迟更高。如果static_image_mode为 True,则忽略,其中手部检测仅对每个图像运行。Float [0.0,1.0]0.5
import cv2
import mediapipe as mpmp_hands = mp.solutions.handsdef main():cv2.namedWindow("MediaPipe Hand", cv2.WINDOW_NORMAL)hands = mp_hands.Hands(static_image_mode=False, max_num_hands=2,min_detection_confidence=0.5, min_tracking_confidence=0.5)img = cv2.imread('data/finger/1.jpg')rgb_frame = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 进行手部追踪results = hands.process(rgb_frame)if results.multi_hand_landmarks:# 绘制手部关键点和连接线for hand_landmarks in results.multi_hand_landmarks:mp_drawing = mp.solutions.drawing_utilsmp_drawing.draw_landmarks(img, hand_landmarks, mp_hands.HAND_CONNECTIONS)# 显示结果cv2.imshow('MediaPipe Hand', img)cv2.waitKey(0)if __name__ == '__main__':main()

mediapipe_005_hand_image

import cv2
import mediapipe as mpmp_hands = mp.solutions.handsdef video():hands = mp_hands.Hands(static_image_mode=False, max_num_hands=2,min_detection_confidence=0.4, min_tracking_confidence=0.4)# 读取视频cap = cv2.VideoCapture('data/hand.mp4')while cap.isOpened():ret, frame = cap.read()if not ret:break# 将 BGR 图像转换为 RGBrgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 进行手部追踪results = hands.process(rgb_frame)if results.multi_hand_landmarks:# 绘制手部关键点和连接线for hand_landmarks in results.multi_hand_landmarks:mp_drawing = mp.solutions.drawing_utilsmp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)# 显示结果cv2.imshow('MediaPipe Hand Tracking', frame)if cv2.waitKey(1) & 0xFF == ord('q'):break# 释放资源cap.release()cv2.destroyAllWindows()if __name__ == '__main__':video()

mediapipe_006.gif

2.3 识别手势含义

使用 KNN 对手势进行预测

import mediapipe as mp
import numpy as np
import cv2
from mediapipe.framework.formats.landmark_pb2 import NormalizedLandmarkList
from sklearn.neighbors import KNeighborsClassifiermp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.hands# 压缩特征点
class Embedder(object):def __init__(self):self._landmark_names = mp.solutions.hands.HandLandmarkdef __call__(self, landmarks):# modify the call func can both handle a 3-dim dataset and a single referencing result.if isinstance(landmarks, np.ndarray):if landmarks.ndim == 3:  # for datasetembeddings = []for lmks in landmarks:embedding = self.__call__(lmks)embeddings.append(embedding)return np.array(embeddings)elif landmarks.ndim == 2:  # for inferenceassert landmarks.shape[0] == len(list(self._landmark_names)), 'Unexpected number of landmarks: {}'.format(landmarks.shape[0])# Normalize landmarks.landmarks = self._normalize_landmarks(landmarks)# Get embedding.embedding = self._get_embedding(landmarks)return embeddingelse:print('ERROR: Can NOT embedding the data you provided !')else:if isinstance(landmarks, list):  # for datasetembeddings = []for lmks in landmarks:embedding = self.__call__(lmks)embeddings.append(embedding)return np.array(embeddings)elif isinstance(landmarks, NormalizedLandmarkList):  # for inference# Normalize landmarks.landmarks = np.array([[lmk.x, lmk.y, lmk.z]for lmk in landmarks.landmark], dtype=np.float32)assert landmarks.shape[0] == len(list(self._landmark_names)), 'Unexpected number of landmarks: {}'.format(landmarks.shape[0])landmarks = self._normalize_landmarks(landmarks)# Get embedding.embedding = self._get_embedding(landmarks)return embeddingelse:print('ERROR: Can NOT embedding the data you provided !')def _get_center(self, landmarks):# MIDDLE_FINGER_MCP:9return landmarks[9]def _get_size(self, landmarks):landmarks = landmarks[:, :2]max_dist = np.max(np.linalg.norm(landmarks - self._get_center(landmarks), axis=1))return max_dist * 2def _normalize_landmarks(self, landmarks):landmarks = np.copy(landmarks)# Normalizecenter = self._get_center(landmarks)size = self._get_size(landmarks)landmarks = (landmarks - center) / sizelandmarks *= 100  # optional, but makes debugging easier.return landmarksdef _get_embedding(self, landmarks):# we can add and delete any embedding featurestest = np.array([np.dot((landmarks[2]-landmarks[0]),(landmarks[3]-landmarks[4])),   # thumb bentnp.dot((landmarks[5]-landmarks[0]), (landmarks[6]-landmarks[7])),np.dot((landmarks[9]-landmarks[0]), (landmarks[10]-landmarks[11])),np.dot((landmarks[13]-landmarks[0]),(landmarks[14]-landmarks[15])),np.dot((landmarks[17]-landmarks[0]), (landmarks[18]-landmarks[19]))]).flatten()return testdef init_knn(file='data/dataset_embedded.npz'):npzfile = np.load(file)X = npzfile['X']y = npzfile['y']neigh = KNeighborsClassifier(n_neighbors=5)neigh.fit(X, y)return neighdef hand_pose_recognition(stream_img):# For static images:stream_img = cv2.cvtColor(stream_img, cv2.COLOR_BGR2RGB)embedder = Embedder()neighbors = init_knn()with mp_hands.Hands(static_image_mode=True,max_num_hands=2,min_detection_confidence=0.5) as hands:results = hands.process(stream_img)if not results.multi_hand_landmarks:return ['no_gesture'], stream_imgelse:annotated_image = stream_img.copy()multi_landmarks = results.multi_hand_landmarks# KNN inferenceembeddings = embedder(multi_landmarks)hand_class = neighbors.predict(embeddings)# hand_class_prob = neighbors.predict_proba(embeddings)# print(hand_class_prob)for landmarks in results.multi_hand_landmarks:mp_drawing.draw_landmarks(annotated_image,landmarks,mp_hands.HAND_CONNECTIONS,mp_drawing_styles.get_default_hand_landmarks_style(),mp_drawing_styles.get_default_hand_connections_style())return hand_class, annotated_image# 手势有10种,数字有8种,1-10之间7和9没有,还有两种是OK手势,和蜘蛛侠spide手势
# `eight_sign`, `five_sign`, `four_sign`, `ok`, `one_sign`, `six_sign`, `spider`, `ten_sign`, `three_sign`, `two_sign`def image():FILE_PATH = 'data/ok.png'img = cv2.imread(FILE_PATH)handclass, img_final = hand_pose_recognition(img)cv2.putText(img_final, text=handclass[0], org=(200, 50), fontFace=cv2.FONT_HERSHEY_SIMPLEX,fontScale=2, color=(255, 255, 255), thickness=2, lineType=cv2.LINE_AA)cv2.imshow('test', cv2.cvtColor(img_final, cv2.COLOR_RGB2BGR))cv2.waitKey(0)def video():cap = cv2.VideoCapture('data/ok.mp4')while cap.isOpened():ret, frame = cap.read()if not ret:breakhandclass, img_final = hand_pose_recognition(frame)cv2.putText(img_final, text=handclass[0], org=(50, 50), fontFace=cv2.FONT_HERSHEY_SIMPLEX,fontScale=2, color=(255, 0, 0), thickness=2, lineType=cv2.LINE_AA)cv2.imshow('test', cv2.cvtColor(img_final, cv2.COLOR_RGB2BGR))if cv2.waitKey(1) & 0xFF == ord('q'):breakif __name__ == '__main__':video()

mediapipe_007

参考

  1. https://developers.google.cn/mediapipe/solutions/
  2. https://github.com/googlesamples/mediapipe
  3. https://github.com/Furkan-Gulsen/Sport-With-AI
  4. https://github.com/Chuanfang-Neptune/DLAV-G9

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

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

相关文章

[C++核心编程-04]----C++类和对象之封装

目录 引言 正文 01-类和对象简介 02-封装简介 03-封装的意义 04-封装案例之设计学生类 05-封装的权限控制 06-struct和class的区别 07-成员属性设置为私有 08-封装案例1-设计立方体 09-封装案例2-判断点和圆的关系 总结 引言 在C中&#xff0c;…

Failed to build flash-attn:ERROR: Could not build wheels for flash-attn

安装 FlashAttention 的时候遇到报错&#xff1a; Failed to build flash-attn ERROR: Could not build wheels for flash-attn, which is required to install pyproject.toml-based projects可能是安装的版本与环境存在冲突吧&#xff0c;我的环境是&#xff1a; python 3.1…

堆的应用2——TOPK问题

TOPK问题 TOP-K问题&#xff1a;即求数据结合中前K个最大的元素或者最小的元素&#xff0c;一般情况下数据量都比较大。 比如&#xff1a;专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。 情况1——数据量小 对于Top-K问题&#xff0c;能想到的最简单直接的方式就…

嵌入式C语言高级教程:实现基于STM32的自适应交通信号控制系统

自适应交通信号控制系统能够基于实时交通流数据调整信号灯的时长&#xff0c;提高路口的通行效率。本教程将指导您如何在STM32微控制器上实现一个基本的自适应交通信号控制系统。 一、开发环境准备 硬件要求 微控制器&#xff1a;STM32F103C8&#xff0c;具备足够的处理能力…

Eclipse下载安装教程(包含JDK安装)【保姆级教学】【2023.10月最新版】

目录 文章最后附下载链接 第一步&#xff1a;下载Eclipse&#xff0c;并安装 第二步&#xff1a;下载JDK&#xff0c;并安装 第三步&#xff1a;Java运行环境配置 安装Eclipse必须同时安装JDK &#xff01;&#xff01;&#xff01; 文章最后附下载链接 第一步&#xf…

[法规规划|数据概念]金融行业数据资产和安全管理系列文件解析(3)

“ 金融行业在自身数据治理和资产化建设方面一直走在前列。” 一直以来&#xff0c;金融行业由于其自身需要&#xff0c;都是国内开展信息化建设最早&#xff0c;信息化程度最高的行业。 在当今数据要素资产化的浪潮下&#xff0c;除了行业自身自身数据治理和资产化建设方面&am…

EditReady for Mac激活版:专业视频转码工具

对于视频专业人员来说&#xff0c;一款高效的视频转码工具是不可或缺的。EditReady for Mac正是这样一款强大的工具&#xff0c;它拥有简洁直观的操作界面和强大的功能&#xff0c;让您的视频处理工作事半功倍。 EditReady for Mac支持多种视频格式的转码&#xff0c;并且支持常…

【Java】初识网络编程

文章目录 前言✍一、互联网的发展1.独立模式2.网络的出现局域网LAN广域网WAN ✍二、网络编程概述✍三、网络编程中的术语介绍IP地址端口号协议OSI七层模型TCP\IP四层模型 ✍四、协议的层级之间是如何配合工作的 前言 在本文中&#xff0c;会对网络编程的一些术语进行解释&#…

动态规划——路径问题:931.下降路径最小和

文章目录 题目描述算法原理1.状态表示&#xff08;经验题目&#xff09;2.状态转移方程3.初始化4.填表顺序5.返回值 代码实现CJava 题目描述 题目链接&#xff1a;931.下降路径最小和 关于这⼀类题&#xff0c;看过我之前的博客的朋友对于状态表示以及状态转移是⽐较容易分析…

5分钟了解下HDFS

随着大数据时代的到来&#xff0c;传统的数据存储和管理方式已经无法满足日益增长的数据处理需求。HDFS&#xff08;Hadoop Distributed File System&#xff09;作为Apache Hadoop项目的一部分&#xff0c;以其高度的容错性、可扩展性和高吞吐量&#xff0c;成为了处理大规模数…

抖音APP运用的AI技术拆解

1.推荐系统&#xff08;RS&#xff09; 用户画像&#xff1a;根据用户的信息&#xff08;如地区、性别、年龄、收藏、关注......&#xff09;进行分析&#xff0c;构建用户画像&#xff0c;对用户进行分类&#xff1b; 行为分析&#xff1a;将用户的显形行为数据&#xff08;如…

搜维尔科技:OptiTrack是基于LED墙虚拟制作舞台的最佳选择

OptiTrack因其绝对精度、易用性、可靠性以及与现场工具的完美集成而被选中&#xff0c;仍然是全球首屈一指的基于 LED 墙的虚拟制作舞台的选择。 当今虚拟制作阶段的低延迟、超精确摄像机跟踪标准 /- 0.2 毫米 位置精度1 < 10 毫秒 系统延迟 /- 0.1 度 旋转精度2 电影…

Linux 操作系统网络编程1

目录 1、网络编程 1.1 OSI 网络七层模型 1.1.1 OSI 参考模型 1.1.2 网络数据传输过程 2 传输层通信协议 2.1 TCP 2.1.1 TCP的3次握手过程 2.1.2 TCP四次挥手过程 2.2 UDP 3 网络编程的IP地址 4 端口 5 套接字 1、网络编程 1.1 OSI 网络七层模型 1.1.1 OSI 参考模型…

Linux cmake 初窥【3】

1.开发背景 基于上一篇的基础上&#xff0c;已经实现了多个源文件路径调用&#xff0c;但是没有库的实现 2.开发需求 基于 cmake 的动态库和静态库的调用 3.开发环境 ubuntu 20.04 cmake-3.23.1 4.实现步骤 4.1 准备源码文件 基于上个试验的基础上&#xff0c;增加了动态库…

优思学院|精益六西格玛黑带培训的内容有哪些?【附思维导图】

引言 在现代企业中&#xff0c;精益六西格玛黑带&#xff08;或称六西格玛黑带&#xff09;处于实施六西格玛方法的最前线。然而&#xff0c;他们的职责远不止执行者的角色。黑带既学习六西格玛的工具&#xff0c;又主导项目以改进绩效指标。在更长远的角度看&#xff0c;他们…

擎天科技与禅道合作,打造统一的项目管理平台

统一、全面的项目管理平台能够帮助企业优化管理流程&#xff0c;提升业务效率。擎天集团选择与禅道软件合作&#xff0c;打造统一的项目管理平台&#xff0c;在降低自研软件的研发成本、打破团队信息孤岛、保障数据全面性等方面效果显著&#xff0c;大大提高了团队沟通协作效率…

25852-47-5,MAc-PEG-MAc通常作为高分子材料的交联剂,以提高材料的力学性能和稳定性

【试剂详情】 英文名称 Methacrylate-PEG-Methacrylate&#xff0c;MAc-PEG-MAc 中文名称 甲基丙烯酸酯-聚乙二醇-甲基丙烯酸酯 CAS号 25852-47-5 外观性状 由分子量决定&#xff0c;固体或者液体。 分子量 0.4k&#xff0c;0.6k&#xff0c;1k&#xff0c;2k&#xf…

基于51单片机的温度检测自动调节设计—温度上下限报警自动控制

基于51单片机的温度自动调节 &#xff08;仿真&#xff0b;程序原理图&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1.DS18B20检测温度给单片机处理&#xff1b; 2.LCD1602显示实时温度、温度上下限&#xff1b; 3.三个按键可设置温度上下限&#xff1…

【项目】使用Yolov8 + tesseract 实现“营业执照”信息解析(OCR) + 输入可为图片或者pdf + 完整代码 + 整体方案 + 全网首发

本项目可用于毕业设计参考、实验等,营业执照分为横版和竖版,整体检测+识别效果如下所示: 说明:图片来源于网络,如有侵权,请联系作者删除。 目录

【JUC】并发编程 Synchronized 锁升级原理

Synchronized如何实现同步/互斥的效果&#xff1f; monitorenter&#xff1a; 将锁对象对象头中Mark Word的前30bit替换成指向操作系统中与其关联的monitor对象&#xff0c;将锁记录位状态改为10 monitorexit&#xff1a; 将锁对象对象头中Mark Word进行重置&#xff0c;重新恢…