yolov8 人体姿态关键点检测

news2024/11/22 15:32:59

参考:
https://github.com/ultralytics/ultralytics
https://github.com/TommyZihao/Train_Custom_Dataset/tree/main/%E5%85%B3%E9%94%AE%E7%82%B9%E6%A3%80%E6%B5%8B
在这里插入图片描述

##安装
pip install ultralytics -i https://pypi.douban.com/simple

1、命令行运行

pip安装好后就可以yolo 命令运行执行

yolo predict model=yolov8n.pt source='https://ultralytics.com/images/bus.jpg'
##检测
yolo detect predict model=yolov8n.pt source='https://ultralytics.com/images/bus.jpg'   

##分割
yolo segment predict model=yolov8n-seg.pt source='https://ultralytics.com/images/bus.jpg'  

##pose
yolo pose predict model=yolov8n-pose.pt source='https://ultralytics.com/images/bus.jpg'

yolo pose predict model=yolov8x-pose-p6.pt source=videos/cxk.mp4 device=0

在这里插入图片描述

在这里插入图片描述
*** 运行效果,source=0是直接调用本地摄像头

yolo pose predict model=yolov8l-pose.pt source=0 show

在这里插入图片描述

2、python接口运行

注意:boxs、keypoints数据获取现在都在data里了
在这里插入图片描述

from ultralytics import YOLO

import cv2
import matplotlib.pyplot as plt


import torch

# 有 GPU 就用 GPU,没有就用 CPU
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

# 载入预训练模型
# model = YOLO('yolov8n-pose.pt')
# model = YOLO('yolov8s-pose.pt')
# model = YOLO('yolov8m-pose.pt')
# model = YOLO('yolov8l-pose.pt')
# model = YOLO('yolov8x-pose.pt')
model = YOLO(r'C:\Users\lonng\Downloads\yolov8l-pose.pt')

# 切换计算设备
model.to(device)

##预测  传入图像、视频、摄像头ID(对应命令行的 source 参数)
img_path = '11.jpg'
results = model(img_path)

##结果

print(len(results),results[0])

结果:
640x512 1 person, 114.0ms
Speed: 8.0ms preprocess, 114.0ms inference, 7.0ms postprocess per image at shape (1, 3, 640, 640)
1 ultralytics.yolo.engine.results.Results object with attributes:

boxes: ultralytics.yolo.engine.results.Boxes object
keypoints: ultralytics.yolo.engine.results.Keypoints object
keys: [‘boxes’, ‘keypoints’]
masks: None
names: {0: ‘person’} ## 0分类表示person
orig_img: array([[[ 25, 27, 36],
[ 25, 27, 36],
[ 25, 27, 36],
…,
[ 35, 55, 90],
[ 35, 55, 90],
[ 35, 55, 90]],

   [[ 25,  27,  36],
    [ 25,  27,  36],
    [ 25,  27,  36],
    ...,
    [ 35,  55,  90],
    [ 35,  55,  90],
    [ 35,  55,  90]],

   [[ 25,  27,  36],
    [ 25,  27,  36],
    [ 25,  27,  36],
    ...,
    [ 36,  56,  91],
    [ 36,  56,  91],
    [ 36,  56,  91]],

   ...,

   [[ 24,  21,   8],
    [ 24,  21,   8],
    [ 24,  21,   8],
    ...,
    [102, 120, 162],
    [102, 120, 162],
    [102, 120, 162]],

   [[ 22,  22,   8],
    [ 22,  22,   8],
    [ 22,  22,   8],
    ...,
    [102, 120, 162],
    [102, 120, 162],
    [102, 120, 162]],

   [[ 22,  22,   8],
    [ 22,  22,   8],
    [ 22,  22,   8],
    ...,
    [102, 120, 162],
    [102, 120, 162],
    [102, 120, 162]]], dtype=uint8)

orig_shape: (2092, 1600)
path: ‘C:\Users\lonng\Desktop\rdkit_learn\opencv2\11.jpg’
probs: None
speed: {‘preprocess’: 8.000612258911133, ‘inference’: 113.99602890014648, ‘postprocess’: 6.998538970947266}

完整代码

from ultralytics import YOLO

import cv2
import matplotlib.pyplot as plt


import torch

