任务目标:使用别人训练好的权重文件,使用yolov8+pyside2,用pyinstaller打包在界面上实现目标检测,计算出框数和目标
由于理解不深刻,外加只负责部署,不负责训练,在打包上遇到巨多问题。实现效果希望打算如图所示:
第一次打包思路如上图所示,上图是个错误示范(代码里面标的people,懒得改了),希望用别人训练好的pt权重文件进行pyinstaller打包,打包时间非常长,打包出来的文件高达3个G,程序一直在转,最开始还认为pyinstaller坏了。打包出来的exe文件在cmd运行,始终找不到_internal\\ultralytics\\cfg\\default.yaml。不管重装环境还是在Linux上都出现了这个问题。
在大量的尝试无果的情况下,发现了很多人部署时使用了onnx模型,pt权重文件转换为onnx模型,python转换代码很简单,这里不赘述了。这里遇到的大坑是在自己电脑上直接使用pt转onnx,终端直接开始训练(图都没有,训练个鬼,别人的pt文件)。pt转onnx始终不成功。(解决:在跑出pt文件的电脑上pt转onnx,几下就跑完了)。
拿到训练好的onnx文件,使用onnxruntime跑出来是一个5*8400的数组,这和pt文件在预测跑出来的resault.boses里面拿数据这种方式完全不同,刚开始对整个数组一头雾水。有的人跑出来是9*8400,有的跑出来80*8400,这个是由于训练时配置文件决定的,比如决定对“手“、”头“、“脚”3个目标进行检测,那么得到的数组就是(4+3)*8400,前面的4代表xywh(中心坐标xy,w宽,h高),后面的是置信度(通俗说就是概率,比如后三位是[0.8、0.9、0.5],对应便是手的概率0.8,头的概率0.9,脚的概率0.5,一般跑出来n多趋近于0,自己根据需要来提取),8400和选择的训练模型有关。
在进行目标标框时,发现框对不上,最后发现问题,训练运用模型是640*640,将图片缩小到640*640,框就对上了。
总结:
1.使用pyinstaller打包实现目标检测,不要直接使用pt文件,让训练员在训练的地方将pt文件转换为onnx文件,对onnx打包。可以显著降低包的大小。
2.onnx跑出来的数组需要自己进行处理,根据需要自行调试。(主要是数据类型,转置,内容提取的问题)。
3.标框时,根据自己的图片大小和模型,将结果图自行处理(主要是图片缩放的问题)。
附上简单的onnx测试代码:
模型输出是(1 5 8400)图片输出为640*640(没对框进行处理),标框上标person+置信度:
import cv2 import numpy as np import onnxruntime def prepare_input(bgr_image, width, height): image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB) image = cv2.resize(image, (width, height)).astype(np.float32) image = image / 255.0 image = np.transpose(image, (2, 0, 1)) input_tensor = np.expand_dims(image, axis=0) return input_tensor image_path = "2.jpg" onnx_model_path = 'best.onnx' session = onnxruntime.InferenceSession(onnx_model_path) image = cv2.imread(image_path) image_height, image_width, _ = image.shape input_tensor = prepare_input(image, 640, 640) outputs = session.run(None, {session.get_inputs()[0].name: input_tensor}) output = np.squeeze(outputs[0]) a = output.T print(a) last_column = a[:, -1] # 找到大于0.7的索引 condition = last_column > 0.7 # 大于0.7的行 result_rows = a[condition] # 大于0.7的值的数量 count = np.sum(condition) # 打印大于0.7的行和数量 print("大于0.7的行:", result_rows) print("大于0.7的数量:", count) boxes = result_rows.tolist() # 读取图片 image = cv2.imread(image_path) # 将 "your_image_path.jpg" 替换为您自己的图片路径 image = cv2.resize(image, (640, 640)) # 在图像上绘制边界框和标签 for box in boxes: x, y, w, h, confidence = box # 计算边界框的左上角和右下角坐标 x1 = int(x - w/2) y1 = int(y - h/2) x2 = int(x + w/2) y2 = int(y + h/2) # 绘制边界框 cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2) # 添加标签文字 label = f"person {confidence:.2f}" cv2.putText(image, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2) cv2.imshow("Image with Bounding Boxes", image) cv2.waitKey(0) cv2.destroyAllWindows()
希望这篇文章对你的移植部署有所帮助.