五.使用OpenCv操作图像上每一个像素点

来源:互联网 发布:适合初学者的php集成 编辑:程序博客网 时间:2024/04/28 20:48

        本文记录使用OpenCv操作图像上每一个像素点,用摄像头采集(拍照)或者直接加载一副图像后,树莓派系统会在内存中为这幅图像分配内存空间,通过定义的IplImage结构体指针指向这块内存空间就方便可以操控它。因为IplImage结构体中定义了很多内部变量,代表图像的属性,具体如下:


1.IplImage结构具体定义如下:
typedef struct _IplImage
{
int nSize; /* IplImage大小 */
int ID; /* 版本 (=0)*/
int nChannels; /* 大多数OPENCV函数支持1,2,3 或 4 个通道 */
int alphaChannel; /* 被OpenCV忽略 */
int depth; /* 像素的位深度,主要有以下支持格式: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,IPL_DEPTH_16S,                                                                                IPL_DEPTH_32S,IPL_DEPTH_32F 和IPL_DEPTH_64F */
char colorModel[4]; /* 被OpenCV忽略 */
char channelSeq[4]; /* 同上 */
int dataOrder; /* 0 - 交叉存取颜色通道, 1 - 分开的颜色通道.只有cvCreateImage可以创建交叉存取图像 */
int origin; /*图像原点位置: 0表示顶-左结构,1表示底-左结构 */
int align; /* 图像行排列方式 (4 or 8),在 OpenCV 被忽略,使用 widthStep 代替 */
int width; /* 图像宽像素数 */
int height; /* 图像高像素数*/
struct _IplROI *roi; /* 图像感兴趣区域,当该值非空时,只对该区域进行处理 */
struct _IplImage *maskROI; /* 在 OpenCV中必须为NULL */
void *imageId; /* 同上*/
struct _IplTileInfo *tileInfo; /*同上*/
int imageSize; /* 图像数据大小(在交叉存取格式下ImageSize=image->height*image->widthStep),单位字节*/
char *imageData; /* 指向排列的图像数据 */
int widthStep; /* 排列的图像行大小,以字节为单位 */
int BorderMode[4]; /* 边际结束模式, 在 OpenCV 被忽略*/
int BorderConst[4]; /* 同上 */
char *imageDataOrigin; /* 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的 */
} IplImage;

IplImage结构体是整个OpenCV函数库的基础,在定义该结构变量时可以用函数cvCreatImage,变量定义方法如下:
IplImage* src=cvCreateImage(cvSize(400,300), IPL_DEPTH_8U,3);
上句定义了一个IplImage指针变量src,图像的大小是400×300,图像颜色深度8位,3通道图像。

2.再看一个结构体CvScalar:

CvScalar就是一个包含四个元素的结构体变量。

CvScalar定义可存放1—4个数值的数值,其结构如下。

typedef struct CvScalar
    {
         double val[4];
    }CvScalar;

================================================================

CvScalar pt;

如果使用的图像是1通道的,则pt.val[0]中存储数据

如果使用的图像是3通道的,则pt.val[0],pt.val[1],pt.val[2]中存储数据


补充:很多人不理解通道是什么?这里做出个人理解:所谓单通道就是一个像素点占一个字节(8位)

所以单通道图像为灰度图像,OpenCv的通道可以是1、2、3、4。而三通道即一个像素点占3个字节,

三通道的图像为彩色图像。


注意:

1.在内存中彩色图像存储顺序为BGR  不是RGB!

2.注意IplImage结构体中的widthStep分量的意思是一行图像所占的字节数。和width不一样,width指的是

   一行上的像素点数,而widthStep是一行所占的字节数(以字节为单位)。因此,通过上面说的单通道和多

   通道的区别,聪明的你肯定知道了。

===============================================================


使用cvGet2D 函数获得某个点的值,idx0=hight 行值,idx1=width 列值。
      CVAPI(CvScalar) cvGet2D( const CvArr* arr, int idx0, int idx1 );

   使用cvSet2D 函数给某个点赋值。
      CVAPI(void) cvSet2D( CvArr* arr, int idx0, int idx1, CvScalar value );
 -----------------------------------------------
由上可见,cvGet2D的返回类型和cvSet2D中value的类型都是CvScalar


下面是利用IplImage这个结构体内部变量的一个例子,目的:改变一个图像的中间一行为白色
#include <stdio.h>#include <stdlib.h>#include "opencv/cv.h"#include "opencv/highgui.h"int main(){int i,j;CvScalar pixel;IplImage* img = cvLoadImage("test.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);//我打开的图像为3通道for(i=0; i<img->width; i++){pixel = cvGet2D(img, (img->height)/2, i);//中间一行pixel.val[0] = 255;//255是白色pixel.val[1] = 0;pixel.val[2] = 0;cvSet2D(img, (img->height)/2, i, pixel);//cvSet2D设置像素点}printf("Height:%d  Width:%d\n", img->height, img->width);cvSaveImage("tmp.jpg", img, 0);cvReleaseImage(&img);return 0;}

运行后发现图像中间有一行变为全白色。


11 0
原创粉丝点击