# 有 GPU 就用 GPU,没有就用 CPU
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

# 载入预训练模型
# model = YOLO('yolov8n-pose.pt')
# model = YOLO('yolov8s-pose.pt')
# model = YOLO('yolov8m-pose.pt')
# model = YOLO('yolov8l-pose.pt')
# model = YOLO('yolov8x-pose.pt')
model = YOLO(r'C:\Users\lonng\Downloads\yolov8l-pose.pt')

# 切换计算设备
model.to(device)

##预测  传入图像、视频、摄像头ID(对应命令行的 source 参数)
img_path = '11.jpg'
results = model(img_path)

##结果

print(len(results),results[0])




# 框(rectangle)可视化配置
bbox_color = (150, 0, 0)             # 框的 BGR 颜色
bbox_thickness = 6                   # 框的线宽

# 框类别文字
bbox_labelstr = {
    'font_size':6,         # 字体大小
    'font_thickness':14,   # 字体粗细
    'offset_x':0,          # X 方向,文字偏移距离,向右为正
    'offset_y':-80,        # Y 方向,文字偏移距离,向下为正
}

# 关键点 BGR 配色
kpt_color_map = {
    0:{'name':'Nose', 'color':[0, 0, 255], 'radius':10},                # 鼻尖
    1:{'name':'Right Eye', 'color':[255, 0, 0], 'radius':10},           # 右边眼睛
    2:{'name':'Left Eye', 'color':[255, 0, 0], 'radius':10},            # 左边眼睛
    3:{'name':'Right Ear', 'color':[0, 255, 0], 'radius':10},           # 右边耳朵
    4:{'name':'Left Ear', 'color':[0, 255, 0], 'radius':10},            # 左边耳朵
    5:{'name':'Right Shoulder', 'color':[193, 182, 255], 'radius':10},  # 右边肩膀
    6:{'name':'Left Shoulder', 'color':[193, 182, 255], 'radius':10},   # 左边肩膀
    7:{'name':'Right Elbow', 'color':[16, 144, 247], 'radius':10},      # 右侧胳膊肘
    8:{'name':'Left Elbow', 'color':[16, 144, 247], 'radius':10},       # 左侧胳膊肘
    9:{'name':'Right Wrist', 'color':[1, 240, 255], 'radius':10},       # 右侧手腕
    10:{'name':'Left Wrist', 'color':[1, 240, 255], 'radius':10},       # 左侧手腕
    11:{'name':'Right Hip', 'color':[140, 47, 240], 'radius':10},       # 右侧胯
    12:{'name':'Left Hip', 'color':[140, 47, 240], 'radius':10},        # 左侧胯
    13:{'name':'Right Knee', 'color':[223, 155, 60], 'radius':10},      # 右侧膝盖
    14:{'name':'Left Knee', 'color':[223, 155, 60], 'radius':10},       # 左侧膝盖
    15:{'name':'Right Ankle', 'color':[139, 0, 0], 'radius':10},        # 右侧脚踝
    16:{'name':'Left Ankle', 'color':[139, 0, 0], 'radius':10},         # 左侧脚踝
}

# 点类别文字
kpt_labelstr = {
    'font_size':4,             # 字体大小
    'font_thickness':2,       # 字体粗细
    'offset_x':0,             # X 方向,文字偏移距离,向右为正
    'offset_y':150,            # Y 方向,文字偏移距离,向下为正
}

