当前位置:首页 >> 机械/仪表 >>

CvArr、Mat、CvMat、IplImage、BYTE转换K


CvArr、Mat、CvMat、IplImage、BYTE 转换(总结而来)
分类: OpenCv 2012-02-29 14:165388人阅读评论(2)收藏举报 byte 优化图像处理数据结构 matrixvector

一、Mat 类型:矩阵类型,Matrix。 在 openCV 中,Mat 是一个多维的密集数据数组。可以用来处理向量和矩阵、图

像、直 方图等等常见的多维数据。 Mat 有3个重要的方法: 1、Mat mat = imread(const String* filename); 读取图像 2、imshow(const string frameName, InputArray mat); 显示图像 3、imwrite (const string& filename, InputArray img); 储存图像 Mat 类型较 CvMat 与 IplImage 类型来说,有更强的矩阵运算能力,支持常见的矩阵运 算。在计算密集型的应用当中,将 CvMat 与 IplImage 类型转化为 Mat 类型将大大减少计算 时间花费。 A.Mat -> IplImage 同样只是创建图像头,而没有复制数据。 例: // 假设 Mat 类型的 imgMat 图像数据存在 IplImage pImg= IplImage(imgMat); B.Mat -> CvMat 与 IplImage 的转换类似,不复制数据,只创建矩阵头。 例: // 假设 Mat 类型的 imgMat 图像数据存在 CvMat cvMat = imgMat; 二、CvMat 类型与 IplImage 类型:“图像”类型 在 openCV 中,Mat 类型与 CvMat 和 IplImage 类型都可以代表和显示图像,但是, Mat 类型侧重于计算,数学性较高,openCV 对 Mat 类型的计算也进行了优化。而 CvMat 和 IplImage 类型更侧重于“图像”,openCV 对其中的图像操作(缩放、单通道提取、图像 阈值操作等)进行了优化。 补充:IplImage 由 CvMat 派生,而 CvMat 由 CvArr 派生即 CvArr -> CvMat -> IplImage CvArr 用作函数的参数, 无论传入的是 CvMat 或 IplImage, 内部都是按 CvMat 处理。 1.CvMat A.CvMat-> IplImage IplImage* img = cvCreateImage(cvGetSize(mat),8,1); cvGetImage(matI,img); cvSaveImage("rice1.bmp",img); B.CvMat->Mat 与 IplImage 的转换类似,可以选择是否复制数据。 Mat::Mat(const CvMat* m, bool copyData=false); 在 openCV 中,没有向量(vector)的数据结构。任何时候,但我们要表示向量时,用矩阵 数据表示即可。 但是,CvMat 类型与我们在线性代数课程上学的向量概念相比,更抽象,比如 CvMat 的元

素数据类型并不仅限于基础数据类型,比如,下面创建一个二维数据矩阵: CvMat* cvCreatMat(int rows ,int cols , int type); 这里的 type 可以是任意的预定义数据类型,比如 RGB 或者别的多通道数据。这样我们便 可以在一个 CvMat 矩阵上表示丰富多彩的图像了。 2.IplImage 在类型关系上,我们可以说 IplImage 类型继承自 CvMat 类型,当然还包括其他的变量将之 解析成图像数据。 IplImage 类型较之 CvMat 多了很多参数,比如 depth 和 nChannels。在普通的矩阵类型当 中,通常深度和通道数被同时表示,如用32位表示 RGB+Alpha.但是,在图像处理中,我们 往往将深度与通道数分开处理,这样做是 OpenCV 对图像表示的一种优化方案。 IplImage 的对图像的另一种优化是变量 origin----原点。在计算机视觉处理上,一个重要的 不便是对原点的定义不清楚,图像来源,编码格式,甚至操作系统都会对原地的选取产生影 响。为了弥补这一点,openCV 允许用户定义自己的原点设置。取值0表示原点位于图片左 上角,1表示左下角。 dataOrder 参数定义数据的格式。有 IPL_DATA_ORDER_PIXEL 和 IPL_DATA_ORDER_PLANE 两种取值,前者便是对于像素,不同的通道的数据交叉排列, 后者表示所有通道按顺序平行排列。 IplImage 类型的所有额外变量都是对“图像”的表示与计算能力的优化。 A.IplImage -> Mat IplImage* pImg = cvLoadImage("lena.jpg"); Mat img(pImg,0); // 0是不複製影像,也就是 pImg 與 img 的 data 共用同個記憶體位置, header 各自有 B.IplImage -> CvMat 法1:CvMat mathdr, *mat = cvGetMat( img, &mathdr ); 法2:CvMat *mat = cvCreateMat( img->height, img->width, CV_64FC3 ); cvConvert( img, mat ); C.IplImage*-> BYTE* BYTE* data= img->imageData; CvMat 和 IplImage 创建时的一个小区别: 1、建立矩阵时,第一个参数为行数,第二个参数为列数。 CvMat* cvCreateMat( int rows, int cols, int type ); 2、建立图像时,CvSize 第一个参数为宽度,即列数;第二个参数为高度,即行数。这 个 和 CvMat 矩阵正好相反。 IplImage* cvCreateImage(CvSize size, int depth, int channels ); CvSize cvSize( int width, int height ); IplImage 内部 buffer 每行是按4字节对齐的,CvMat 没有这个限制

