参考网址:
从文件中读入一幅图像,将之反色,然后显示出来。
// HelloOpenCV.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <math.h>
#include <cv.h>
#include <highgui.h>
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
int main(int argc, _TCHAR* argv[])
{
IplImage* img = 0;
int height,width,step,channels;
uchar *data;
int i,j,k;
const char * imagePath = "C:\\Users\\lenmovo\\Pictures\\Lena.jpg";
// load an image
img=cvLoadImage(imagePath);
if(!img){
printf("Could not load image file: %s\n",argv[1]);
exit(0);
}
// get the image data
height = img->height;
width = img->width;
step = img->widthStep;
channels = img->nChannels;
data = (uchar *)img->imageData;
printf("Processing a %dx%d image with %d channels\n",height,width,channels);
// create a window
cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
cvMoveWindow("mainWin", 300, 100);
// invert the image
// 相当于 cvNot(img);
//IplImage *pDstImg = cvCreateImage(cvGetSize(img),img->depth,img->nChannels);
//cvNot(img, pDstImg);
for(i=0;i<height;i++) for(j=0;j<width;j++) for(k=0;k<channels;k++)
data[i*step+j*channels+k]=255-data[i*step+j*channels+k];
//for(i=0;i<height;i++)
// for(j=0;j<step;j++)
// data[i*step+j]=255-data[i*step+j];
// show the image
//cvShowImage("mainWin", pDstImg );//显示cvNot(img, pDstImg)结果
cvShowImage("mainWin", img );
// wait for a key
cvWaitKey(0);
// release the image
cvReleaseImage(&img );
cvDestroyWindow("mainWin");
return 0;
}
一. 图像类 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;
二. 用到的函数:
1. cvLoadImage(imagePath); 用于从文件中读入
img=cvLoadImage(fileName,flag);
flag: >0 将读入的图像强制转换为一幅三通道彩色图像
=0 将读入的图像强制转换为一幅单通道灰度图像
<0 读入的图像通道数与所读入的文件相同.图像支持的图像格式: BMP, DIB, JPEG, JPG, JPE, PNG, PBM, PGM, PPM, SR, RAS, TIFF, TIF
OpenCV默认将读入的图像强制转换为一幅三通道彩色图像. 不过可以按以下方法修改读入方式:
2. cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
int cvNamedWindow( const char* name, int flags=CV_WINDOW_AUTOSIZE );
name 为窗口的名字,用来区分不同的窗口,并被显示为窗口标题。
flags 窗口属性标志。可以选择CV_WINDOW_AUTOSIZE(1)和0两种值。
CV_WINDOW_AUTOSIZE这个标志被设置后, 如果用户不能手动改变窗口大小,窗口大小会自动调整以适合被显示图像(参考cvShowImage)。
0表示以固定的窗口尺寸显示图像。
函数cvNamedWindow创建一个可以放置图像和trackbar的窗口。
被创建的窗口可以通过它们的名字被引用。
如果已经存在这个名字的窗口,这个函数将不做任何事情。
3.cvMoveWindow("mainWin", 300, 100);
void cvMoveWindow( const char* name, int x, int y );
用于设定或修改名为name的窗口在屏幕中的位置。
x 窗口左上角的x坐标。
y 窗口左上角的y坐标。
4.cvShowImage("mainWin", img );
在指定窗口("mainWin")中显示图像(img)。
5.cvWaitKey(0);
此函数试图让程序等待delay ms后在继续运行其后面的语句。
若delay=0,则无限期等待,直到按下键盘任意按键。
6.cvReleaseImage(&img ); 释放图像
7.cvDestroyWindow("mainWin");销毁指定名字的窗口。
8.cvCreateImage(cvGetSize(img),img->depth,img->nChannels);
IplImage* cvCreateImage(CvSize size, int depth, int channels);size: cvSize(width,height);
depth: 像素深度: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,
IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F, IPL_DEPTH_64F
channels: 像素通道数. Can be 1, 2, 3 or 4.
各通道是交错排列的. 一幅彩色图像的数据排列格式如下:
b0 g0 r0 b1 g1 r1 ...
9.cvNot(img, pDstImg);
cvNot(const CvArr* src,CvArr* dst) 函数会将src中的每一个元素的每一位取反,然后把结果赋给dst。
补充:IplImage由CvMat派生,而CvMat由CvArr派生即CvArr -> CvMat -> IplImage
三. 取反操作
for(i=0;i<height;i++)
for(j=0;j<width;j++)
for(k=0;k<channels;k++)
data[i*step+j*channels+k]=255-data[i*step+j*channels+k];
在上面的cvCreateImage函数说明中提到各通道是交错排列的,所以其中k为第k个通道,step = channels*width。
上面代码可以用
for(i=0;i<height;i++)
for(j=0;j<step;j++)
data[i*step+j]=255-data[i*step+j];
替换,也就是对各通道不做区分一致处理。