因为要读研,而且搞的是图像方向,老师说要搞图像方向matlab和openCV是最常用的,所以在读研之前希望把代码从c#和JAVA转到c++中,并且为以后深入的学习图像打好基础。言归正传~
先利用这个小例子来简单的了解一下图像从读入内存,在内存中操作图像,在屏幕上显示,最终存到硬盘上的全部过程走一遍。本人喜欢把写出的程序变成方法,利用几个必要地参数来进行调用,可以防止以后代码越来越多,让自己看不懂。
1.首先介绍几个结构体
【1】IplImage:Intel Image Processing Library (IPL)
百度百科上说这是最重要的一个结构体了,因为这个类型就相当于C#中的BitMap或一个二维数组来表示这个图像,只是openCV有个专属的结构而已。
【2】CvSize:
typedef struct CvSize
{
int width; /* 矩形宽 */
int height; /* 矩形高 */
}CvSize;
其实就是定义长、宽的一个结构,为什么要用它,自己定义不好么?在创建图像的时候需要图像的长、宽,这里就需要CvSize做参数了。
2.常用的函数介绍
①图像载入函数(把硬盘上的图像文件读入内存中)
函数cvLoadImage载入指定图像文件,并返回指向该文件的IplImage指针。函数支持bmp、jpg、 png、 tiff等格式的图像。
其函数原型如下:
IplImage* cvLoadImage( const char* filename, int iscolor);
其中,filename 是待载入图像的名称,包括图像的扩展名;iscolor是一个辅助参数项,可选正数、零和负数三种值,正数表示作为三通道(CV_LOAD_IMAGE_COLOR)图像载入,零(CV_LOAD_IMAGE_GRAYSCALE)表示该图像作为单通道图像,负数(CV_LOAD_IMAGE_UNCHANGED)表示载入图像的通道数由图像文件自身决定。
②创建图像(创建首地址并分配存储空间)
其函数原型如下:
IplImage* cvCreateImage( CvSize size, int depth, int channels );
创建图像需要先选定个CvSize的长、宽来确定图像的形状大小。
图像的深度:图像深度是指存储每个像素所用的位数,也用于量度图像的色彩分辨率。
depth 图像元素的位深度,可以是下面的其中之一:
IPL_DEPTH_8U - 无符号8位整型
IPL_DEPTH_8S - 有符号8位整型
IPL_DEPTH_16U - 无符号16位整型
IPL_DEPTH_16S - 有符号16位整型
IPL_DEPTH_32S - 有符号32位整型
IPL_DEPTH_32F - 单精度浮点数
IPL_DEPTH_64F - 双精度浮点数
图像的通道数:灰度图的通道数为1,彩色图的通道为3,描述一个像素点,如果是灰度,那么只需要一个数值来描述它,就是单通道。如果一个像素点,有RGB三种颜色来描述它,就是三通道
③窗口定义函数(图片要用相框,窗口就是这个相框)
函数cvNamedWindow定义一个窗口,用于显示图像。其函数原型如下:
int cvNamedWindow( const char* name, unsigned long flags );
其中,name是窗口名,flags是窗口属性指标值,可以选择CV_WINDOW_AUTOSIZE和0两种值。CV_WINDOW_AUTOSIZE表示窗口尺寸与图像原始尺寸相同,0表示以固定的窗口尺寸显示图像。一般相框都是和相片匹配啦。
④图像显示函数(终于可以显示了,显示是指定相框是哪个,照片是哪个,他们的组合展示到屏幕上)
函数cvShowImage是在指定的窗口中显示图像,其函数原型如下:
void cvShowImage( const char* name, const CvArr* image );
其中,name是窗口名称,image是图像类型指针,一般是IplImage指针
⑤图像保存函数(内存中的图像保存到硬盘上)
函数cvSaveImage以指定的文件名保存IplImage类型的指针变量,其函数原型如下:
int cvSaveImage( const char* filename, const CvArr* image );
其中,filename是图像保存路径和名称,image是IplImage指针变量。
如果不输入路径就是直接存储在当前工程文件下。
⑥图像销毁函数
函数cvReleaseImage销毁已定义的IplImage指针变量,释放占用内存空间。
其函数原型如下:
void cvReleaseImage( IplImage** image );
其中,image为已定义的IplImage指针。在使用完图像之后要把其销毁,和释放指针是一样道理。
3.疑惑
~到底IplImage类型是怎么个形式?任意位置的像素点怎么操作?
~放缩时候像素点的转换的本质是什么?图片缩小像素点应该变少,因为最终的文件大小也相应的变小了,但是变换的程度和放缩的比例好像不成正比,这其中是个什么关系?
#include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> using namespace cv; using namespace std; int main() { void ImageZoom(char *,float,char *); ImageZoom("lenna.jpg",0.314,"lenna缩放图.jpg"); return 0; } //图片缩放方法 /*1、原图片和缩放之后的图片的展示 2、肯以根据参数来进行长宽的倍数调整 3、最后保存至当前项目中,名字叫ImageName缩放图 */ void ImageZoom(char *ImageName,float scale,char *SaveName) { const char *pstrWindowsSrcTitle = "原图"; const char *pstrWindowsDstTitle = "缩放图"; double fScale = 0.3; //缩放倍数 CvSize czSize; //目标图像尺寸 //从文件中读取图像 IplImage *pSrcImage = cvLoadImage(ImageName,CV_LOAD_IMAGE_UNCHANGED); IplImage *pDstImage = NULL; //计算目标图像大小 czSize.width = pSrcImage->width * fScale; czSize.height = pSrcImage->height * fScale; //创建图像并缩放 pDstImage = cvCreateImage(czSize, pSrcImage->depth, pSrcImage->nChannels); cvResize(pSrcImage, pDstImage,CV_INTER_AREA); //创建窗口 cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE); cvNamedWindow(pstrWindowsDstTitle, CV_WINDOW_AUTOSIZE); //在指定窗口中显示图像 cvShowImage(pstrWindowsSrcTitle, pSrcImage); cvShowImage(pstrWindowsDstTitle, pDstImage); //等待按键事件 cvWaitKey(); //保存图片,在使用之后要销毁窗口和图片 cvSaveImage(SaveName,pDstImage); cvDestroyWindow(pstrWindowsSrcTitle); cvDestroyWindow(pstrWindowsDstTitle); cvReleaseImage(&pSrcImage); cvReleaseImage(&pDstImage); }