补充:
A.BYTE*-> IplImage* img= cvCreateImageHeader(cvSize(width,height),depth,channels); cvSetData(img,data,step);

//首先由 cvCreateImageHeader()创建 IplImage 图像头,制定图像的尺寸,深度和通道数; //然后由 cvSetData()根据 BYTE*图像数据指针设置 IplImage 图像头的数据数据, //其中 step 指定该 IplImage 图像每行占的字节数,对于1通道的 IPL_DEPTH_8U 图像,step 可以等于 width。

IplImage*图像结构指针转换成 byte *
最近在封装 opencv 中一些标定,视觉方面的函数,接口定义为 byte*,需要将 byte*与 iplImage*相互转换。 其中遇到几个小问题,1)当 byte*转成 IplImage*时 setData()接受图像头,故需要 createImageHeader().在上篇 cvSetData()中已经说明。 2)在 IplImage*转成 Byte*时,其实就是取 IplImage*中的 imageData 数据区指针,但是要 注意几点: A:IplImage*指针存放图像有两种方式,由 originar 变量控制,0-left up 为起点,1-left down 为起点。所以要根据 origial 处理图像情况。看是否需要对图像进行倒置下。 B:IplImage*存放图像根据读人的格式不同,channel 不同。即便是8位图像可能存放成3 个通道,所以在转化时获取数据需要注意。 代码贴出来: ////////////////////////////////////////////////////////////////////////// // Name: byte2IplImg // Function: convert byte* to IplImage format. // Author: liyy // Data:2011.05.23 ////////////////////////////////////////////////////////////////////////// IplImage * CconvertImgStruct::Byte2IplImg( byte *pImg,int width,int height,int bitCount ) { if (!pImg ) { return NULL; } IplImage * pIplImg = cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,bitCount/BITCHAN) ; long lWidthByte = (width * bitCount+31)/32 *4; cvSetData(pIplImg,pImg,lWidthByte); return pIplImg;

} ////////////////////////////////////////////////////////////////////////// //Name: IplImage2Byte

//Function: convert IplImage to byte* //Author:liyy //Date: 2011.05.23 ////////////////////////////////////////////////////////////////////////// byte * CconvertImgStruct::IplImage2Byte( IplImage *IplImg ) { if (!IplImg) { return NULL; } int nHeight = IplImg->height; int nWidth =IplImg->width; int bitCount = IplImg->depth; int nChanel = IplImg->nChannels; byte *pImg = new byte[nHeight*nWidth*nChanel*sizeof(byte)]; if (IplImg->origin == 0) { //from left-down for (int i = 0; i< nHeight;i++) { for (int j = 0; j< nWidth;j++) { for (int k =0; k < nChanel;k++) { //*(pImg+i*nWidth+j*nChanel+k) *(IplImg->imageData+(nHeight-i-1)*nWidth+j*nChanel+k); pImg[i*nWidth*nChanel+j*nChanel+k] IplImg->imageData[(nHeight-i-1)*nWidth*nChanel+j*nChanel+k]; } } } } else { //from left-up memcpy(pImg,IplImg->imageData,nHeight*nWidth*nChanel*sizeof(byte)); } //pImg = (byte *)IplImg->imageData; return pImg; }

