opencv学习(六)书本《学习Opencv》(中文版)第四章的作业答案第二题(opencv3.0.0+VS2012+win7)

来源:互联网 发布:笛子软件下载 编辑:程序博客网 时间:2024/04/30 09:54

显示坐标很简单,但是显示RGB就必须要非常了解IPlImage结构如何获取数据了,书上讲的非常繁杂,下面仔细分析一下IPlImage结构,

opencv最重要的结构体是IplImage结构。从本质上讲,这是一个CvMat对象,但它还有一些其他成员变量将矩阵解释为图像

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通道图像。


关键在这一句:

uchar* bgr = (uchar*)Img->imageData + Img->widthStep * point.y + Img->nChannels * point.x;//获取某个像素点
大神的分析:

你应该是刚学opncv吧,widthstep是指图像每行所占的字节数,主要要和width区别,width是指每行所含的像素个数,但是一个像素也可能占一个字节,也可能占三个字节或者四个.imagedata是指向存储图像像素值数组的指针,内容是这个数组的首地址,point.y指的是像素点的行坐标,所以Img->imageData + Img->widthStep*point.y便是该像素点所在行的首地址,然后再加上该像素点所在的列,即point.x,就得到了该像素点的地址.


真大神:http://www.cnblogs.com/uriboyka/archive/2013/04/23/3038788.html

假设你要访问第K通道,第i行,第j列的像素

一 间接访问:(通用,但效率低,可访问任意格式的图像)

对于单通道字节型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); CvScalar s; s=cvGet2D(img,i,j); /* get the (j,i) pixel value, 注意cvGet2D与cvSet2D中坐标参数的顺序与其它opencv函数坐标参数顺序恰好相反.本函数中i代表y轴,即height;j代表x轴,即weight.也即先cvGet2D的第二个参数i表示行号,第三个参数j表示列号。而元素的坐标值的(j,i) printf("intensity=%f\n",s.val[0]);*/ s.val[0]=111; cvSet2D(img,i,j,s); // set the (j,i) pixel value设置像素值

对于多通道字节型/浮点型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); CvScalar s; s=cvGet2D(img,i,j); // get the (j,i) pixel value printf("B=%f, G=%f, R=%f\n",s.val[0],s.val[1],s.val[2]); s.val[0]=111; s.val[1]=111; s.val[2]=111; cvSet2D(img,i,j,s); // set the (j,i) pixel value

二 直接访问:(效率高,但容易出错)

对于单通道字节型图像:

1 IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); 2 ((uchar *)(img->imageData + i*img->widthStep))[j]=111;
对于多通道字节型图像:

1 IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3); 2 ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B 3 ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G 4 ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R

对于多通道浮点型图像:

1 IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); 2 ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B 3 ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G 4 ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R

 

三 基于指针的直接访问:(简单高效)

对于单通道字节型图像:

1 IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); 2 int height      = img->height; 3 int width       = img->width; 4 int step        = img->widthStep; 5 uchar* data    = (uchar *)img->imageData; data[i*step+j] = 111;

对于多通道字节型图像:

复制代码
1 IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3); 2 int height      = img->height; 3 int width       = img->width; 4 int step        = img->widthStep; 5 int channels   = img->nChannels; 6 uchar* data    = (uchar *)img->imageData; 7 data[i*step+j*channels+k] = 111;
复制代码

对于多通道浮点型点型图像(假设图像数据采用4字节(32位)行对齐方式):

复制代码
1 IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); 2 int height     = img->height; 3 int width      = img->width; 4 int step       = img->widthStep; 5 int channels = img->nChannels; 6 float * data    = (float *)img->imageData; 7 data[i*step+j*channels+k] = 111;
复制代码

由此可以知道第二题找到BGR像素值就不难了

源码如下:

#include "cv.h"  #include "highgui.h"  #include<string>#include<iostream>#include<cstdio>using namespace std;void my_mouse_callback(int event, int x, int y, int flags, void* param);  void putText(IplImage* image, CvPoint point); void putText2(IplImage* image, CvPoint point); CvPoint point;int main(int argc, char** argv){  cvNamedWindow("taenshow",CV_WINDOW_AUTOSIZE);     IplImage* image = cvLoadImage(argv[1]);      cvShowImage("taenshow",image);while(1){cvSetMouseCallback("taenshow",my_mouse_callback,(void*)image);  char c = (char)cvWaitKey(33);        if( c == 27 ) break;  }    return 0;  }    void my_mouse_callback(int event, int x, int y, int flags, void* param)  {      IplImage* img = (IplImage*)param;  switch(event){case CV_EVENT_LBUTTONDOWN :point.x = x;point.y = y;putText(img,point);break;case CV_EVENT_RBUTTONDOWN:point.x=x;point.y=y;putText2(img,point);break;  }}    void putText(IplImage* image, CvPoint point)  {  char color[100],px[100],py[100];_itoa(point.x,px,10);//整数转换成字符串;_itoa(point.y,py,10);//整数转换成字符串;strcpy(color,"("); strcat(color,px);strcat(color,",");strcat(color,py);strcat(color,")"); CvFont font ;    cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX,0.5,0.5,0);      cvPutText(image,color,point,&font,cvScalar(0,0,255));  //BGR    cvShowImage("taenshow",image);}void putText2(IplImage* Img,CvPoint point)//鼠标左键显示颜色值RGB{     //定义bgr接受像素颜色信息 uchar* bgr = (uchar*)Img->imageData + Img->widthStep * point.y + Img->nChannels * point.x;//获取某个像素点,直接访问//CvScalar s = cvGet2D(Img,point.x,point.y);//获取像素点为(x,y)点的BGR的值,貌似有问题,在某些像素点报错?char color[100];//显示颜色值字符串char cb[16],cg[16],cr[16];//单个颜色值字符串  //sprintf_s(cb,"%f",bgr[0]);//double转string//sprintf_s(cg,"%f",bgr[1]);//sprintf_s(cr,"%f",bgr[2]);_itoa(bgr[0],cb,10);//int转string_itoa(bgr[1],cg,10);_itoa(bgr[2],cr,10);   //_itoa(s.val[0],cb,10);//_itoa(s.val[1],cg,10);//_itoa(s.val[2],cr,10); strcpy(color,"("); strcat(color,cb);strcat(color,",");strcat(color,cg);strcat(color,",");strcat(color,cr);strcat(color,")"); //初始化显示字体CvFont font;    cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX,0.5,0.5);      //颜色信息显示    cvPutText(Img,color,cvPoint(point.x,point.y),&font,CV_RGB(255,255,0)); //BGR    cvShowImage("taenshow",Img);}


0 0
原创粉丝点击