社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

ONNXRUNTIME | Faster-RCNN ONNX模型在C++与Python推理不一致原因找到了

OpenCV学堂 • 4 年前 • 637 次点击  

点击上方↑↑↑OpenCV学堂”关注我

onnxruntime 推理python与c++支持

现象

最近用torchvision中的Faster-RCNN训练了一个自定义无人机跟鸟类检测器,然后导出ONNX格式,Python下面运行效果良好!显示如下:


然后我就想把这个ONNXRUNTIME部署成C++版本的,我先测试了torchvision的预训练模型Faster-RCNN转行为ONNX格式。然后针对测试图像,代码与测试效果如下:


transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])

sess_options = ort.SessionOptions()
# Below is for optimizing performance
sess_options.intra_op_num_threads = 24
# sess_options.execution_mode = ort.ExecutionMode.ORT_PARALLEL
sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
ort_session = ort.InferenceSession("faster_rcnn.onnx", sess_options=sess_options)
src = cv.imread("D:/images/cars.jpg")
image = cv.cvtColor(src, cv.COLOR_BGR2RGB)
blob = transform(image)
c, h, w = blob.shape
input_x = blob.view(1, c, h, w)
def  to_numpy(tensor):
    return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy()

# compute ONNX Runtime output prediction
ort_inputs = {ort_session.get_inputs()[0].name: to_numpy(input_x)}
ort_outs = ort_session.run(None, ort_inputs)
boxes = ort_outs[0# boxes
labels = ort_outs[1# labels
scores = ort_outs[2# scores
print(boxes.shape, boxes.dtype, labels.shape, labels.dtype, scores.shape, scores.dtype)

index = 0
for x1, y1, x2, y2 in boxes:
    if scores[index] > 0.5:
        cv.rectangle(src, (np.int32(x1), np.int32(y1)),
                     (np.int32(x2), np.int32(y2)), (0255255), 180)
        label_id = labels[index]
        label_txt = coco_names[str(label_id)]
        cv.putText(src, label_txt, (np.int32(x1), np.int32(y1)), cv.FONT_HERSHEY_PLAIN, 1.0, (00255), 1)
    index += 1
cv.imshow("Faster-RCNN Detection Demo", src)
cv.waitKey(0)
cv.destroyAllWindows()

运行结果如下:


然后我把python代码转行为C++的代码,运行结果如下:

发现很多类型都变成 background类型 了,就是类型预测错误了!C++与Python推理使用的label-map文件完全一致,我晕了!

原因与修改

我仔细核对了两边预测输出三个层分别是boxes、labels、scores、解析顺序都没有错!然后我把python中输出三个层数据类型打印出来如下:

print(boxes.shape, boxes.dtype, labels.shape, labels.dtype, scores.shape, scores.dtype)

输出打印结果如下:

(100, 4) float32 (100,) int64 (100,) float32

可以证明:

Boxes 数据类型是浮点数Labels数据类型是int64scores数据类型是浮点数

而我在ONNXRUNTIME C++获取输出的语句如下:

const int* labels_prob = ort_outputs[1].GetTensorMutableData(); // labelscv::Mat det_labels(boxes_shape[0], 1, CV_32S, (int*)labels_prob);

直接用 int类型而不是int64 获取labels数据了,我立刻意识到是因为数据类型不一致导致的内存错误,我知道OpenCV中有个数据类型是int64,于是我把第一行代码改成:

const int64* labels_prob = ort_outputs[1].GetTensorMutableData();

发现OpenCV Mat没有支持int64的,无法创建这样的Mat对象!

所以我放弃了,直接读取数组,代码如下:

int64 classId = labels_prob[i];std::cout<< "class id: " << classId << std::endl;

就这样,再次运行演示程序,发现结果跟python版本的完全一致!

就这样我又改好了一个bug!


总结:

模型推理时刻注意C++的中数据类型问题!

最后show一下我的成果:


扫码查看OpenCV+Pytorch系统化学习路线图


 推荐阅读 

CV全栈开发者说 - 从传统算法到深度学习怎么修炼

2022入坑深度学习,我选择Pytorch框架!

Pytorch轻松实现经典视觉任务

教程推荐 | Pytorch框架CV开发-从入门到实战

OpenCV4 C++学习 必备基础语法知识三

OpenCV4 C++学习 必备基础语法知识二

OpenCV4.5.4 人脸检测+五点landmark新功能测试

OpenCV4.5.4人脸识别详解与代码演示

OpenCV二值图象分析之Blob分析找圆

OpenCV4.5.x DNN + YOLOv5 C++推理

OpenCV4.5.4 直接支持YOLOv5 6.1版本模型推理



Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/131505