= =

} ////////////////////////////////////////////////////////////////////////// //Name: IplImage2Byte //Function: convert IplImage to byte* //Author:liyy //Date: 2011.05.23 ////////////////////////////////////////////////////////////////////////// byte * CconvertImgStruct::IplImage2Byte( IplImage *IplImg ) { if (!IplImg) { return NULL; } int nHeight = IplImg->height; int nWidth =IplImg->width; int bitCount = IplImg->depth; int nChanel = IplImg->nChannels; byte *pImg = new byte[nHeight*nWidth*nChanel*sizeof(byte)]; if (IplImg->origin == 0) { //from left-down for (int i = 0; i< nHeight;i++) { for (int j = 0; j< nWidth;j++) { for (int k =0; k < nChanel;k++) { //*(pImg+i*nWidth+j*nChanel+k) *(IplImg->imageData+(nHeight-i-1)*nWidth+j*nChanel+k); pImg[i*nWidth*nChanel+j*nChanel+k] IplImg->imageData[(nHeight-i-1)*nWidth*nChanel+j*nChanel+k]; } } } } else { //from left-up memcpy(pImg,IplImg->imageData,nHeight*nWidth*nChanel*sizeof(byte)); }

= =

//pImg = (byte *)IplImg->imageData; return pImg; }

OpenCV 中 IplImage 图像格式与 BYTE 图像数据的转换
分类: oencv 2011-04-27 22:33540人阅读评论(1)收藏举报

转自 http://blog.csdn.net/xiaofengsheng/archive/2009/11/16/4814709.aspx OpenCV 中 IplImage 图像格式与 BYTE 图像数据的转换 IplImage* iplImage; BYTE* data; 1 由 IplImage*得到 BYTE*图像数据: data = iplImage->imageDataOrigin; //未对齐的原始图像数据 或者 data = iplImage->imageData; //已对齐的图像数据 2 由 BYTE*得到 IplImage*图像数据 iplImage = cvCreateImageHeader(cvSize(width,height),depth,channels); cvSetData(iplImage,data,step);

首先由 cvCreateImageHeader()创建 IplImage 图像 头,制定图像的尺 寸,深度和通道数;然后由 cvSetData()根据 BYTE*图像数据指针设置 IplImage 图像头的数据数 据,其中 step 指定该 IplImage 图像 每行占的字节数,对于1通道的 IPL_DEPTH_8U 图像,step 可以等于

width。 1,如果是从新创造一个 Iplimage,则用 IplImage* cvCreateImage( CvSize size, int depth, int channels ),它创建头并分配数据。 注:当不再使用这个新图像时,要调用 void cvReleaseImage( IplImage** image )将它的头和图像数 据释放!

2,如果有图像数据没有为图像头分配存储空间(即,没有为 IplImage* 指针分配动态存储空间) ,则 先调用 IplImage* cvCreateImageHeader( CvSize size, int depth, int channels )创建图像头,再 调用 void cvSetData( CvArr* arr, void* data, int step )指定图像数据, 可以理解为将这个新图 像的数据指针指向了一个已存在的图像数据上, 不存在图像数据存储空 间的分配操 作。 注:当不再使用这个新图像时,要调用 void cvReleaseImageHeader( IplImage** image )将它的图像 头释放! 3,如果有图像数据也有图像头(用于 IplImage 为静态分配存储空间的 情 况) ,则先调用 IplImage* cvInitImageHeader( CvSize size, int depth, int channels )更改图像头,

再调用 void cvSetData( CvArr* arr, void* data, int step )指定图像数据。 注:因为这个新图像使用的是其它图像的数据和已有的图像头,所以不 能使用 cvReleaseImage 将它的 头和图像数据释放, 也不能使用 cvReleaseData 将它的图像数据释 放!

4,如果从已有的一个图像创建,则用 IplImage* cvCloneImage( const IplImage* image ),它制作 图像的完整拷贝包括头、ROI 和数据。 注:当不再使用这个新图像时,要调用 void cvReleaseImage( IplImage** image )将它的头和图像数 据释放! 图像分割: 概念:

图像分割是将图像划分成若干个互不相交的小区域的过 程,所谓小区域是某种意义下具有共同属性的像素的连通集合。 从集合的观点看:它应该是具有如下性质的一种点集,集 合 R 代表整个区域,对 R 的分割可看作将 R 分成 N 个满足以下五个条 件的非空子集 R1,R2,…,RN:

目的:
无论是图像处理、分析、理解与识别,其基础工作一般都建立在图像分割的基础上; 将图像中有意义的特征或者应用所需要的特征信息提取出来;

