opencv的mat openvino的tensor libtorch的tensor
opencv的mat
对于矩阵数据,在opencv里面是通过使用mat这个数据结构来实现的,我觉得这个数据结构本身设计是用来做图片的存储,所以很多的教程都是关于三维矩阵的(其中一个维度是channel),关于三维矩阵的定义、读取、写入等操作的博客也有很多。而我这次遇到的问题主要是关于不带channel的三维矩阵以及四维矩阵的一些操作。
在说具体内容之前,先说一下这个mat类型是这样的,它和矩阵数据类型相比之外,还有一个channel这个维度,所以在定义、读取、写入的时候一般需要考虑这个维度,进行相应处理。
定义
mat建立 关于mat矩阵的建立可以参考这篇文章,这里建立的时候,有几个参数需要说明一下,就是这个(CV_8UC1// 8位无符号单通道 CV_8UC3// 8位无符号3通道 等等)这些,还有很多取值,这里这个参数是可以加也可以不加的,对于图片,一般是图片,存在三个通道的问题,所以可以加,如果我们只是用mat矩阵来表示一个矩阵,而这个矩阵,只是用来存储数据,并不表示实际的图片,直接定义矩阵的维度和各个维度的大小,以及数据的类型即可。
阅读一下这张图,这是我其他博客截的,我想说明一个问题,mat类型是包含信息头和存储数据的信息体的,通常的赋值操作只能相当于c++的浅拷贝,也就是说里面的信息体还是同一块内存,对赋值前和赋值后的变量进行操作,都是对同一块内存进行操作,显然赋值前后的变量都会受到影响。要想新开辟一个内存区域的话,需要使用clone()克隆函数和copyTo()拷贝函数。具体内容可以看这篇文章 这篇博客里面还有很多关于mat的一些基本操作函数的说明。
读取和写入
mat的读取关于读取,这篇文章说的很全面了,介绍了三种方法,我也没有完全实践过,第一种通过at访问和第二种通过ptr访问我的代码中是直接用了的,可以跑的通,第二种ptr访问用于四维矩阵。高维矩阵的访问 在这篇文章里面,说明了各个维度的矩阵建议用什么方式去访问,我验证了,是可以行得通的,可以参考。
说回第一篇文章里面的东西,建议看的时候注意对于最后一个维度的处理,在这里面,如果我们的数据是图片的话,最后一个维度是channel,但是如果不是图片的话,最后一个维度或许就没有特殊的含义,就是一个维度的数据而已,这时候按照正常的维度对待即可,没有特殊的含义了,但是对最后一个维度的访问方式,还是建议按照博客中的方式,比较建议,这个应该是这里的惯例,代码中的cv::Vec3f指的是取出一个vector数组,里面有三个float类型元素,如果你的最后一个维度不止三个,那这个类型就不行了, 需要使用原始的某个类型去直接取出来。关于这几种访问方式的速度问题,暂时还没有结论。
openvino的tensor
关于openvino 这是一个推理的工具,OpenVINO是英特尔基于自身现有的硬件平台开发的一种可以加快高性能计算机视觉和深度学习视觉应用开发速度工具套件。这个工具比较好用,当然了还有tensorRT等其他大厂推出的工具。关于它的使用,有官方文档说的很好。1 2 关于它的使用,主要是现在的版本已经提供了预处理功能,不需要我们自己去写预处理那一块的代码,它自身提供了关于输入的例如通道交换、resize、数据类型转换、颜色通道顺序改变等常用功能。在文档里面搜索,也可以查到。这个极大的简化了我们代码中自己需要写的预处理函数部分。
接下来就是推理,
这个很简单,就是几行代码的事情。所以这个框架的使用还是比较简单的,安装好了,一些自带的接口用一下就好了。
libtorch的tensor
libtorch是大家熟知的pytorch的C++版本,基于这个框架可以用来实现一些C++版本的网络模型。不过还是比较麻烦的,因为有一些函数只在pytorch里面才有,并且python有很多的第三方库,c++就没有,这就导致了很多代码模块的实现起来很不方便。
关于libtorch tensor的常见操作可以参考这几篇博客:1 2 3
这是一个需要注意的不同之处。
这几篇博客,基本都说了libtorch的函数以及用法,如果还没有的,可能需要自己搜一下,或者就是libtorch就是不提供这个接口。
opencv的mat openvino的tensor libtorch的tensor的互相转换
libtorch的tensor和opencv的mat的互相转换
如果你在写C++的网络模型,很多时候我们需要借助opencv类来进行很多图像或者是矩阵的操作,因为这个类提供的接口比libtorch多,那么这就涉及到两种矩阵存储类型之间的转换了,opencv的mat结构和libtorch的tensor之间是可以转换的。但是这里需要指出的是,这里的转换不适用于存储图片的情形,存储图片的时候,前面第一节关于mat的部分也都说了,会涉及到通道这个维度,以及这个维度处于矩阵哪一维的情况,那是专门的一种转换方式。这个网上也有很多,可以自己找一找。因为我这边模型推理的时候是先转换为openvino的tensor来进行的,所以没有图片mat转libtorch tensor的情况。
如下,这个图展示的就是libtorch tensor转换为cv::mat的情况,这里的mid_output_tensor是一个libtorch的tensor.最终转换为了mid_output_Mat这个mat类型的矩阵。
如下这个代码就实现了从cv::mat转换为dist_tensor的操作。
torch::Tensor dist_tensor = torch::zeros({ B,H,W }, torch::kFloat);
int size132[3] = { B,H,W };
cv::Mat dist_mat(3, size132, CV_32FC1);
dist_tensor = torch::from_blob(dist_mat.data, { B,H,W }, torch::kFloat);
opencv的mat转换为openvino的tensor
在opencv中输入的图片是cv::mat,在推理之前,需要转换为openvino的tensor,
通过这个函数,可以把输入的imgs转换为input_tensor. 实质上是把内存中的区域给了input_tensor这个变量。
openvino的tensor转换为libtorch的tensor
当推理完了之后,输出的结果是openvino tensor,如果还有进行很多的后处理,那么openvino tensor很可能不合适,因为它自带函数很少,没有libtorch tensor自带的函数多。转换可以使用以下的方法。
get_output_tensor是获得推理输出结果的函数,参数0是第一个结果,如果就一个结果,就不需要加参数。