OPENCV中图像数据结构及其转化
1. IplImage
它是openCV库中表示图像的结构体。
初始化:
cvLoadImage(),cvCreateImage()
访问元素:【行指针】
b = ((uchar *)(img->imageData + row * img->widthStep))[col * img->nChannels + 0];
a. IplImage*转Mat
Mat mtx= cvarrToMat(img);
b. IplImage*转CvMat
①CvMat matheader;
CvMat * mat = cvGetMat(img, &matheader);
②CvMat * mat = cvCreateMat(img->height, img->width, CV_64FC3);
cvConvert(img, mat);
c. IplImage*转BYTE*
IplImage* img0 = cvLoadImage("1.bmp");
BYTE* pDst = (unsigned char*)img0->imageData;
2. CvMat
cvCreateMat(),cvInitMatHeader()
CvMat -> Mat
Mat::Mat(const CvMat* m, bool copyData=false); /*类似IplImage -> Mat,可选择是否复制数据*/
CvMat-> IplImage
IplImage* img = cvCreateImage(cvGetSize(mat),8,1);
cvGetImage(matI,img);
3. Mat
矩阵头+指向像素数据的指针。计算时,可以把CvMat 或 IplImage 浅拷贝为 cv::Mat , 然后计算, 计算完再转回CvMat 或 IplImage,可大大提高运算效率.
Mat mat = imread(const String* filename); 读取图像
imshow(const string frameName, InputArray mat); 显示图像
imwrite (const string& filename, InputArray img); 储存图像
【均是直接转成目标类型】
Mat -> IplImage
Mat M
= M; /*只创建图像头,不复制数据*/
Mat -> CvMat
例子(假设Mat类型的imgMat图像数据存在):
CvMat cvMat = imgMat;/*Mat -> CvMat, 类似转换到IplImage,不复制数据只创建矩阵头
关系
Mat类型侧重于计算,能够更加方便的进行内存管理,不再需要程序员手动管理内存的释放,能处理多维数据。
CvMat和IplImage类型更侧重于“图像”。CvArr -> CvMat -> IplImage. CvArr用作函数的参数,无论传入的是CvMat或IplImage,内部都是按CvMat处理。
IplImage内部buffer每行是按4字节对齐的,CvMat没有这个限制
我们看到很多函数的参数是InputArray, 而调用的时候传入的是cv::Mat对象
4. BYTE*转IplImage*
已知BYTE* pDst;
IplImage* img;
img = cvCreateImageHeader(cvSize(img0->width, img0->height), IPL_DEPTH_8U, img0->nChannels);
cvSetData(img, pDst, img0->widthStep);
参考:
https://www.cnblogs.com/summerRQ/articles/2406109.html
http://blog.sina.com.cn/s/blog_afe2af380101bgyn.html
http://blog.csdn.net/bagboy_taobao_com/article/details/47048249
加载图像与释放
cvLoadImage
每次都会开辟一块新的内存,如果不释放,就会导致内存泄露
1.释放 cvReleaseImage( &src ); src=NULL;
2. 使用CvvImage类代替 【覆盖,只需程序结束时释放】
CvvImage pSrcImg;
IplImag *pSrcImgCopy ; //使用IplImag变量做个拷贝。毕竟IplImag 类处理方便。
pSrcImgCopy = cvCreateImage(cvSize(IMGWIDHT,IMGHEIGHT),IPL_DEPTH_8U, 3);// 要正确释放pSrcImgCopy 时,声明时必须create
//获取图像:
pSrcImg.Load(str); //str为Cstring类型的图像文件名
pSrcImgCopy = pSrcImg.GetImage(); //拷贝出pSrcImg的图像数据。
//释放内存
cvReleaseImage(&pSrcImgCopy );
pSrcImg.Destroy();
cvCloneImage
每次拷贝是制作图像的完整拷贝包括头、ROI和数据。不会覆盖以前的内容。每次使用时编译器会分配内存空间。
1.直接使用
IplImag *img = cvCloneImage(frame);
2.先释放再使用
IplImag *img = cvCreateImage( cvSize(frame->width,frame->hight), frame->depth, frame->nChannels );
cvReleaseImage(&img);
img = cvCloneImage(frame);
3. 使用cvCopy函数代替
IplImag *img = cvCreateImage( cvSize(frame->width,frame->hight), frame->depth, frame->nChannels );
cvCopy(frame,img,NULL);
cvCloneImage与cvCloneMat: 在赋值的同时会开辟一个新的空间给定义的变量,只适合用于变量开始定义,千万不要用在算法处理中间,否则会产生一个新的地址空间,会将赋值对象的指针地址改变,这样会导致整个程序有不可预测的错误发生
cvCopyImage与cvCopyMat: 只复制值,并不会分配一个空间给赋值对象。建议在程序中间进行复制时使用。
cvGetCols()、cvGetRows()同理
1.CvMat *srcMat = cvCreateMat(width, height, CV_8UC3); // 创建一个三通道无符号整数类型的矩阵
cvReleaseData(srcMat); // 先释放目标矩阵的数据区
cvGetCols(frame,srcMat,0,width);
2.cvCreateMatHeader(width, height, CV_8UC3);
cvGetCols(frame,srcMat,0,width);
IplImag*、CvMat*、CvHistogram* 等结构体指针在使用后要释放
IplImage *frame= cvCreateImage(cvSize(width,height),8,1);
CvMat *srcMat = cvCreateMat(width, height, CV_8U);
CvHistogram *hist = cvCreateHist(1,&histSize,CV_HIST_ARRAY,ranges,1);
......
cvReleaseMat(&srcMat);
cvReleaseImage(&frame);
cvReleaseHist(&hist);
参考:
http://blog.sina.com.cn/s/blog_51c1ed0501011g0c.html
http://blog.csdn.net/shangyaowei/article/details/17424507