图像分割的最终结果是将图像分解成一些具有某种特征的单元,称 为图像的基元;
相对于整幅图像来说,这种图像基元更容易被快速处理。

图像分割的特征: 分割出来的各区域对某种性质例如灰度,纹理而言具有相似性,区 域内部是连通的的且没有过多小孔。 区域边界是明确的 相邻区域对分割所依据的性质有明显的差异

图像分割的方法:

一、基于像素灰度值的分割方法:阈值(门限)方法 二、基于区域的分割方法:通过直接确定区域间的边界来实现分割 的边界方法; 三、基于边缘的分割技术:首先检测边缘像素,再将边缘像素连接 起来构成边界形成分割。

图像分割包含的内容:
边缘检测

边缘跟踪: 从图像中一个边缘点出发,然后根据某种判别准则搜索下一个边缘 点以此跟踪出目标边界。 阈值分割:
原始图像——f(x,y)

灰度阈值——T 阈值运算得二值图像——g(x,y)
区域分割:

阈值分割法由于没有或很少考虑空间关系,使多阈值选择受到限制 于区域的分割方法可以弥补这点不足, 它利用的是图像的空间性质, 该方法认为分割 出来的属于同一区域的像素应具有相似的性质,其概念是相当直观 的。
传统的区域分割算法有区域增长法和区域分裂合并法。 该类方法在没有先验知识可以利 用时,对含有复杂场景 或自然景物等先验知识不足的图像进行分割, 也可以取得较好的性能。 但是, 空间和时 间开销都比较大。

区域生长法主要考虑象素及其空间邻域象素之间的关系 开始时确定一个或多个象素点作为种子,然后按某种相似性准则增

长区域,逐步生成具有某种均匀性的空间区域,将相邻的具有相似性质 的象素或区域归并从而逐步增长区域, 直至没有可以归并的点或其它小 区域为止。 区域内象素的相似性度量可以包括平均灰度值、纹理、颜色等信息。 主要步骤:

选择合适的种子点 确定相似性准则(生长准则) 确定生长停止条件

区域分裂:

条件:如果区域的某些特性不满足一致性准则 开始:从图像的最大区域开始,一般情况下,是从整幅图像开始 注意: 确定分裂准则(一致性准则) 确定分裂方法,即如何分裂区域,使得分裂后的子区域的特性尽可 能都满足一致性准则值

图像分割的基本原理:

图像分割是将图像划分成若干个互不相交的小区域的过程,小区域 是某种意义下具有共同属性的像素的连通集合。 ?如不同目标物体所占的图像区域、前景所占的图像区域等; ?连通是指集合中任意两个点之间都存在着完全属于该集合的连通 路径; ?对于离散图像而言,连通有4连通和8连通之分。

图像分割有三种不同的途径: 1.是将各像素划归到相应物体或区域的像素聚类方法, 即区域 法; 2.是通过直接确定区域间的边界来实现分割的边界方法; 3.是首先检测边缘像素,再将边缘像素连接起来构成边界形成 分割。 在图像分割技术中,最常用的是利用阈值化处理迚行的图像分 割。 在图像的阈值化处理过程中,选用不同的阈值其处理结果差异 很大; 阈值过大,会提取多余的部分; 阈值过小,又会丢失所需的部分; 因此,阈值的选取非常重要。

边缘检测和图像分割的联系: 边缘检测后的图像是二值图像,对二值图像可以运用形态学操作来 分割目标, 所以边缘检测是图像分割的一个前提。但分割不一定非要用边缘检 测。

================================== 图像特征: ?图像特征是指图像中可用作标志的属性,它可以分为统计特征和视觉 特征两类。 ?图像的统计特征是指一些人为定义的特征,通过变换才能得到,如图 像的直方图、 矩、频谱等; ?图像的视觉特征是指人的视觉可直接感受到的自然特征,如区域的亮 度、纹理或轮廓等

轮廓提取: 二值图像轮廓提取的算法非常简单,就是掏空内部点: 如果原图像中 有一点为黑,且它 的8个邻点都是黑色时,说明该点是内部点,将该点删除(置为白色像 素值255) 。对

图像中所有像素点执行该操作便可完成图像轮廓的提取。

