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

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

opencv的Mat结构里需要注意的细节_第1张图片

但是最后看程序运行的可视化结果,是没问题的。这个疑惑,在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);

之所以需要消除维数是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的维度。

你可能感兴趣的:(人工智能,计算机视觉,opencv)