欢迎光临
我们一直在努力

海康VM6200实现深度推理功能:Python脚本调用YOLO模型

本文目录

    • 前言
    • 一、海康Python环境配置
      • 1.2 安装pip命令
    • 二、在海康中安装YOLO依赖
      • 2.1 安装依赖
      • 2.2 验证环境
    • 三、在Python脚本模块中导入YOLO模型
      • 3.1 准备onnx文件
      • 3.2 编写推理脚本

前言

声明:此文章仅为技术探讨探究使用,不可作为商业用途。如需转载,请务必联系作者本人获取授权,未经许可禁止转载、抄袭或用于任何商业用途。

本文将以YOLOv5官方权重为例,手把手带你在海康VM6200上完成从环境配置、依赖安装、模型转换(pt转onnx)到Python脚本模块推理调用的完整部署流程,并附上可直接运行的推理脚本,帮助你快速跑通深度学习功能。

一、海康Python环境配置

在刚开始研究的时候,不知道python版本是多少,不敢贸然安装依赖库,因为yolo环境中依赖库的版本与python版本有着严格的规定,如果不一致又要重新配。我这里在python脚本中确认了一下python版本,打印出的日志显示版本是3.7.0。### 1.1 海康内置python版本查询方法。

Python脚本查询

查询代码

v = sys.version_info
PrintMsg(f"Python Version: {v.major}.{v.minor}.{v.micro} "
f"({sys.version.split()[0]})")

1.2 安装pip命令

确认内置 Python 版本为 3.7 后,接下来需要为其安装 pip 工具,以便后续安装第三方库。在海康4.4版本中内置Python解释器位于以下路径:

以你实际安装位置为准。我这里是安装在了D盘。

D:\\Application\\HIKVision\\VisionMaster4.4.0\\Applications\\ModuleProxy\\x64

pip命令位置 没有安装python环境前Scripts文件夹是空的。 安装步骤:左键点击get-pip.py拖到python.exe中(相当于执行 python.exe get-pip.py 命令),之后会弹出一个黑色窗口,是在正在安装。安装完毕后会自动关闭。(如果你命令窗口有设置不自动关闭,那么不会关掉窗口,不要担心,你的窗口没关闭不是没安装成功。) 安装完成后,如果看到Scripts文件夹下新增了wheel.exe、pip.exe、pip3.7.exe、pip3.exe这四个文件代表安装成功。可进行下一步。

常见问题:

  • 如果安装后 Scripts 文件夹仍为空,可能是权限不足,建议以管理员身份运行。

二、在海康中安装YOLO依赖

配置好Python环境后,接下来需要安装YOLOv5运行所需的依赖库。

2.1 安装依赖

使用在刚才的文件夹的路径中输入cmd后敲回车进入命令行窗口进入命令行窗口1> 确保自己进入的窗口前的地址是你的python.exe所在的地址!,如果不一致会出现安装失败! 进入命令行窗口2 接下来,安装yolov5依赖,我这里是去了Ultralytics官网找到了yolov5的requirements文件,这个文件是每个yolo模型都需要的,里面包含了该模型的依赖库。也可以使用我下面的代码来安装。

在命令行后面输入下面内容后敲回车。(直接复制粘贴进去)

.\\python.exe -m pip install numpy==1.21.6 opencv-python onnxruntime==1.14.1 -i https://mirrors.aliyun.com/pypi/simple/ –trusted-host mirrors.aliyun.com

2.2 验证环境

安装完毕后在命令行中输入。(依旧复制粘贴)

.\\python.exe -c "import numpy, cv2, onnxruntime;print('numpy:',numpy.__version__);print('opencv:',cv2.__version__);print('onnxruntime:',onnxruntime.__version__)"

如果打印出的日志显示 numpy: 1.21.6 opencv: 5.0.0 onnxruntime: 1.14.1 则证明环境安装成功!


或者在python脚本中验证。 在python脚本中验证第三方库 代码:

import sys
import numpy
import cv2
import onnxruntime
from ioHelper import *

def Process(data) > int:
moduleVar = IoHelper(data, INIT_MODULE_VAR)
globalVar = IoHelper(data, INIT_GLOBAL_VAR)
localVar = IoHelper(data, INIT_LOCAL_VAR)
try:
PrintMsg("numpy: %s" % numpy.__version__)
PrintMsg("cv2: %s" % cv2.__version__)
PrintMsg("onnxruntime: %s" % onnxruntime.__version__)
except BaseException as e:
PrintMsg("FAIL " + str(e))
return 0

如果看到能够打印出版本号说明已经成功安装!

三、在Python脚本模块中导入YOLO模型

海康VM6200支持通过「Python脚本」模块调用外部Python代码。下面演示如何在VM中加载YOLOv5模型并进行推理。

3.1 准备onnx文件