# 骨架连接 BGR 配色
skeleton_map = [
    {'srt_kpt_id':15, 'dst_kpt_id':13, 'color':[0, 100, 255], 'thickness':5},       # 右侧脚踝-右侧膝盖
    {'srt_kpt_id':13, 'dst_kpt_id':11, 'color':[0, 255, 0], 'thickness':5},         # 右侧膝盖-右侧胯
    {'srt_kpt_id':16, 'dst_kpt_id':14, 'color':[255, 0, 0], 'thickness':5},         # 左侧脚踝-左侧膝盖
    {'srt_kpt_id':14, 'dst_kpt_id':12, 'color':[0, 0, 255], 'thickness':5},         # 左侧膝盖-左侧胯
    {'srt_kpt_id':11, 'dst_kpt_id':12, 'color':[122, 160, 255], 'thickness':5},     # 右侧胯-左侧胯
    {'srt_kpt_id':5, 'dst_kpt_id':11, 'color':[139, 0, 139], 'thickness':5},        # 右边肩膀-右侧胯
    {'srt_kpt_id':6, 'dst_kpt_id':12, 'color':[237, 149, 100], 'thickness':5},      # 左边肩膀-左侧胯
    {'srt_kpt_id':5, 'dst_kpt_id':6, 'color':[152, 251, 152], 'thickness':5},       # 右边肩膀-左边肩膀
    {'srt_kpt_id':5, 'dst_kpt_id':7, 'color':[148, 0, 69], 'thickness':5},          # 右边肩膀-右侧胳膊肘
    {'srt_kpt_id':6, 'dst_kpt_id':8, 'color':[0, 75, 255], 'thickness':5},          # 左边肩膀-左侧胳膊肘
    {'srt_kpt_id':7, 'dst_kpt_id':9, 'color':[56, 230, 25], 'thickness':5},         # 右侧胳膊肘-右侧手腕
    {'srt_kpt_id':8, 'dst_kpt_id':10, 'color':[0,240, 240], 'thickness':5},         # 左侧胳膊肘-左侧手腕
    {'srt_kpt_id':1, 'dst_kpt_id':2, 'color':[224,255, 255], 'thickness':5},        # 右边眼睛-左边眼睛
    {'srt_kpt_id':0, 'dst_kpt_id':1, 'color':[47,255, 173], 'thickness':5},         # 鼻尖-左边眼睛
    {'srt_kpt_id':0, 'dst_kpt_id':2, 'color':[203,192,255], 'thickness':5},         # 鼻尖-左边眼睛
    {'srt_kpt_id':1, 'dst_kpt_id':3, 'color':[196, 75, 255], 'thickness':5},        # 右边眼睛-右边耳朵
    {'srt_kpt_id':2, 'dst_kpt_id':4, 'color':[86, 0, 25], 'thickness':5},           # 左边眼睛-左边耳朵
    {'srt_kpt_id':3, 'dst_kpt_id':5, 'color':[255,255, 0], 'thickness':5},          # 右边耳朵-右边肩膀
    {'srt_kpt_id':4, 'dst_kpt_id':6, 'color':[255, 18, 200], 'thickness':5}         # 左边耳朵-左边肩膀
]


## 解析目标检测预测结果
num_bbox = len(results[0].boxes.cls)
print('预测出 {} 个框'.format(num_bbox))
# 转成整数的 numpy array
bboxes_xyxy = results[0].boxes.xyxy.cpu().numpy().astype('uint32')
print("bboxes_xyxy:",bboxes_xyxy)
## 解析关键点检测预测结果
# print("bboxes_keypoints:",results[0].keypoints.data.cpu().numpy().astype('uint32'))
bboxes_keypoints = results[0].keypoints.data.cpu().numpy().astype('uint32')






