OpenCV(三) 之 基本数据结构 CvMat和 IplImage
OpenCV(三) 之 基本数据结构 CvMat和 IplImage
OpenCv中基本的数据类型
| 类型 | 参数 | 表示 |
|---|---|---|
| CvPoint | int x,y | 像素点 |
| CvPoint2D32f | float x,y | 平面点 |
| CvPoint3D32f | float x,y,z | 空间点 |
| CvSize | int width,height | 图像大小 |
| CvSize2D32f | float x, y | 区域大小 |
| CvSize3D32f | float x,y,z | 立方体大小 |
| CvRect | int x,y,width,height | 矩形区域 |
| CvScalar | double val[4] | RGBA 值 |
类型的构造函数仅是类型名首字母小写,比如cvPoint(int x,int y),除了CvScalar
CvScalar类型是可以用来存放4个double类型的数组,最多四个不一定要四个
- typedef struct CvScalar
- {
- double val[4];
- };
其赋值函数有四种
- 1. CvScalar cvScalar(double v0,double v1,double v2, double v3);
- 2. CvScalar cvRealScalar(double v0);
- //第一个数值赋值,剩余三个为0
- 3. CvScalar cvScalarAll(double v);
- //所有的四个值都相同
- 4. CV_RGB
- #define CV_RGB(r,g,b) cvScalar(b,r,g,0);
CvMat类型
- typedef struct CvMat {
- int type;
- int step;
- int* refcount; // for internal use only
- union {
- uchar* ptr;
- short* s;
- int* i;
- float* fl;
- double* db;
- } data;
- union {
- int rows;
- int height;
- };
- union {
- int cols;
- int width;
- };
- } CvMat;
其构造函数
- CvMat* cvCreateMat(int rows,int cols,int type);
- CvMat* cvCreateMatHeader(int rows,int cols,int type);
- CvMat* cvInitMatHeader(CvMat *mat,int rows,int cols,int type, void* data=NULL, int step = CV_AUTOSTEP)
- CvMat* cvCloneMat(CvMat*)
- //内存释放
- void cvReleaseMat(CvMat** mat)
使用数组创建CvMat
- float vals[4]=[1,2,3,4];
- CvMat* mat;
- cvInitMatHeader(mat,2,2,CV_32FC1,vals);
CvMat属性值的获取
- cvGetElemType(const CvArr* arr);//返回数据类型
- cvGetDims(const CvArr* arr,int* sizes=NULL);//返回CvMat的维数,相当于张量的阶数, int* 可以用来存储每一维对应的长度
- cvGetDimSize(const CvArr* arr,int index);//返回第index维度上的长度
CvMat数据值的读取
- float sum( const CvMat* mat )
- {
- float s = 0.0f;
- for(int row=0; row<mat->rows; row++ )
- {
- const float* ptr = (const float*)(mat->data.ptr + row * mat->step);
- for( col=0; col<mat->cols; col++ )
- {
- s += *ptr++;
- }
- }
- return( s );
- }
这里要注意的是
要强制指定数据类型,因为CvMat定义中数据类型是union。
使用step参数是每一行所占的字节数,并不等于cols*sizeof(bytes),因为含有优化的地址对齐问题。
CvMat矩阵数据存储顺序是先行再列,3D数据存储顺序是每个位置的channels,然后按行、列排列。
下图时一组空间点存到不同的CvMat的存储结果

