《学习opencv》笔记——IplImage数据结构

1.IplImage数据结构


(1)IplImage的结构


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


(2)访问数据图像

imageData里存放的是HSV空间数据,所以下面的程序是将S和V部分加满。


#include <cv.h>
#include <highgui.h>
#include <iostream>
using namespace std;

int main(int argc, char** argv)
{
	IplImage* img = cvLoadImage("460.jpg");
	void saturate_sv(IplImage *img);
	saturate_sv(img);
	cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE );
	cvShowImage("Example1", img );
	cvWaitKey(0);
	cvReleaseImage( &img );
	cvDestroyWindow("Example1");
	return 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+1] = 255;
		ptr[3*x+2] = 255;
		}
	}
}


加满S和V后的结果为




(3)对ROI和widthStep的补充

ROI和widthStep在实际工作中有很重要的作用,在很多情况下,使用它们会提高计算机视觉代码的执行速度。这是因为它们运行对图像的某一小部分进行操作,而不是对整个图像进行运算。

实例代码,利用imageROI来增加某范围的像素


#include <cv.h>
#include <highgui.h>
#include <iostream>
using namespace std;

int main(int argc, char** argv)
{

	IplImage* src;
	if( ((src=cvLoadImage("460.jpg")) != 0 ))
	{
		int x = atoi("80");
		int y = atoi("150");
		int width = atoi("270");
		int height = atoi("250");
		int add = atoi("-100");
		cvShowImage( "大脸猫", src);
		cvSetImageROI(src, cvRect(x,y,width,height));
		cvAddS(src, cvScalar(add),src);
		cvResetImageROI(src);
		cvShowImage( "大脸猫1",src);
		cvWaitKey();
	}
	cvReleaseImage( &src );  
	return 0;
}


显示结果:




利用widthStep方法同样可以把选中区域内所有像素的值加200


#include <cv.h>
#include <highgui.h>
#include <iostream>
using namespace std;

int main(int argc, char** argv)
{

	IplImage* interest_img;
	CvRect interest_rect;
	if( ((interest_img=cvLoadImage("460.jpg")) != 0 ))
	{
		interest_rect.x = atoi("80");
		interest_rect.y = atoi("150");
		interest_rect.width = atoi("270");
		interest_rect.height = atoi("250");
		int add = atoi("1");


		IplImage *sub_img = cvCreateImageHeader(
			cvSize(
			interest_rect.width, 
			interest_rect.height
			),
			interest_img->depth, 
			interest_img->nChannels
			);

		sub_img->origin = interest_img->origin;

		sub_img->widthStep = interest_img->widthStep;

		sub_img->imageData = interest_img->imageData + 
			interest_rect.y * interest_img->widthStep  +
			interest_rect.x * interest_img->nChannels;

		cvAddS( sub_img, cvScalar(add), sub_img );

		cvReleaseImageHeader(&sub_img);

		cvShowImage( "大脸猫22", interest_img );
		cvWaitKey();
	}
	return 0;
}


实验结果:




看起来ROI的方法更方便些,为什么还要使用widthStep呢?原因在于有些时候在处理过程中,想在操作过程中设置和保持一幅图像的多个子区间处于活动状态,但是ROI只能串行处理并且必须不断地设置和重置。所以在实际工作中widthStep更好。


 to be continued




发布了129 篇原创文章 · 获赞 61 · 访问量 47万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览