您的位置:首页 > 运维架构

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

2015-08-06 09:41 399 查看
显示坐标很简单,但是显示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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: