opencv _相关
2015-12-09 17:06
393 查看
转载请注明出处:http://blog.csdn.net/xiaowei_cqu/article/details/7557063
!!此篇是基于IplImage* (C接口或者说2.1之前版本的接口,新的Mat的访问方式请参考博文:《访问Mat图像中每个像素的值》)
IplImage是OpenCV中CxCore部分基础的数据结构,用来表示图像,其中Ipl是Intel Image Processing Library的简写。以下是IplImage的结构分析(来自OpenCV中文网站:http://www.opencv.org.cn/index.php/Cxcore基础结构#IplImage)
[cpp] view plaincopy
typedef struct _IplImage
{
int nSize;
int ID;
int nChannels;
int alphaChannel;
int depth;
char colorModel[4];
char channelSeq[4];
int dataOrder;
int origin;
int align;
int width;
int height;
struct _IplROI *roi;
struct _IplImage *maskROI;
void *imageId;
struct _IplTileInfo *tileInfo;
int imageSize;
char *imageData;
int widthStep;
int BorderMode[4];
int BorderConst[4];
char *imageDataOrigin;
}
IplImage;
直接访问:
对我们来说比较重要的两个元素是:char *imageData以及widthStep。imageData存放图像像素数据,而widStep类似CvMat中的step,表示以字节为单位的行数据长度。一个m*n的单通道字节型图像,其imageData排列如下:
如果我们要遍历图像中的元素,只需:
[cpp] view plaincopy
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
uchar* tmp;
for(int i=0;iheight;i++)
for(int j=0;jwidth;j++)
*tmp=((uchar *)(img->imageData + i*img->widthStep))[j];
这种直接访问的方法速度快,但容易出错,我们可以通过定义指针来访问。即:
[cpp] view plaincopy
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
ucha* data=(uchar *)img->imageData;
int step = img->widthStep/sizeof(uchar);
uchar* tmp;
for(int i=0;iheight;i++)
for(int j=0;jwidth;j++)
*tmp=data[i*step+j];
而多通道(三通道)字节图像中,imageData排列如下:
其中(Bi,Bj)(Gi,Gj)(Ri,Rj)表示图像(i,j)处BGR分量的值。使用指针的遍历方法如下:
[cpp] view plaincopy
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
uchar* data=(uchar *)img->imageData;
int step = img->widthStep/sizeof(uchar);
int channels = img->nChannels;
uchar *b,*g,*r;
for(int i=0;iheight;i++)
for(int j=0;jwidth;j++){
*b=data[i*step+j*chanels+0];
*g=data[i*step+j*chanels+1];
*r=data[i*step+j*chanels+2];
}
*如果要修改某像素值,则直接赋值。
使用cvGet2D()函数访问:
cvGet*D系列函数可以用来返回特定位置的数组元素(一般使用cvGet2D),原型如下:[cpp] view plaincopy
CvScalar cvGet1D( const CvArr* arr, int idx0 );
CvScalar cvGet2D( const CvArr* arr, int idx0, int idx1 );
CvScalar cvGet3D( const CvArr* arr, int idx0, int idx1, int idx2 );
CvScalar cvGetND( const CvArr* arr, int* idx );
idx0,idx1,idx2分别用来指示元素数组下标,即cvGet2D返回(idx0,idx1)处元素的值。
因此,单通道图像像素访问方式如下:
[cpp] view plaincopy
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
double tmp;
for(int i=0;iheight;i++)
for(int j=0;jwidth;j++)
tmp=cvGet2D(img,i,j).val[0];
多通道字节型/浮点型图像:
[cpp] view plaincopy
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
double tmpb,tmpg,bmpr;
for(int i=0;iheight;i++)
for(int j=0;jwidth;j++){
tmpb=cvGet2D(img,i,j).val[0];
tmpg=cvGet2D(img,i,j).val[1];
tmpr=cvGet2D(img,i,j).val[2];
}
如果是修改元素的值,可用cvSet*D(一般是cvSet2D)函数:
[cpp] view plaincopy
void cvSet1D( CvArr* arr, int idx0, CvScalar value );
void cvSet2D( CvArr* arr, int idx0, int idx1, CvScalar value );
void cvSet3D( CvArr* arr, int idx0, int idx1, int idx2, CvScalar value );
void cvSetND( CvArr* arr, int* idx, CvScalar value );
这种方法对于任何图像的访问方式是一样的,比较简单,但效率较低,不推荐使用。
相关文章推荐
- django+uwsgi+nginx部署,静态文件
- linux基础(七)----linux命令系统学习----系统安全相关命令
- Linux学习笔记(二十一、输出重定向)
- Apache应用服务器之四:Apache与Tomcat安装与配置
- OpenGL学习笔记
- linux中serial driver理解【转】
- errno.h linux errno
- Linux内核中进程上下文、中断上下文、原子上下文、用户上下文的理解【转】
- linux内核设计与实现笔记 进程调度
- linux下安装或升级GCC4.8,以支持C++11标准
- VS2013+WIN10+OPENCV3.0环境配置
- OpenCV 的内存泄露问题(静态内存泄露)
- cenos yum 安装nginx
- css3网站
- Apache Kafka监控之Kafka Web Console
- 自动化运维利器---pssh
- zabbix自定义网卡流量监控脚本and解决图形字体方块问题
- [转帖]迅为4412开发板最小linux系统的存储空间修改
- shell小例子
- Apache和Tomcat的区别