opencv的Mat结构里需要注意的细节

在使用opencv的dnn模块做深度学习时,经常会遇到一个疑惑。疑惑是这样的:用C++编写的程序,当执行完outs = net.forward()之后,如果outs里有Mat的维数大于2,那么设断点调试的时候,可以看到rows和cols都等于-1,以目标检测为例,输出outs里包含box和score,断点调试查看out_score的信息如下:

但是最后看程序运行的可视化结果,是没问题的。这个疑惑,在opencv源码里可以找到解释,在mat.hpp文件,第2559行至2561行,中间的注释里说:当矩阵的维数大于2时,rows和columns的值为-1

首先分析,out_score的形状,如果是基于pytorch框架做目标检测,那么它的形状是(batchsize, num_proposal, num_class)。在使用opencv的dnn模块做深度学习目标检测时,通常是输入一张图片到神经网络里做前向计算的,因此batchsize这个维度是多余的。想要避免出现rows和cols都等于-1这种情况,在生成onnx文件之前,添加对输出张量的消除batchsize维度的处理,这个在pytorch里有现成的函数squeeze()满足这个需求。假如没有添加这个步骤,那么在opencv里也有解决办法。使用opencv的reshape函数就能达到pytorch或者numpy里的squeeze()函数消除维数是1的那个维度,示例代码:  out_score = out_score.reshape(0, num_proposal);     num_proposal是二维矩阵的行数

之所以需要消除维数是1的那个维度,是因为在接下来计算每一个proposal的最大类别置信度(也就是求out_score的每一行的最大值)时,可以使用opencv提供的minMaxLoc函数来完成,而在调用这个函数之前需要提取out_score的一行,示例代码: Mat scores = out_score.row(idx).colRange(0, num_class);  这时如果out_sxcore的dims大于2,程序就会报错,因而需要在此之前消除维数是1的维度。调用opencv现成函数来求最大类别置信度,这样就不需要自己手动编写for循环了。当然,如果你自己手动编写for循环求最大类别置信度,那么前面out_score的dims是否大于2就无关紧要了,这时也就不要消除维数是1的维度。

上面讲述的是编写C++程序调用opencv的dnn模块做深度学习时的一个bug,但是编写python程序调用opencv的dnn模块做深度学习时就不会出现这个问题,因为在python程序里,当执行完outs = net.forward()之后,返回的是numpy.array这种数据结构,这是与C++程序的一个区别。

不过,在C++程序里,当Mat的dims>2时,想要访问Mat的高和宽,可以通过size属性获取,例如上面的out_score,在程序里添加   cout<<out_score.size[0]<<","<<out_score.size[1]<<","<<out_score.size[2]<<endl;

就可以打印出out_socre的维度信息了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值