for idx in range(num_bbox): # 遍历每个框
    
    # 获取该框坐标
    bbox_xyxy = bboxes_xyxy[idx] 
    
    # 获取框的预测类别(对于关键点检测,只有一个类别)
    bbox_label = results[0].names[0]
    

    img_bgr = cv2.imread(img_path)
    # 画框
    img_bgr = cv2.rectangle(img_bgr, (bbox_xyxy[0], bbox_xyxy[1]), (bbox_xyxy[2], bbox_xyxy[3]), bbox_color, bbox_thickness)
    
    # 写框类别文字:图片,文字字符串,文字左上角坐标,字体,字体大小,颜色,字体粗细
    img_bgr = cv2.putText(img_bgr, bbox_label, (bbox_xyxy[0]+bbox_labelstr['offset_x'], bbox_xyxy[1]+bbox_labelstr['offset_y']), cv2.FONT_HERSHEY_SIMPLEX, bbox_labelstr['font_size'], bbox_color, bbox_labelstr['font_thickness'])
    
    bbox_keypoints = bboxes_keypoints[idx] # 该框所有关键点坐标和置信度
    
    # 画该框的骨架连接
    for skeleton in skeleton_map:
        
        # 获取起始点坐标
        srt_kpt_id = skeleton['srt_kpt_id']
        srt_kpt_x = bbox_keypoints[srt_kpt_id][0]
        srt_kpt_y = bbox_keypoints[srt_kpt_id][1]
        
        # 获取终止点坐标
        dst_kpt_id = skeleton['dst_kpt_id']
        dst_kpt_x = bbox_keypoints[dst_kpt_id][0]
        dst_kpt_y = bbox_keypoints[dst_kpt_id][1]
        
        # 获取骨架连接颜色
        skeleton_color = skeleton['color']
        
        # 获取骨架连接线宽
        skeleton_thickness = skeleton['thickness']
        
        # 画骨架连接
        img_bgr = cv2.line(img_bgr, (srt_kpt_x, srt_kpt_y),(dst_kpt_x, dst_kpt_y),color=skeleton_color,thickness=skeleton_thickness)
        
    # 画该框的关键点
    for kpt_id in kpt_color_map:
        
        # 获取该关键点的颜色、半径、XY坐标
        kpt_color = kpt_color_map[kpt_id]['color']
        kpt_radius = kpt_color_map[kpt_id]['radius']
        kpt_x = bbox_keypoints[kpt_id][0]
        kpt_y = bbox_keypoints[kpt_id][1]
        
        # 画圆:图片、XY坐标、半径、颜色、线宽(-1为填充)
        img_bgr = cv2.circle(img_bgr, (kpt_x, kpt_y), kpt_radius, kpt_color, -1)
        
        # 写关键点类别文字:图片,文字字符串,文字左上角坐标,字体,字体大小,颜色,字体粗细
        # kpt_label = str(kpt_id) # 写关键点类别 ID(二选一)
        # kpt_label = str(kpt_color_map[kpt_id]['name']) # 写关键点类别名称(二选一)
        # img_bgr = cv2.putText(img_bgr, kpt_label, (kpt_x+kpt_labelstr['offset_x'], kpt_y+kpt_labelstr['offset_y']), cv2.FONT_HERSHEY_SIMPLEX, kpt_labelstr['font_size'], kpt_color, kpt_labelstr['font_thickness'])




plt.imshow(img_bgr[:,:,::-1])
plt.show()
cv2.imwrite('11_pose.jpg', img_bgr)

在这里插入图片描述

实时摄像头关键点检测

from ultralytics import YOLO

import cv2
import matplotlib.pyplot as plt

import time
import torch

# 有 GPU 就用 GPU,没有就用 CPU
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

# 载入预训练模型
# model = YOLO('yolov8n-pose.pt')
# model = YOLO('yolov8s-pose.pt')
# model = YOLO('yolov8m-pose.pt')
# model = YOLO('yolov8l-pose.pt')
# model = YOLO('yolov8x-pose.pt')
model = YOLO(r'C:\Users\lonng\Downloads\yolov8l-pose.pt')

# 切换计算设备
model.to(device)



# 框(rectangle)可视化配置
bbox_color = (150, 0, 0)             # 框的 BGR 颜色
bbox_thickness = 2                   # 框的线宽

# 框类别文字
bbox_labelstr = {
    'font_size':2,         # 字体大小
    'font_thickness':4,   # 字体粗细
    'offset_x':0,          # X 方向,文字偏移距离,向右为正
    'offset_y':-20,       # Y 方向,文字偏移距离,向下为正
}

