opencv从入门到精通(4)--IplImage数据结构
2016-01-25 11:00
381 查看
前面讲了CvMat矩阵结构,下面介绍IplImage,本质上讲IplImage也是CvMat结构,但是它还有一些成员将矩阵解释为图像。
其中比较重要的变量是width,height,depth,Channels,imageData和widthStep。前两个和矩阵一样,depth和nChannels在矩阵中写在一起,这里则分开表示。depth即数据类型主要有6个,在第一篇里遇到过:
IPL_DEPTh_8U 无符号8位整数
IPL_DEPTh_8S 有符号8位整数
IPL_DEPTh_16S 有符号16位整数
IPL_DEPTh_32S 有符号32位整数
IPL_DEPTh_32F 有符号32位浮点数单精度
IPL_DEPTh_64F 有符号64位浮点数双精度
nChannels即通道数可取1,2,3和4。imageData包含指向图像第一行的指针。widthStep即每行的字节数。
另一个比较主要的成员是origin,用于设置坐标原点位于图像的左上角(参数IPL_ORIGIN_TL)还是左下角(参数IPL_ORIGIN_BL)。
最后介绍感兴趣的区域–ROI,实际上是图像的一个子图,设定了ROI之后,opencv里的函数便只对子图里的像素进行处理。
下面举一个看例子,输入是3通道RGB图像,输出它的绿色通道图像。
运用widthStep。效果和ROI相同,但是有时候设置ROI需要不断重置,用widthStep更为高效。
IplImage结构
IplImage头结构:
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;
其中比较重要的变量是width,height,depth,Channels,imageData和widthStep。前两个和矩阵一样,depth和nChannels在矩阵中写在一起,这里则分开表示。depth即数据类型主要有6个,在第一篇里遇到过:
IPL_DEPTh_8U 无符号8位整数
IPL_DEPTh_8S 有符号8位整数
IPL_DEPTh_16S 有符号16位整数
IPL_DEPTh_32S 有符号32位整数
IPL_DEPTh_32F 有符号32位浮点数单精度
IPL_DEPTh_64F 有符号64位浮点数双精度
nChannels即通道数可取1,2,3和4。imageData包含指向图像第一行的指针。widthStep即每行的字节数。
另一个比较主要的成员是origin,用于设置坐标原点位于图像的左上角(参数IPL_ORIGIN_TL)还是左下角(参数IPL_ORIGIN_BL)。
最后介绍感兴趣的区域–ROI,实际上是图像的一个子图,设定了ROI之后,opencv里的函数便只对子图里的像素进行处理。
访问IplImage数据
与访问矩阵数据的区别在于起始位置指针imgdata是字节类型的,不需要像矩阵数据那样进行转换。指针换算的公式,对于一个宽为img->width,高为img->height的c通道图像,每行的字节长度为img-widthStep,矩阵头的指针为img->imageData,那么a行b列i通道变量的位置为(uchar * )(img->imageData+a * img-widthStep+b*c+i)。下面举一个看例子,输入是3通道RGB图像,输出它的绿色通道图像。
#include <stdio.h> #include <fstream> #include<iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include "cv.h" using namespace cv; using namespace std; //把红蓝通道的数据置0 void saturate_sv( IplImage* img ) { for( int y=0; y<img->height; y++ ) { uchar* ptr = (uchar*) (img->imageData + y * img->widthStep); for( int x=0; x<img->width; x++ ) { ptr[3*x+0] =0; ptr[3*x+2] = 0; } } } int main( ) { IplImage* img = cvLoadImage( "a1.ppm"); cvNamedWindow("window1", CV_WINDOW_AUTOSIZE ); cvNamedWindow("window2", CV_WINDOW_AUTOSIZE ); cvShowImage("window1", img ); saturate_sv(img); cvShowImage("window2", img ); cvWaitKey(0); cvReleaseImage( &img ); cvDestroyWindow("window1"); cvDestroyWindow("window2"); return 0; }
用ROI和widthStep设定感兴趣的区域
ROI的使用通过void cvSetImageROI(IplImage * image,CvRect rect)和void cvResetImageROI(IplImage * image)两个函数,前者设定ROI,后者取消ROI。#include <stdio.h> #include <fstream> #include<iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include "cv.h" using namespace cv; using namespace std; int main() { IplImage* src=cvLoadImage("a1.ppm",1); IplImage* dic=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3); cvCopy(src,dic); cvNamedWindow("pre", CV_WINDOW_AUTOSIZE); cvNamedWindow("post1", CV_WINDOW_AUTOSIZE); cvNamedWindow("post2", CV_WINDOW_AUTOSIZE); cvShowImage( "pre", src); cvSetImageROI(src, cvRect(200,300,400,200));//在点(200,300)开始选择大小为400 *200的区域 cvSetImageROI(dic, cvRect(200,300,400,200)); cvAddS(src, cvScalar(255,0,0),dic);//src每个像素的RGB值加上dic输出dic cvShowImage( "post1",dic); cvSaveImage("a2.ppm",dic); cvResetImageROI(src); cvResetImageROI(dic); cvShowImage( "post2",dic); cvWaitKey(); cvReleaseImage( &src ); cvReleaseImage( &dic ); cvDestroyWindow("pre"); cvDestroyWindow("post1"); cvDestroyWindow("post2"); return 0; }
运用widthStep。效果和ROI相同,但是有时候设置ROI需要不断重置,用widthStep更为高效。
#include <stdio.h> #include <fstream> #include<iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include "cv.h" using namespace cv; using namespace std; int main() { IplImage* src=cvLoadImage("a1.ppm",1); IplImage *dic = cvCreateImageHeader( cvSize(400, 200), src->depth, src->nChannels );//该函数不分配内存,设定大小为400*200的区域 dic->origin = src->origin; dic->widthStep = src->widthStep; dic->imageData = src->imageData + 300 * src->widthStep + 100 * src->nChannels;//设定区域起始位置 cvAddS(dic, cvScalar(100,34,23),dic); cvNamedWindow("pre", CV_WINDOW_AUTOSIZE); cvNamedWindow("post1", CV_WINDOW_AUTOSIZE); cvNamedWindow("post2", CV_WINDOW_AUTOSIZE); cvShowImage( "pre", src); cvShowImage( "post1",dic); cvShowImage( "post2",src); cvSaveImage("a3.ppm",dic); cvWaitKey(); cvReleaseImage( &src ); cvReleaseImageHeader(&dic); cvDestroyWindow("pre"); cvDestroyWindow("post1"); cvDestroyWindow("post2"); return 0; }
相关文章推荐
- PHP GD 图像处理组件的常用函数总结
- PHP图像处理之imagecreate、imagedestroy函数介绍
- jsvascript图像处理―(计算机视觉应用)图像金字塔
- Javascript图像处理思路及实现代码
- python中使用OpenCV进行人脸检测的例子
- opencv 做人脸识别 opencv 人脸匹配分析
- 使用opencv拉伸图像扩大分辨率示例
- PHP图像处理之使用imagecolorallocate()函数设置颜色例子
- java数字图像处理基础使用imageio写图像文件示例
- 使用Java进行图像处理的一些基础操作
- javascript图像处理―边缘梯度计算函数
- Javascript图像处理―阈值函数实例应用
- Javascript图像处理―虚拟边缘介绍及使用方法
- 基于C++实现kinect+opencv 获取深度及彩色数据
- OpenCV 2.4.3 C++ 平滑处理分析
- PHP图像处理类库及演示分享
- php图像处理函数大全(推荐收藏)
- Javascript图像处理―图像形态学(膨胀与腐蚀)
- Javascript图像处理―平滑处理实现原理
- 利用Python和OpenCV库将URL转换为OpenCV格式的方法