我这里拿官方权重来做示例。去github官方权重下载链接yolov5s.pt下载完成后将pt模型文件转换成onnx格式。转换onnx格式需要依赖yolov5源码,这里github链接yolov5源码我这里下载的是7.0版本。文件不大,就80多M。下载完毕后,配置虚拟环境和依赖不用多说了吧。网上有很多教程。上面环境等一切就绪后,在程序中的export.py程序中,进行onnx格式导出。

python export.py weights yolov5s.pt include onnx imgsz 640 opset 12

这里我没有试过能否通过Ultralytics库进行转换,网上搜索到的教程yolov5必须使用export.py程序转换,大家可以自行测试。

3.2 编写推理脚本

在海康VM的「Python脚本」模块中,编写如下代码:

# coding: utf-8
import sys, time
import numpy as np
import cv2
import onnxruntime as ort
from ioHelper import *

# ====== 配置 ======
MODEL_PATH = "放你onnx格式文件的绝对路径"
INPUT_SIZE = 640 # 与onnx格式的图片尺寸一致!
CONF_THRESHOLD = 0.25
NMS_THRESHOLD = 0.45
PROVIDER = "cpu" # cpu / openvino / dml / cuda
THREADS = 4 # CPU线程数,0=自动
USE_CLASS_COLORS = True
CLASS_NAMES = [
"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck",
"boat", "traffic light", "fire hydrant", "stop sign", "parking meter", "bench",
"bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra",
"giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
"skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove",
"skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup",
"fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich", "orange",
"broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
"potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse",
"remote", "keyboard", "cell phone", "microwave", "oven", "toaster", "sink",
"refrigerator", "book", "clock", "vase", "scissors", "teddy bear", "hair drier",
"toothbrush"
]
# ==================

_sess = None
_input_name = None
_output_name = None

def _load_model():
global _sess, _input_name, _output_name
if _sess is None:
so = ort.SessionOptions()
so.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
if THREADS > 0:
so.intra_op_num_threads = THREADS
prov_map = {
"cpu": ["CPUExecutionProvider"],
"openvino": ["OpenVINOExecutionProvider", "CPUExecutionProvider"],
"dml": ["DmlExecutionProvider", "CPUExecutionProvider"],
"cuda": ["CUDAExecutionProvider", "CPUExecutionProvider"],
}
_sess = ort.InferenceSession(
MODEL_PATH, sess_options=so,
providers=prov_map.get(PROVIDER, ["CPUExecutionProvider"]))
_input_name = _sess.get_inputs()[0].name
_output_name = _sess.get_outputs()[0].name
PrintMsg("[YOLO] providers: %s" % str(_sess.get_providers()))

def _image_to_numpy(img_data):
h = int(img_data.height)
w = int(img_data.width)
buf = img_data.buffer
n = int(img_data.dataLen) if img_data.dataLen else len(buf)
arr = np.frombuffer(buf, dtype=np.uint8)
if n == w * h:
return cv2.cvtColor(arr.reshape(h, w), cv2.COLOR_GRAY2BGR), True
elif n == w * h * 3:
return cv2.cvtColor(arr.reshape(h, w, 3), cv2.COLOR_RGB2BGR), False
return None, False

def _preprocess(img_bgr):
h, w = img_bgr.shape[:2]
r = min(INPUT_SIZE / w, INPUT_SIZE / h)
nw, nh = int(round(w * r)), int(round(h * r))
resized = cv2.resize(img_bgr, (nw, nh), interpolation=cv2.INTER_LINEAR)
canvas = np.full((INPUT_SIZE, INPUT_SIZE, 3), 114, dtype=np.uint8)
dw, dh = (INPUT_SIZE nw) // 2, (INPUT_SIZE nh) // 2
canvas[dh:dh + nh, dw:dw + nw] = resized
rgb = cv2.cvtColor(canvas, cv2.COLOR_BGR2RGB)
blob = rgb.astype(np.float32) / 255.0
blob = blob.transpose(2, 0, 1)[None, ...]
return np.ascontiguousarray(blob), r, (dw, dh)

def _postprocess(outputs, r, dw, dh):
"""向量化后处理"""
preds = outputs[0][0]
mask = preds[:, 4] >= CONF_THRESHOLD
preds = preds[mask]
if len(preds) == 0:
return []
cls_id = np.argmax(preds[:, 5:], axis=1)
cls_conf = preds[np.arange(len(preds)), 5 + cls_id]
conf = preds[:, 4] * cls_conf
keep = conf >= CONF_THRESHOLD
preds, cls_id, conf = preds[keep], cls_id[keep], conf[keep]
if len(preds) == 0:
return []
boxes = np.column_stack([
preds[:, 0] preds[:, 2] / 2,
preds[:, 1] preds[:, 3] / 2,
preds[:, 2], preds[:, 3]])
idx = cv2.dnn.NMSBoxes(
boxes.tolist(), conf.tolist(), CONF_THRESHOLD, NMS_THRESHOLD)
results = []
for i in idx:
i = int(i)
x, y, bw, bh = boxes[i]
results.append((int(cls_id[i]), float(conf[i]),
(x dw) / r, (y dh) / r, bw / r, bh / r))
return results