# 关键点 BGR 配色
kpt_color_map = {
    0:{'name':'Nose', 'color':[0, 0, 255], 'radius':6},                # 鼻尖
    1:{'name':'Right Eye', 'color':[255, 0, 0], 'radius':6},           # 右边眼睛
    2:{'name':'Left Eye', 'color':[255, 0, 0], 'radius':6},            # 左边眼睛
    3:{'name':'Right Ear', 'color':[0, 255, 0], 'radius':6},           # 右边耳朵
    4:{'name':'Left Ear', 'color':[0, 255, 0], 'radius':6},            # 左边耳朵
    5:{'name':'Right Shoulder', 'color':[193, 182, 255], 'radius':6},  # 右边肩膀
    6:{'name':'Left Shoulder', 'color':[193, 182, 255], 'radius':6},   # 左边肩膀
    7:{'name':'Right Elbow', 'color':[16, 144, 247], 'radius':6},      # 右侧胳膊肘
    8:{'name':'Left Elbow', 'color':[16, 144, 247], 'radius':6},       # 左侧胳膊肘
    9:{'name':'Right Wrist', 'color':[1, 240, 255], 'radius':6},       # 右侧手腕
    10:{'name':'Left Wrist', 'color':[1, 240, 255], 'radius':6},       # 左侧手腕
    11:{'name':'Right Hip', 'color':[140, 47, 240], 'radius':6},       # 右侧胯
    12:{'name':'Left Hip', 'color':[140, 47, 240], 'radius':6},        # 左侧胯
    13:{'name':'Right Knee', 'color':[223, 155, 60], 'radius':6},      # 右侧膝盖
    14:{'name':'Left Knee', 'color':[223, 155, 60], 'radius':6},       # 左侧膝盖
    15:{'name':'Right Ankle', 'color':[139, 0, 0], 'radius':6},        # 右侧脚踝
    16:{'name':'Left Ankle', 'color':[139, 0, 0], 'radius':6},         # 左侧脚踝
}

# 点类别文字
kpt_labelstr = {
    'font_size':1.5,             # 字体大小
    'font_thickness':3,       # 字体粗细
    'offset_x':10,             # X 方向,文字偏移距离,向右为正
    'offset_y':0,            # Y 方向,文字偏移距离,向下为正
}

# 骨架连接 BGR 配色
skeleton_map = [
    {'srt_kpt_id':15, 'dst_kpt_id':13, 'color':[0, 100, 255], 'thickness':2},       # 右侧脚踝-右侧膝盖
    {'srt_kpt_id':13, 'dst_kpt_id':11, 'color':[0, 255, 0], 'thickness':2},         # 右侧膝盖-右侧胯
    {'srt_kpt_id':16, 'dst_kpt_id':14, 'color':[255, 0, 0], 'thickness':2},         # 左侧脚踝-左侧膝盖
    {'srt_kpt_id':14, 'dst_kpt_id':12, 'color':[0, 0, 255], 'thickness':2},         # 左侧膝盖-左侧胯
    {'srt_kpt_id':11, 'dst_kpt_id':12, 'color':[122, 160, 255], 'thickness':2},     # 右侧胯-左侧胯
    {'srt_kpt_id':5, 'dst_kpt_id':11, 'color':[139, 0, 139], 'thickness':2},        # 右边肩膀-右侧胯
    {'srt_kpt_id':6, 'dst_kpt_id':12, 'color':[237, 149, 100], 'thickness':2},      # 左边肩膀-左侧胯
    {'srt_kpt_id':5, 'dst_kpt_id':6, 'color':[152, 251, 152], 'thickness':2},       # 右边肩膀-左边肩膀
    {'srt_kpt_id':5, 'dst_kpt_id':7, 'color':[148, 0, 69], 'thickness':2},          # 右边肩膀-右侧胳膊肘
    {'srt_kpt_id':6, 'dst_kpt_id':8, 'color':[0, 75, 255], 'thickness':2},          # 左边肩膀-左侧胳膊肘
    {'srt_kpt_id':7, 'dst_kpt_id':9, 'color':[56, 230, 25], 'thickness':2},         # 右侧胳膊肘-右侧手腕
    {'srt_kpt_id':8, 'dst_kpt_id':10, 'color':[0,240, 240], 'thickness':2},         # 左侧胳膊肘-左侧手腕
    {'srt_kpt_id':1, 'dst_kpt_id':2, 'color':[224,255, 255], 'thickness':2},        # 右边眼睛-左边眼睛
    {'srt_kpt_id':0, 'dst_kpt_id':1, 'color':[47,255, 173], 'thickness':2},         # 鼻尖-左边眼睛
    {'srt_kpt_id':0, 'dst_kpt_id':2, 'color':[203,192,255], 'thickness':2},         # 鼻尖-左边眼睛
    {'srt_kpt_id':1, 'dst_kpt_id':3, 'color':[196, 75, 255], 'thickness':2},        # 右边眼睛-右边耳朵
    {'srt_kpt_id':2, 'dst_kpt_id':4, 'color':[86, 0, 25], 'thickness':2},           # 左边眼睛-左边耳朵
    {'srt_kpt_id':3, 'dst_kpt_id':5, 'color':[255,255, 0], 'thickness':2},          # 右边耳朵-右边肩膀
    {'srt_kpt_id':4, 'dst_kpt_id':6, 'color':[255, 18, 200], 'thickness':2}         # 左边耳朵-左边肩膀
]


