OpenCV实现Mat与vector,Mat与数组互转
OpenCV实现Mat与vector互转
【尊重原创,转载请注明出处】https://blog.csdn.net/guyuealian/article/details/80253066
1、Mat与vector互转
下面是鄙人实现的Mat与vector互转的方法,需要注意的是vector转Mat时,使用reshape()后,必须clone()一份,否则返回的结果出错,关于这方面的原因,可以参考鄙人的博客:https://blog.csdn.net/guyuealian/article/details/80252853
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
/***************** Mat转vector **********************/
template<typename _Tp>
vector<_Tp> convertMat2Vector(const Mat &mat)
{
return (vector<_Tp>)(mat.reshape(1, 1));//通道数不变,按行转为一行
}
/****************** vector转Mat *********************/
template<typename _Tp>
cv::Mat convertVector2Mat(vector<_Tp> v, int channels, int rows)
{
cv::Mat mat = cv::Mat(v);//将vector变成单列的mat
cv::Mat dest = mat.reshape(channels, rows).clone();//PS:必须clone()一份,否则返回出错
return dest;
}
int main()
{
/* char ->CV_8SC
* unsigned char,uchar ->CV_8UC
* unsigned short int,ushort->CV_16UC
* short int->CV_16SC
* int ->CV_32SC
* float ->CV_32FC
* double->CV_64FC
*/
uchar arr[4][3] = { { 1, 1,1 },{ 2, 2,2 },{ 3, 3,3 },{ 4,4, 4 } };
cv::Mat srcData(4, 3, CV_8UC1, arr);
cout << "srcData=\n" << srcData << endl;
vector<uchar> v = convertMat2Vector<uchar>(srcData);
cv::Mat dest = convertVector2Mat<uchar>(v, 1, 4);//把数据转为1通道,4行的Mat数据
cout << "dest=\n" << dest << endl;
system("pause");
waitKey();
return 0;
}
运行结果:
srcData=
[ 1, 1, 1;
2, 2, 2;
3, 3, 3;
4, 4, 4]
dest=
[ 1, 1, 1;
2, 2, 2;
3, 3, 3;
4, 4, 4]
2、Mat与数组互转
利用Mat来存储数据,避免使用数组等操作
cv::Mat mean = (cv::Mat_<float>(2, 1) << 0.4404, 0.3111);
cout << "mean=" << mean << endl;
float a=mean.at<float>(0, 0);
float b = mean.at<float>(0, 0);
将数组内容传递给Mat,示例代码:
unsigned char cbuf[height][width];
cv::Mat img(height, width, CV_8UC1, (unsigned char*)cbuf);
将Mat中的内容传递给数组,如果Mat中的数据是连续的,那么对于传递到一维vector我们可以这样:
std::vector<uchar> array(mat.rows*mat.cols);
if (mat.isContinuous())
array = mat.data;
同样的,传递到一维数组我们可以这样
unsigned char *array=new unsigned char[mat.rows*mat.cols];
if (mat.isContinuous())
array = mat.data;
对于二维vector的传值,我们可以这样处理
uchar **array = new uchar*[mat.rows];
for (int i=0; i<mat.rows; ++i)
array[i] = new uchar[mat.cols];
for (int i=0; i<mat.rows; ++i)
array[i] = mat.ptr<uchar>(i);
RGB图与数组转换(3维矩阵)
BYTE* iPtr = new BYTE [height*width*3];
for(int i=0;i<height;i++)
{
for(int j=0;j<width;j++)
{
for(int k=0;k<3;k++)
{
iPtr[i*width*3+j*3+k] = img.at<Vec3b>(i,j)[k];
}
}
}
其中,img是一个3维uchar的Mat,Vec3b代表3个uchar,对于灰度图、4维矩阵等,只要把通道数和at的数据类型改一下就可以套用以上格式。还有一点千万注意,Mat的(i,j)是按(行,列)的规则,而图像中则是(高,宽),跟Size(x,y),Rect(x,y)的(x,y)是不同的
4字节对齐的情况
http://lib.csdn.net/article/opencv/24030
但如果图像大小不是4的整数倍,某些场合下不能直接使用Mat::data。因为图像在OpenCV里的存储机制问题,行与行之间可能有空白单元(一般是补够4的倍数或8的倍数,称为padding。这些空白单元对图像来说是没有意思的,只是为了在某些架构上能够更有效率,比如intel MMX可以更有效的处理那种个数是4或8倍数的行。Mat提供了一个检测图像是否连续的函数isContinuous()。当图像连通时,我们就可以把图像完全展开,看成是一行。此时调用Mat::ptr<>()方法就等价于Mat::data:
int nr=image.rows;
int nc=image.cols;
if(image.isContinuous())
{
nr=1;
nc=nc*image.rows*image.channels();
}
for(int i=0;i<nr;i++)
{
const uchar* inData=image.ptr<uchar>(i);
uchar* outData=outImage.ptr<uchar>(i);
for(int j=0;j<nc;j++)
{
*outData++=*inData++;
}
}
例如保存BMP格式的图像时,BMP要求图像数据按四字节对齐,此时就需要对Mat中的数据进行补零
对齐方法就是在每一行尾部补零,零的个数可能是1~3个
相关文章
- OpenCV图像处理篇之边缘检測算子
- OpenCV的图像直角坐标系转极坐标系的函数warpPolar()详解,并附自己写的实现直角坐标系转极坐标系的MATLAB代码
- 利用OpenCV的仿射变换函数warpAffine()实现图像的亚像素级平移
- 详解OpenCV的窗口滑动条创建控制函数createTrackbar()
- 详解OpenCV的窗口创建函数namedWindow()
- 运动目标的背景建模-混合高斯背景建模和KNN模型建模的OpenCV代码实现
- 边缘检测算子Canny原理概述并利用OpenCV的库函数Canny()对图像进行边缘检测
- 基于OpenCV的图像编解码实践
- Ubuntu 16.04 python和OpenCV安装
- OpenCV Mat遍历的方法
- Dlib学习笔记:dlib array2d与 OpenCV Mat互转
- Ubuntu18.04下OpenCV调用笔记本摄像头
- Android Opencv 之 Android Studio 进行 opencv ( 4.2.0) 环境搭建,并简单进行图片灰度处理demo
- Opencv学习笔记(六)SURF学习笔记
- OpenCV Open Camera 打开摄像头
- OpenCV 2.4.11 VS2010 Configuration
- (原)opencv中使用限制对比度自适应直方图均衡CLAHE