IplImage
- typedef struct _IplImage{
- int nSize;
- int ID;
- int nChannels; //**type
- int alphaChannel;
- int depth; //**type
- int dataOrder; //数组存储结构,是按照像素存IPL_DATA_ORDER_PIXEL,还是先按照通道存IPL_DATA_ORDER_PLANE
- int origin; //图像坐标原点位于左上角 IPL_ORIGIN_TL,还是左下角IPL_ORIGIN_BL
- int align;
- int width; //**columns
- int height; //**rows
- char colorModel[4];
- char channelSeq[4];
- struct _IplROI* roi; //region of interest
- struct _IplImage* maskROI;
- void* imageId;
- struct _IplTileInfo* tileInfo;
- int imageSize;
- char* imageData; //** data
- int widthStep; //** step
- int BorderMode[4];
- int BorderConst[4];
- char* imageDataOrigin;
- }
其中注释**部分对应着CvMat的成员变量,CvMat的type成员被拆分成了两个属性:depth, nChannels表示像素值深度和图像的通道数
depth的取值有
- IPL_DEPTH_8U; IPL_DEPTH_8S; IPL_DEPTH_16S; IPL_DEPTH_32S; IPL_DEPTH_32F; IPL_DEPTH_64F;
看字面就知道什么意思了。
IplROI包含的属性:
- int xOffset, yOffset; //x,y 方向的偏置
- int height, width; //感兴趣区域的大小
- int COI; //Channel of Interest,感兴趣的通道
一旦ROI设置了,那么对图像的操作将尽在ROI内操作。
IplImage数据的访问示例
对于HSV图像,希望将S,V通道值设置为255:
- void saturate_sv(IplImage* img)
- {
- for(int y=0;y<img->height;y++)
- {
- uchar* ptr=(uchar*)(img->imageData+y*img->widthStep);
- for(int x=0;x<img->width;i++)
- {
- ptr[3*x+1]=255;
- ptr[3*x+2]=255;
- }
- }
- }
这里奇怪为什么默认img->dataOrder=IPL_DATA_ORDER_PIXEL。这是因为
We say that dataOrder may be either IPL_DATA_ORDER_PIXEL of IPL_DATA_ORDER_PLANE, but in fact only IPL_DATA_ORDER_PIXEL is supported by OpenCV. Both values are generally supported by IPL/IPP, but OpenCV always uses interleaved images.
Note: 比较CvMat和IplImage数据区的操作,发现IplImage->imageData并没有进行类型转换,全部都是byte字节,而CvMat则需要转换成所存储数据的类型,在指针运算时需要特别注意,尤其是IplImage和CvMat进行计算时。
ROI的使用:
- void cvSetImageROI(IplImage* image, CvRect rect); //设置rect区域为感兴趣区域
- void cvResetImageROI(IplImage* image); //取消图像的感兴趣区域
- #include "highgui.h"
- #include "cv.h"
- int main(int argc, char** argv)
- {
- // 图像路径、ROI的x,y偏移量, 长和宽、像素值增加量
- IplImage* src;
- if (argc == 7 && ((src = cvLoadImage(argv[1])) != 0))
- {
- int xOffset = atoi(argv[2]); //x偏移
- int yOffset = atoi(argv[3]); //y偏移
- int width = atoi(argv[4]); //ROI宽
- int height = atoi(argv[5]); //ROI高
- int add = atoi(argv[6]); //每个像素值增加量
- cvSetImageROI(src, cvRect(xOffset, yOffset, width, height));
- cvAddS(src, cvScalarAll(add), src);
- cvResetImageROI(src);
- cvNamedWindow("src");
- cvShowImage("src", src);
- cvWaitKey(0);
- cvReleaseImage(&src);
- cvDestroyWindow("src");
- }
- }