## 逐帧处理函数
def process_frame(img_bgr):
    
    '''
    输入摄像头画面 bgr-array,输出图像 bgr-array
    '''
    
    # 记录该帧开始处理的时间
    start_time = time.time()
    
    results = model(img_bgr, verbose=False) # verbose设置为False,不单独打印每一帧预测结果
    
    # 预测框的个数
    num_bbox = len(results[0].boxes.cls)
    
    # 预测框的 xyxy 坐标
    bboxes_xyxy = results[0].boxes.xyxy.cpu().numpy().astype('uint32') 
    
    # 关键点的 xy 坐标
    bboxes_keypoints = results[0].keypoints.data.cpu().numpy().astype('uint32')
    
    for idx in range(num_bbox): # 遍历每个框

        # 获取该框坐标
        bbox_xyxy = bboxes_xyxy[idx] 

        # 获取框的预测类别(对于关键点检测,只有一个类别)
        bbox_label = results[0].names[0]

        # 画框
        img_bgr = cv2.rectangle(img_bgr, (bbox_xyxy[0], bbox_xyxy[1]), (bbox_xyxy[2], bbox_xyxy[3]), bbox_color, bbox_thickness)

        # 写框类别文字:图片,文字字符串,文字左上角坐标,字体,字体大小,颜色,字体粗细
        img_bgr = cv2.putText(img_bgr, bbox_label, (bbox_xyxy[0]+bbox_labelstr['offset_x'], bbox_xyxy[1]+bbox_labelstr['offset_y']), cv2.FONT_HERSHEY_SIMPLEX, bbox_labelstr['font_size'], bbox_color, bbox_labelstr['font_thickness'])

        bbox_keypoints = bboxes_keypoints[idx] # 该框所有关键点坐标和置信度

        # 画该框的骨架连接
        for skeleton in skeleton_map:

            # 获取起始点坐标
            srt_kpt_id = skeleton['srt_kpt_id']
            srt_kpt_x = bbox_keypoints[srt_kpt_id][0]
            srt_kpt_y = bbox_keypoints[srt_kpt_id][1]

            # 获取终止点坐标
            dst_kpt_id = skeleton['dst_kpt_id']
            dst_kpt_x = bbox_keypoints[dst_kpt_id][0]
            dst_kpt_y = bbox_keypoints[dst_kpt_id][1]

            # 获取骨架连接颜色
            skeleton_color = skeleton['color']

            # 获取骨架连接线宽
            skeleton_thickness = skeleton['thickness']

            # 画骨架连接
            img_bgr = cv2.line(img_bgr, (srt_kpt_x, srt_kpt_y),(dst_kpt_x, dst_kpt_y),color=skeleton_color,thickness=skeleton_thickness)
                 
        # 画该框的关键点
        for kpt_id in kpt_color_map:

            # 获取该关键点的颜色、半径、XY坐标
            kpt_color = kpt_color_map[kpt_id]['color']
            kpt_radius = kpt_color_map[kpt_id]['radius']
            kpt_x = bbox_keypoints[kpt_id][0]
            kpt_y = bbox_keypoints[kpt_id][1]

            # 画圆:图片、XY坐标、半径、颜色、线宽(-1为填充)
            img_bgr = cv2.circle(img_bgr, (kpt_x, kpt_y), kpt_radius, kpt_color, -1)

            # 写关键点类别文字:图片,文字字符串,文字左上角坐标,字体,字体大小,颜色,字体粗细
            # kpt_label = str(kpt_id) # 写关键点类别 ID(二选一)
            # kpt_label = str(kpt_color_map[kpt_id]['name']) # 写关键点类别名称(二选一)
            # img_bgr = cv2.putText(img_bgr, kpt_label, (kpt_x+kpt_labelstr['offset_x'], kpt_y+kpt_labelstr['offset_y']), cv2.FONT_HERSHEY_SIMPLEX, kpt_labelstr['font_size'], kpt_color, kpt_labelstr['font_thickness'])
            
    # 记录该帧处理完毕的时间
    end_time = time.time()
    # 计算每秒处理图像帧数FPS
    FPS = 1/(end_time - start_time)

    # 在画面上写字:图片,字符串,左上角坐标,字体,字体大小,颜色,字体粗细
    FPS_string = 'FPS  '+str(int(FPS)) # 写在画面上的字符串
    img_bgr = cv2.putText(img_bgr, FPS_string, (25, 60), cv2.FONT_HERSHEY_SIMPLEX, 1.25, (255, 0, 255), 2)
    
    return img_bgr



