然后我就想把这个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)), ( 0 , 255 , 255 ), 1 , 8 , 0 )

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 , ( 0 , 0 , 255 ), 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

可以证明:

const int * labels_prob = ort_outputs[ 1 ].GetTensorMutableData; // labels cv:: 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新功能测试

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

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

OpenCV4.5.4 直接支持YOLOv5 6.1版本模型推理 返回搜狐,查看更多

责任编辑:

声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。