def _class_color(cid):
hexs = ('FF3838', 'FF9D97', 'FF701F', 'FFB21D', 'CFD231',
'48F90A', '92CC17', '3DDB86', '1A9334', '00D4BB',
'2C99A8', '00C2FF', '344593', '6473FF', '0018EC',
'8438FF', '520085', 'CB38FF', 'FF95C8', 'FF37C7')
h = hexs[cid % len(hexs)]
return (int(h[4:6], 16), int(h[2:4], 16), int(h[0:2], 16))

def _draw_boxes(img_bgr, dets):
lw = max(round(sum(img_bgr.shape) / 2 * 0.003), 2)
sf = lw / 3
tf = max(lw 1, 1)
for cid, conf, x, y, bw, bh in dets:
p1 = (int(x), int(y))
p2 = (int(x + bw), int(y + bh))
color = _class_color(cid) if USE_CLASS_COLORS else (128, 128, 128)
cv2.rectangle(img_bgr, p1, p2, color, thickness=lw, lineType=cv2.LINE_AA)
name = CLASS_NAMES[cid] if cid < len(CLASS_NAMES) else str(cid)
label = "%s %.2f" % (name, conf)
w, h = cv2.getTextSize(label, 0, fontScale=sf, thickness=tf)[0]
outside = p1[1] h >= 3
cv2.rectangle(img_bgr, p1, (p1[0] + w, p1[1] h 3 if outside else p1[1] + h + 3),
color, 1, cv2.LINE_AA)
cv2.putText(img_bgr, label, (p1[0], p1[1] 2 if outside else p1[1] + h + 2),
0, sf, (255, 255, 255), thickness=tf, lineType=cv2.LINE_AA)
return img_bgr

def Process(data) > int:
moduleVar = IoHelper(data, INIT_MODULE_VAR)
globalVar = IoHelper(data, INIT_GLOBAL_VAR)
localVar = IoHelper(data, INIT_LOCAL_VAR)
try:
_load_model()
t0 = time.time()

img_data = moduleVar.in0
img_bgr, is_gray = _image_to_numpy(img_data)
t1 = time.time()

blob, r, (dw, dh) = _preprocess(img_bgr)
t2 = time.time()

outputs = _sess.run([_output_name], {_input_name: blob})
t3 = time.time()

dets = _postprocess(outputs, r, dw, dh)
t4 = time.time()

parts = []
coords = []
for cid, conf, x, y, bw, bh in dets:
name = CLASS_NAMES[cid] if cid < len(CLASS_NAMES) else str(cid)
parts.append("%s,%.2f,%.1f,%.1f,%.1f,%.1f" % (name, conf, x, y, bw, bh))
coords.extend([float(x), float(y), float(bw), float(bh), float(conf)])
moduleVar.out0 = "\\n".join(parts) if parts else "NONE"
try:
moduleVar.out1 = coords
except BaseException:
pass
PrintMsg("[YOLO] detect %d objects:\\n%s" % (len(dets), moduleVar.out0))

img_drawn = _draw_boxes(img_bgr.copy(), dets)
out_img = ImageData()
out_img.width = img_bgr.shape[1]
out_img.height = img_bgr.shape[0]
out_img.pixel_format = img_data.pixel_format
if is_gray:
out_img.buffer = cv2.cvtColor(img_drawn, cv2.COLOR_BGR2GRAY).tobytes()
else:
out_img.buffer = cv2.cvtColor(img_drawn, cv2.COLOR_BGR2RGB).tobytes()
out_img.dataLen = len(out_img.buffer)
moduleVar.out2 = out_img

PrintMsg("[time] conv=%.1fms pre=%.1fms infer=%.1fms post=%.1fms total=%.1fms" % (
(t1 t0) * 1000, (t2 t1) * 1000, (t3 t2) * 1000,
(t4 t3) * 1000, (t4 t0) * 1000))
except BaseException as e:
PrintMsg("[YOLO] error: " + str(e))
return 1
return 0

成功后,可以拿yolo官方自带的图片进行测试,如果能够成功调用,会打印出检测信息。左侧的输入输出与我保持一致!测试模型是否能够成功调用 成功展示! 推理展示

这里的耗时80多ms是在没有使用openvino和CUDA加速的情况下。加速后推理速度会更快。

希望本文能帮助你在海康VM6200上顺利跑通YOLOv5深度学习功能。如有问题,欢迎在评论区交流讨论。

赞(0)
未经允许不得转载:171主机测评 » 海康VM6200实现深度推理功能:Python脚本调用YOLO模型
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址