# 调用摄像头逐帧实时处理模板
# 不需修改任何代码,只需修改process_frame函数即可
# 同济子豪兄 2021-7-8

# 导入opencv-python
import cv2
import time

# 获取摄像头,传入0表示获取系统默认摄像头
cap = cv2.VideoCapture(1)

# 打开cap
cap.open(0)

# 无限循环,直到break被触发
while cap.isOpened():
    
    # 获取画面
    success, frame = cap.read()
    
    if not success: # 如果获取画面不成功,则退出
        print('获取画面不成功,退出')
        break
    
    ## 逐帧处理
    frame = process_frame(frame)
    
    # 展示处理后的三通道图像
    cv2.imshow('my_window',frame)
    
    key_pressed = cv2.waitKey(60) # 每隔多少毫秒毫秒,获取键盘哪个键被按下
    # print('键盘上被按下的键:', key_pressed)

    if key_pressed in [ord('q'),27]: # 按键盘上的q或esc退出(在英文输入法下)
        break
    
# 关闭摄像头
cap.release()

# 关闭图像窗口
cv2.destroyAllWindows()

在这里插入图片描述

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

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

相关文章

图像金字塔

​ 图像金字塔是由一幅图像的多个不同分辨率的子图构成的图像集合。是通过一个图像不断的降低采样率产生的,最小的图像可能仅仅有一个像素点。下图是一个图像金子塔的示例。从图中可以看到,图像金字塔是一系列以金字塔形状排列的、自底向上分辨率逐渐降低…

静电监控系统选购策略:有效提高系统可靠性与性价比

随着工业自动化和信息化程度的提高,静电在工业生产中的影响越来越显著。静电的存在会对电子设备、传输介质等产生不良影响,甚至会导致产品损坏和火灾事故的发生。因此,静电监控系统的选购对于工业生产的稳定具有重要意义。 一、功能需求 静…

Java实训日志06

文章目录 八、项目开发实现步骤(八)创建服务接口1、创建学校服务接口2、创建状态服务接口3、创建学生服务接口4、创建用户服务接口 (九)创建服务接口实现类1、创建学校服务接口实现类2、创建状态服务接口实现类3、创建学生服务接口…

【CMake 入门与进阶(10)】 CMakeLists.txt 语法规则_循环语句(附使用代码)

cmake 中除了 if 条件判断之外,还支持循环语句,包括 foreach()循环、while()循环。 foreach 循环 1、foreach 基本用法 foreach 循环的基本用法如下所示: foreach(loop_var arg1 arg2 ...)command1(args ...)command2(args ...)... endfore…

chatgpt赋能python:Python编写计算器的方法

Python编写计算器的方法 介绍 计算器是一款常见的实用工具,它能够进行基本的算数运算,如加减乘除等。在Python中,我们可以利用各种库和函数来实现计算器的功能,从而方便地进行数值计算。 怎么编写计算器 在Python中&#xff0…

WINS服务的作用和效率

WINS服务的作用和效率 目录 WINS服务的作用和效率 一、WINS服务 二、配置 2.1、服务端 2.2、客户端 2.3、配置方法 三、效果 3.1、计算机-网络(过去的“网上邻居”) 3.2、局域网打印机共享 3.3、基于NetBios名称的数据库客户端连接 一、WINS服…

爆肝万字带你超级详细全面了解Linux命令大全

🍁前言 👑作者主页:👉CSDN丨博客园 🏆学习交流:👉在下周周ovoの社区 对这篇万字博客目录总结如下: 关机命令、重启命令,创建用户、删除用户、修改密码、切换用户、切换到…

Centos8 如何给磁盘扩容