模板匹配: 模板匹配是指用一个较小的图像,即模板与源图像迚行比较,以确定在 源图像中是否 存在与该模板相同或相似的区域,若该区域存在, 还可确定其位置并 提取该区域。

形状匹配: 形状也是描述图像内容的一个重要特征, 利用形状迚行匹配需 要考虑三个问题。 首先,形状常与目标联系在一起,所以相对于颜色,形状特征可以看作 是更高层次的 图像特征。要获得有关目标的形状参数,常常要先对图像迚行分割,所 以形状特征会 受图像分割效果的影响。 其次, 目标形状的描述是一个非常复杂的问题, 至今还没有 找到能与人的感觉相一致的图像形状的确切数学定义。最后,从不同视 角获取的图像中 目标形状可能会有很大差别,为准确迚行形状匹配,需要解决平移、尺 度、 旋转变换

不变性的问题。 标的形状常常可以用目标的轮廓来表示, 而轮廓是由一系列边界点所组 成的。一般认为, 在较大尺度下常常能较可靠地消除误检并检测到真正的边界点, 但在大 尺度下对边界的 定位不易准确。相反,在较小尺度下对真正边界点的定位常比较准确, 但在小尺度下 误检的比例会增加。 所以, 可考虑先在较大尺度下检测出真正的边界点, 再在较小尺度 下对真正边界点迚行较精确的定位。小波变换和分析作为一种多尺度、 多通道分析工具, 比较适合对图像迚行多尺度的边界检测。


相关文章:
CvArr、Mat、CvMat、IplImage、BYTE转换K
CvArrMatCvMatIplImageBYTE 转换(总结而来)分类: OpenCv 2012-02-29 14:165388人阅读评论(2)收藏举报 byte 优化图像处理数据结构 matrixvector 一、Mat ...
CvArr、Mat、CvMat、IplImage、BYTE转换(总结而来)
CvArr、Mat、CvMatIplImageBYTE转换(总结而来)_计算机软件及应用_IT/计算机_专业资料。Mat openv一、Mat 类型:矩阵类型,Matrix。 在 openCV 中,Mat 是一个多维...
Mat, IplImage, CvMat, Cvarr关系及元素获取
MatIplImageCvMatCvarr 因为之前查资料关于 opencv 几种坑爹类型 CvMat, Mat, IplImage, Cvarr 的详细讲解很 多,但详细到多通道元素获取和涉及到类型转换的文章极少...
opencv数据间转换函数
opencv作为一款图像视觉处理领域的应用库 功能异常强大 很多人结合VS在用 本文档整理了其中常用的数据格式间的转化CvArrMatCvMatIplImageBYTE 转换(总结而来)...
OpenCV中Mat与IplImage和CvMat类型之间的相互转换
OpenCV 中 MatIplImageCvMat 类型之间的相互转换 Mat 类型较 CvMatIplImage 有更强的矩阵运算能力,支持常见的矩阵运算(参照 Matlab 中的各 种矩阵...
opencv中Mat与IplImage,CVMat类型之间转换=
opencv 中 MatIplImage,CVMat 类型之间转换 opencv 中对图像的处理是最基本的操作,一般的图像类型为 IplImage 类型,但是 当我们对图像进行处理的时候,多数都是...
open cv中的Mat详解
[k],可以计算为: addr( Mi0 ;:::;iM.dims-1...OpenCV 中 IplImage, CvMat, Mat 的关系和相互转换...CvMat 之上还有一个更抽象的基类---CvArr,这在源...
opencv中的几种常见的图像类型
中,几种常见的图像类型有: IplImage,Mat,CvMat,CvArr CvArr : 老版本的结构了...// Mat -> CvMat OpenCV 中 IplImage 图像格式与 BYTE 图像数据的转换 IplImage...
OpenCV类Mat详解
iM.dims-1),其中 0<= ik < M.size [k],...从 MatCvMatIplImage 的后台转换是通过...step–每个矩阵行占用的字节数。如果任何值应包括每...
mat
? 直接存取,假设使用 4-字节校正: CvMat* M = cvCreateMat(4,4,CV_32FC1...0 ) 3.cvArr(IplImage 或者 cvMat) 转化cvMat 方式一、 cvGetMat 方式: ...
更多相关标签:
cvarr iplimage | cvmat cvarr | cvmat到cvarr | cvmat转cvarr | cvmat转iplimage | cvmat iplimage | iplimage cvmat转换 | cvmat和iplimage |