上述过程还存在另一种直接地址操作的方法
- #include "highgui.h"
- #include "cv.h"
- int main(int argc, char** argv)
- {
- // 图像路径、ROI的x,y偏移量, 长和宽、像素值增加量
- IplImage* src;
- if (argc == 7 && ((src = cvLoadImage(argv[1])) != 0))
- {
- int xOffset = atoi(argv[2]); //x偏移
- int yOffset = atoi(argv[3]); //y偏移
- int width = atoi(argv[4]); //ROI宽
- int height = atoi(argv[5]); //ROI高
- int add = atoi(argv[6]); //每个像素值增加量
- IplImage * sub_img = cvCreateImageHeader(cvSize(width, height), src->depth, src->nChannels);
- sub_img->widthStep = src->widthStep;
- sub_img->imageData = src->imageData + yOffset*src->widthStep + xOffset*src->nChannels;
- cvAddS(sub_img, cvScalarAll(add), sub_img);
- cvReleaseImageHeader(&sub_img);
- cvResetImageROI(src);
- cvNamedWindow("src");
- cvShowImage("src", src);
- cvWaitKey(0);
- cvReleaseImage(&src);
- cvDestroyWindow("src");
- }
- }
这里很容易理解,就是将ROI截取出来作为一个新的图像,需要注意的时sub_img并没有新分配地址,数据区指向的仍然是src的数据区,此时图像sub_img的数据区并不是连续的,所以将src->widthStep赋值给sub_img-》widthStep保证读取正确的地址数据。
OpenCV(三) 之 基本数据结构 CvMat和 IplImage的更多相关文章
- OpenCV数据结构:CvMat,IplImage,CvArr的应用
最近看HS算法时,发现在新的OpenCV3.0已经移除了该算法,于是不得不看老版的.这其中涉及到了CvMat,CvArr,IplImage的使用.关于这三个结构与Mat的转换关系,总结如下: (1)派 ...
- OpenCV——Mat、CvMat、IplImage类型浅析【转】
OpenCV中常见的与图像操作有关的数据容器有Mat,cvMat和IplImage. 一.Mat类型:矩阵类型,Matrix. 在openCV中,Mat是一个多维的密集数据数组.可以用来处理向量和矩阵 ...
- Opencv中将CvMat转为IplImage
Opencv中将CvMat转为IplImage,并在内存获得起头指针,而不用cvSaveImage(),贴上代码 IplImage * imgg = NULL; imgg = cvCreateImag ...
- OpenCV学习(2)--基本数据结构
OpenCV的基本数据结构 CvPoint:表示图像中的点 CvPoint2D32f:二维空间中的点 CvPoint3D32f:三维空间中的点 这些都是结构体,并不是C++语言中的类,所以他们的构造函 ...
- CvArr、Mat、CvMat、IplImage、BYTE转换
一.Mat类型:矩阵类型,Matrix. 在openCV中.Mat是一个多维的密集数据数组. 能够用来处理向量和矩阵.图像.直方图等等常见的多维数据. Mat有3个重要的方法: ...
- 图像处理之opencv---mat、cvmat、IplImage之间的转换
一.Mat类型:矩阵类型,Matrix. 在openCV中,Mat是一个多维的密集数据数组.可以用来处理向量和矩阵.图像.直方图等等常见的多维数据. Mat有3个重要的方法: 1.Mat mat = ...
- 【转】Cvmat与IplImage的相互转换
seyvlei 原文地址 1.IplImage转Cvmat IplImage* src = cvLoadImage(); CvMat* mat=cvCreateMat(src->height,s ...
- 《学习opencv》笔记——基本数据结构,CvMat,矩阵訪问
老板让让做一个东东.输入端要用到opencv顺便就来学习一下.买了本书<学习opencv>翻来一看,opencv1.0,去官网上一看.opencv2.49,瞬间有种蛋碎的赶脚.看着 ...
- opencv常用数据结构之:IplImage
typedef struct_IplImage{ int nSize; //IplImage大小 int ID; //版本(=0) int nChannels; //大多 ...
随机推荐
- Yii2 ActiveRecord save失败
当给AR写beforeSave方法时,注意返回true还是false.如果没有返回值,或者返回false,那么就不会存入数据库.如下 晚上写代码的时候beforeSave忘了返回true,导致无法存入 ...
- 错误:java.util.Map is an interface, and JAXB can't handle interfaces.
问题: 在整合spring+cxf时报错java.util.Map is an interface, and JAXB can't handle interfaces. 解决方法: 将服务端的serv ...
- css3 FlexBox 弹性布局
Flex 弹性布局 这个是css3中新添加的内容,现在已经支持所有的浏览器,利用Flex布局,可以简便.完整.响应式地实现各种页面布局. 注意:在设置 flex 后,子元素的flaot ,clear, ...
- 【Android自学日记】两种适配器的使用
ArrayAdapter适配器: (1)用于显示基本的文字内容 (2)基本使用过程:新建适配器---创建或加载数据源---适配器加载数据源---视图加载适配器 ArrayAdapter(上下文,当前L ...
- C#string类型总结
字符串的特性:不可变性,每对字符串做拼接或者重新赋值之类的操作,都会在内存中产生一个新的实例. 所以说,在.Net平台下,如果你对一个字符串进行大量的拼接赋值等操作,会产生大量的垃圾. --- ...
- Linux下的压缩和解压缩命令——gzip/gunzip
gzip命令 gzip命令用来压缩文件.gzip是个使用广泛的压缩程序,文件经它压缩过后,其名称后面会多处".gz"扩展名. gzip是在Linux系统中经常使用的一个对文件进行压 ...
- 推荐一篇 关于REST 和 SOAP区别的文章
写的很出色! https://www.ibm.com/developerworks/cn/webservices/0907_rest_soap/ 我的感觉就是REST针对的是资源,通过api的URL就 ...
- Python初识(一)
首先我有编程语言的基础,你也有就最好了,这样会很快认识Python. 当然由于本人见识和学识的局限性,请广大猿/媛们多多包涵与指正(希望多评论哦),共同进步嘛. ◆ 准备环境:到python官网下载p ...
- java注解处理
1.自定义注解类型 package com.yc.annotation; import java.lang.annotation.ElementType; import java.lang.ann ...
- 461. Hamming Distance and 477. Total Hamming Distance in Python
题目: The Hamming distance between two integers is the number of positions at which the corresponding ...