今天发现 在home目录下无法写入文件,经过查看磁盘空间,发现/dev/mapper/cl-home空间满了。于是乎,给磁盘进行扩容,扩充成功,下面将操作步骤分享出来。 查看空间 [rootasrcent8 ~]# df -k 文件系统 1K…

jsp与java bean

软件开发应具有较高的可维护性,以方便后续的代码维护,而实现高可维护性的有效途径是要实现软件的低耦合、高内聚。软件设计分层的概念主要就是将软件各部分进行解耦合设计,对于JSP动态开发技术而言, JavaBean是最基础的分层技术。…

Java集合框架:栈、Stack详解

目录 一、栈 二、栈的使用 1. Stack类 2. 栈的模拟实现 三、栈的应用场景 1. 改变元素的序列 2. 将递归转化为循环(如:逆序打印链表) 3. 栈的oj题练习(oj题中都用到了栈这种数据结构) 四、栈,虚拟机…

Stable diffusion webui 本地安装教学

Stable diffusion AI的绘图工具,这是一种扩散模型,可以通过不断去噪来获得最终的艺术作品。这款工具是当前最受欢迎的AI绘图工具之一,不仅是还是开源的,而且其中的AUTOMATIC111 Stable-diffusion-webui版本深受AI绘图玩家的喜爱&a…

三、Docker的基本组成和常用命令(一)

文章目录 Docker的基本组成镜像(image)容器(container)仓库(repository)总结 Docker的常用命令帮助命令镜像命令docker imagesdocker searchdocker pulldocker rmi Docker的基本组成 镜像(image) Docker 镜像(Image)就是一个只读的模板。镜像可以用来创…

用Netty自己实现Dubbo RPC

1.RPC基本介绍 1>.RPC(Remote Procedure Call)— 远程过程调用,是一个计算机通信协议.该协议允许运行在一台计算机中的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程; 2>.两个或多个应用程序都分布在不同的服务器上,它们之间的调用都像是本地方法…

跟着《代码随想录》练习代码

更新中。。。有错误请指正 数组 二分查找704 class Solution:def search(self,nums:list,target:int)->int:left 0right len(nums)-1while left<right:mid (leftright)//2guess nums[mid]if guess target:return midbreakelif guess > target:right mid -1els…

浅析浏览器的缓存

随着浏览器功能的日益强大&#xff0c;在工作中&#xff0c;浏览器是前端工程师们最重要的战友和开发调试工具&#xff0c;它承载着用户最舒适的用户体验&#xff0c;ui最佳的设计成果展示&#xff0c;后台数据最直观的展示。因此&#xff0c;对浏览器的认识和理解起到举足轻重…

使用pipe、select实现线程间通信和性能测试

一 代码实现 理论依据&#xff1a; 管道中无数据时&#xff0c;读阻塞。 写数据时&#xff0c;长度小于PIPE_BUF时&#xff0c;写数据是原子操作&#xff0c;这样不会出现写一半的情况。在我的虚拟机上PIPE_BUF的值是4096&#xff0c;在标准中linux系统中该值都是4096. 测试代…

小型极简主义 Linux 发行版:Peropesis

导读Peropesis 是 personal operating system 的转写简拼&#xff0c;一个小型、极简主义、基于命令行的 Linux 操作系统。目前仍是一个不完整的系统&#xff0c;但它正在不断改进。 此外&#xff0c;它是一个由自由软件创建的自由操作系统&#xff0c;在 GNU GPL 或 BSD 许可下…

csdn编辑模式

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

非授权访问测试-业务安全测试实操(9)

非授权访问测试, 越权测试 非授权访问测试 测试原理和方法 非授权访问是指用户在没有通过认证授权的情况下能够直接访问需要通过认证才能访问到的页面或文本信息。可以尝试在登录某网站前台或后台之后,将相关的页面链接复制到其他浏览器或其他电脑上进行访问,观察是否能访…

第二届BSN全球技术创新发展峰会在武汉成功举行

6月9日&#xff0c;由湖北省人民政府指导&#xff0c;湖北省发展改革委、国家信息中心联合主办&#xff0c;中国移动、中国电信、中国联通、武汉市江汉区人民政府、区块链服务网络&#xff08;BSN&#xff09;发展联盟、湖北省楚天云公司承办的第二届区块链服务网络&#xff08…