在OpenCV中用指针访问像素值的一些体会
2013-10-27 15:12
309 查看
OpenCV中文站中有一篇关于OpenCV基础操作的文章《OpenCV
编程简介(矩阵/图像/视频的基本读写操作)入门必读》,上面对OpenCV的一些入门操作进行了详细的介绍。我也是看了这篇文章后才开始了OpenCV的编程。但是最近发现了一个理解上的小失误,导致一个问题困扰了很长时间。现在问题解决了,就把思考的过程写在这跟大家分享一下。
该文章其中有一部分是关于如何操作图像像素值的介绍:
基于指针的直接访问:(简单高效)
IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
int height = img->height;
int width = img->width;
int step = img->widthStep/sizeof(uchar);
uchar* data = (uchar *)img->imageData;
data[i*step+j] = 111;
对像素值的访问,作者用了data[i*step+j]这样的格式,当时没怎么仔细想,就认为这是图像中坐标为(i, j)像素的值,其实并不是这样的。
首先,来看一下IplImage的结构,其中像素值存放在char *imageData指针做指向的区域,OpenCV官方文档中将其解释为"A pointer to the aligned image data",就是指向排列好的图像数据的指针。但是指针取出来,是一个一维数组data[i*step+j],是怎么体现出“排列好的”这个性质的呢?OpenCV用了一个辅助的变量来实现。就是IplImage的widthStep,它表示图像一行有多少个字节。用这个值除以一个像素所占的字节数,就可以得到一行有多少个像素。data[i*step+j]就是第i行第j个像素的像素值(i和j从0开始,这个应该不用我说吧)。
但是,如果用(i, j)来表示坐标的话,正好反了。因为行号是在列的方向递增的。比如说第5行,那么它的纵坐标应该是5-1。第五行的第几个,这个几才代表横坐标。
明白了这点就好办了,如果想用(i, j)同时来表示坐标和数组中的点,那么应该用data[i+j*step]。i在图像宽度范围内递增,j在图像高度范围内递增。如果图像宽和高非别为w和h,那么对像素的遍历可以用下面的循环搞定:
for(int j = 0; j < h; j++) {
for(int i = 0; i < w; i++) {
printf("(%d, %d)=%d\t", i, j, data[i+j*step]);
}
}
以后就定义成data[i+j*step],方便后面的操作。一般情况下还是习惯i在前、j在后的格式。
编程简介(矩阵/图像/视频的基本读写操作)入门必读》,上面对OpenCV的一些入门操作进行了详细的介绍。我也是看了这篇文章后才开始了OpenCV的编程。但是最近发现了一个理解上的小失误,导致一个问题困扰了很长时间。现在问题解决了,就把思考的过程写在这跟大家分享一下。
该文章其中有一部分是关于如何操作图像像素值的介绍:
基于指针的直接访问:(简单高效)
IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
int height = img->height;
int width = img->width;
int step = img->widthStep/sizeof(uchar);
uchar* data = (uchar *)img->imageData;
data[i*step+j] = 111;
对像素值的访问,作者用了data[i*step+j]这样的格式,当时没怎么仔细想,就认为这是图像中坐标为(i, j)像素的值,其实并不是这样的。
首先,来看一下IplImage的结构,其中像素值存放在char *imageData指针做指向的区域,OpenCV官方文档中将其解释为"A pointer to the aligned image data",就是指向排列好的图像数据的指针。但是指针取出来,是一个一维数组data[i*step+j],是怎么体现出“排列好的”这个性质的呢?OpenCV用了一个辅助的变量来实现。就是IplImage的widthStep,它表示图像一行有多少个字节。用这个值除以一个像素所占的字节数,就可以得到一行有多少个像素。data[i*step+j]就是第i行第j个像素的像素值(i和j从0开始,这个应该不用我说吧)。
但是,如果用(i, j)来表示坐标的话,正好反了。因为行号是在列的方向递增的。比如说第5行,那么它的纵坐标应该是5-1。第五行的第几个,这个几才代表横坐标。
明白了这点就好办了,如果想用(i, j)同时来表示坐标和数组中的点,那么应该用data[i+j*step]。i在图像宽度范围内递增,j在图像高度范围内递增。如果图像宽和高非别为w和h,那么对像素的遍历可以用下面的循环搞定:
for(int j = 0; j < h; j++) {
for(int i = 0; i < w; i++) {
printf("(%d, %d)=%d\t", i, j, data[i+j*step]);
}
}
以后就定义成data[i+j*step],方便后面的操作。一般情况下还是习惯i在前、j在后的格式。
相关文章推荐
- opencv内存总结和访问图像中像素方法案例(指针方法)
- opencv访问图片中像素的方法(一)——指针访问
- opencv学习笔记1::访问图像中像素的三类方法(用指针,迭代器,动态地址)代码及用时检测
- Opencv用指针访问像素
- OpenCV访问图像像素的方法收集以及自己实践中得体会
- opencv2-用指针来访问图像像素
- opencv 通过指针访问图像像素值,输出为空的问题
- 用指针访问像素OPENCV
- OpenCV访问图像像素的方法收集以及自己实践中得体会
- opencv学习(十)颜色缩减 // 查表 // 计时 // 访问像素的三个方法(指针/STL迭代器(待详细了解)/动态地址)//历遍图像的14种方法
- opencv2-用迭代器访问图像像素
- 【OpenCV】访问Mat图像中每个像素的值
- 像素临近区域、颜色通道、ROI区域的访问---opencv.2学习笔记2
- 【OpenCV】访问Mat中每个像素的值
- 【OpenCV】访问Mat中每个像素的值(新)
- opencv访问图像像素及简单应用
- 【OpenCV】访问Mat图像中每个像素的值
- 用动态地址计算配合at访问像素OPENCV
- OpenCV访问Mat中每个像素的值
- 【OpenCV】访问Mat图像中每个像素的值