0


Opencv 基本操作四 指针数组、vector与Mat之间的相互转换

在深度学习模型部署中通常存在读取图像为mat,然后将mat转换为float指针传入模型的操作。为了快捷开发,因此对指针数组、vector与Mat之间的相互转换进行整理。实现了指针数组、vector之间的相互转换;vector与Mat之间的相互转换(含单通道图像和多通道图像)。vector转mat主要应用在语义分割结果的处理中。

1、指针数组与vector之间的相互转换

这里强调一下为什么使用vector而不使用指针数组,因为使用vector可以更为方便的操作数据,就比如说数据的拷贝,裁剪、拼接等。就比如,博主的代码实现了vector的加法重载,可以便捷的实现vector的拼接。

指针转vector

std::vector vp(p, p + 1000);,其中p为指针的名称,1000为指针的数据长度

vector转指针

int* p2 = vp.data();//浅拷贝(p2与vp共用同一片内存区域)

//重载vector的运算符template<typenameT>
vector<T>&operator+(vector<T>& v1, vector<T>& v2){
    v1.insert(v1.end(), v2.begin(), v2.end());return v1;}//指针数组转vectorint* p =newint[100];//空间分配方式一
p =(int*)malloc(1000*sizeof(p));//空间分配方式二:malloc赋值方式
p[0]=-1;

std::vector<int>vp(p, p +1000);//深拷贝(把起始地址到结束地址的值拷贝一遍)
vp[1]=222;//-------实现vector的拼接--------
std::vector<int> vp2 = vp + vp;//vecort转指针数组int* p2 = vp.data();//浅拷贝(p2与vp共用同一片内存区域)
p2[2]=3333;
std::cout <<"int* p: "<< p[0]<<", "<< p[1]<<", "<< p[2]<< std::endl;
std::cout <<"vector vp: "<< vp[0]<<", "<< vp[1]<<", "<< vp[2]<< std::endl;
std::cout <<"int* p2: "<< p2[0]<<", "<< p2[1]<<", "<< p2[2]<< std::endl;

在指针与数组的相互转换过程中需要注意的是内存空间的变化,指针转vector后数据被拷贝了一次,而vector转指针后数据并没有被拷贝。具体可以见上述代码的输出,改变vp不会影响p,而改变p2会影响vp
在这里插入图片描述

vector的类型转换

有的时候需要转换vector的数据类型,可以使用以下方法

std::vector<int64> output_data0;//对应seg结果  argmax后为int64
std::vector<uchar>int2uchar(output_data0.begin(), output_data0.end());

2、mat转vector

通常来说mat转vector是十分便捷的,仅需要一个reshape操作即可,reshape(int cn, int rows)表示把数据的通道变为cn,行数变为rows。具体如下所示,下面代码表示把单通道mat转换为vector。

std::vector<float> vec = mat.reshape(1,1);

然而,对于三通道的mat转换略为麻烦,需要将多通道split为三个单通道才行,具体实现的转换函数如下所示。

std::vector<float>mat2vector(cv::Mat img, cv::Size2d size ={512,512}){
    cv::resize(img, img, size);
    cv::cvtColor(img, img, cv::COLOR_BGR2RGB);
    img.convertTo(img, CV_32FC3);//数据归一化
    img = img /255.0;//将rgb数据分离为单通道
    std::vector<cv::Mat> mv;
    cv::split(img, mv);
    std::vector<float> R = mv[0].reshape(1,1);
    std::vector<float> G = mv[1].reshape(1,1);
    std::vector<float> B = mv[2].reshape(1,1);//RGB数据合并
    std::vector<float> input_data;
    input_data.insert(input_data.end(), R.begin(), R.end());
    input_data.insert(input_data.end(), G.begin(), G.end());
    input_data.insert(input_data.end(), B.begin(), B.end());return input_data;}

3、vector转mat

在深度学习部署场景中,vector转mat分三种情况,情况一:uchar形式的vector转单通道mat;情况二:float形式的vector转单通道mat;情况三:float形式的vector转三通道mat。

vector<uchar>转单通道mat

如果是std::vector<int64>则需要转换为std::vector<uchar>才行,在深度学习中argmax后返回的数据类型通常是int64的。

//语义分割结果转mat
cv::Mat vector2mat(std::vector<uchar> output, cv::Size2d size ={512,512}){
    cv::Mat out_result(size.height, size.width, CV_8UC1, cv::Scalar(0));
    out_result.data = output.data();return out_result;}

vector<float>转单通道mat

因为mat.data 是uchar型的指针,所有vector<float>不能像vector<uchar>那样进行赋值操作,但其有两种赋值方式,分别是memcpy和mat.assign

cv::Mat vector2mat(std::vector<float> output, cv::Size2d size ={512,512}){
    cv::Mat out_result(size.height, size.width, CV_32FC1, cv::Scalar(0));memcpy(out_result.data, output.data(), output.size()*sizeof(float));//output.assign((float*)out_result.datastart, (float*)out_result.dataend);return out_result;}

vector<float>转三通道mat

这里通过调用上一步实现的函数,实现目标功能,所转换的mat为bgr格式。

//将CHW格式的数据转换为bgr格式的mat
cv::Mat cwhfloat2mat(std::vector<float> output, cv::Size2d size ={512,512}){
    cv::Mat out_result;int dis = size.height * size.width;//将数据进行切片
    vector<float> r{&output[0],&output[0]+ dis };
    vector<float> g{&output[0]+ dis,&output[0]+2* dis };
    vector<float> b{&output[0]+2* dis,&output[0]+3* dis };

    vector<cv::Mat> mat_bgr;
    mat_bgr.push_back(vector2mat(b, size));
    mat_bgr.push_back(vector2mat(g, size));
    mat_bgr.push_back(vector2mat(r, size));
    cv::merge(mat_bgr, out_result);//out_result = out_result * 255;//out_result.convertTo(out_result, CV_8UC3);//cv::cvtColor(out_result, out_result, cv::COLOR_BGR2RGB);return out_result;}
标签: opencv c++ 人工智能

本文转载自: https://blog.csdn.net/a486259/article/details/126848868
版权归原作者 万里鹏程转瞬至 所有, 如有侵权,请联系我们删除。

“Opencv 基本操作四 指针数组、vector与Mat之间的相互转换”的评论:

还没有评论