Win7 Win8 Win10系统。
opencv的安装路径为默认。
电脑为 64 位。
VC6.0++的安装路径可以改变,但是Opencv的安装路径最默认,不要改变其安装路径,不然会很麻烦。
右键我的电脑->属性->高级系统设置->环境变量->用户变量的Path添加 C:\Program Files (x86)\OpenCV\bin;
工具->选项->目录
选择Include files
文件->新建->工程->Win32 Console Application 然后给 工程命名、位置。
然后在弹出来的窗口 选择“一个Hello,World!”程序。这样就创建成功了。
cxcore.lib cv.lib ml.lib cvaux.lib highgui.lib cvcam.lib
(要注意打空格,否则会导致字母相连,否则会出问题)。
#include "stdafx.h" #include<cv.h> #include<highgui.h> int main(int argc, char* argv[]) { cvNamedWindow("name"); IplImage* img = cvLoadImage(".\\timg.jpg"); cvShowImage("name",img); cvWaitKey(0); return 0; }注意:《图片路径要改的》。
(如果是安装 配置成功的话,会弹出来一个窗口)。
函数原型:
int cvNamedWindow( const char* name, int flags=CV_WINDOW_AUTOSIZE );
name :
窗口的名字,它被用来区分不同的窗口,并被显示为窗口标题。
flags :
窗口属性标志。目前唯一支持的标志是CV_WINDOW_AUTOSIZE。当这个标志被设置后,用户不能手动改变窗口大小,窗口大小会自动调整以适合被显示图像(参考cvShowImage)。
函数cvNamedWindow创建一个可以放置图像的窗口。被创建的窗口可以通过它们的名字被引用。
如果已经存在这个名字的窗口,这个函数将不做任何事情。
函数原型:
IplImage* cvLoadImage( const char* filename, filename ,int flags=CV_LOAD_IMAGE_COLOR)
flags :
指定读入图像的颜色和深度: );
filename :
要被读入的文件的文件名。
flags :
指定读入图像的颜色和深度:默认为 1,是图片按照本身的大小。int flags=CV_LOAD_IMAGE_COLOR 这句话不用深究,只需要记着默认参数为1,图片大小为本身即可。
函数原型:
void cvShowImage( const char* name, const CvArr* image );name:
窗口的名字。
image:函数cvShowImage 在指定窗口中显示图像。如果窗口创建的时候被设定标志CV_WINDOW_AUTOSIZE,那么图像将以原始尺寸显示;否则,图像将被伸缩以适合窗口大小。
函数原型:
int cvWaitKey( int delay=0 );
delay :
延迟的毫秒数。
函数cvWaitKey无限制的等待按键事件(delay<=0时);或者延迟"delay"毫秒。返回值为被按键的值,如果超过指定时间则返回-1。
函数原型:
void cvDestroyWindow( const char* name );
name :
要被销毁的窗口的名字。
函数cvDestroyWindow销毁指定名字的窗口。
uchar R = CV_IMAGE_ELEM(image, uchar, y, nChannels * x);
uchar G = CV_IMAGE_ELEM(image, uchar, y, nChannels * x + 1);
ucahr B = CV_IMAGE_ELEM(image, uchar, y, nChannels * x + 2);
CV_IMAGE_ELEM是一个宏,用于获取图像中指定位置的数据。不过令人比较无语的是,OpenCV没有提供直接获取RGB值的方法,RGB三个值各自在内存中的位置需要程序员自己计算(最后一个参数)。
不过据说OpenCV后面扩展的C++接口提供了相应功能。。
CV_IMAGE_ELEM是一个宏,
#define CV_IMAGE_ELEM( image, elemtype, row, col ) \
(((elemtype*)((image)->imageData + (image)->widthStep*(row)))[(col)])
#define CV_MAT_ELEM( mat, elemtype, row, col ) \
(*(elemtype*)CV_MAT_ELEM_PTR_FAST( mat, row, col, sizeof(elemtype)))
但要想正确的得到图像的坐标为(x,y)点的像素值,是应该这样写CV_IMAGE_ELEM(Image, uchar, y, x)
要注意像素点的坐标xy和行列值的顺序是相反的(可以仔细思考为什么)
如果写反:CV_IMAGE_ELEM(Image, uchar, x, y),结果有时候就造成了访问image越界,从而报错。
不过将IMAGE的数据按照原来的样子复制到mat中可以这么写:
CV_IMAGE_ELEM(pImage, uchar, i, j) = CV_MAT_ELEM(*mat, uchar, i, j)
不用改变顺序
总之,当应用这个宏是如果老报错,就试试换个顺序,或者检查访问的地址是否越界。
为什么乘以3,这里就涉及到傅里叶图像变换了。
想要了解的可以看一下:
http://wenku.baidu.com/link?url=hIQA_vb0A4-JWDD7x6kt79nfQJuSGnditjpEXvcPI4R6esSi33Y8nHRDGuFGCuoIq0y1wULJnozRc9WARcz_7w2UogRV958bG6IQotvTIC_&qq-pf-to=pcqq.c2c
#include "stdafx.h" #include<cv.h> #include<highgui.h> int main(int argc, char* argv[]) { int i,j,b,g,r; IplImage *img,*bg; img=cvLoadImage(".\\timg.jpg"); //要显示的图片 bg=cvLoadImage(".\\bg.jpg"); //背景图 int posx=10,posy=10; //posx 和poxy是 从背景图的何处开始显示要显示的图片,坐上角为 0 0,(即距离背景图的左上 // 角X方向10个像素点,y方向 10个像素点的位置开始显示要显示的图片) for(i = 0; i < img->height/2; i++) { // img图片显示一半,i 为0 到img->height/2,含义:img像素点从0 ,到img->height/2的位置都要进行显示 for(j = 0; j < img->width/2; j++) { b=CV_IMAGE_ELEM(img,uchar,i,j*3+0); g=CV_IMAGE_ELEM(img,uchar,i,j*3+1); r=CV_IMAGE_ELEM(img,uchar,i,j*3+2); //得到img 的RGB值 CV_IMAGE_ELEM(bg,uchar,i+posy,(j+posx)*3+0)=b; CV_IMAGE_ELEM(bg,uchar,i+posy,(j+posx)*3+1)=g; CV_IMAGE_ELEM(bg,uchar,i+posy,(j+posx)*3+2)=r; //这些代码只需要记住就可以了,不用 深究。 //意思是,先得到img的RGB值,然后将其赋给特定位置的BG图的RGB。这样 就显示上去了。 // RGB是工业上 的一种颜色标准, //是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的, //RGB即是代表红、绿、蓝 // 三个通道的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一 } } cvNamedWindow("飞机大战"); cvShowImage("飞机大战",bg); cvWaitKey(0);//暂停 cvDestroyWindow("飞机大战"); cvWaitKey(0); return 0; }
注意:《图片路径要改的》。
一、在背景图上显示另一 张图的时候显示的位置超过了背景图的大小:
造成程序崩溃。例如:背景图的大小为 500×500,如果 非要img图片在背景图上 的显示为位置为:700×700,就会造成崩溃。因为你在 试图找到一个根本找不到的位置。
二、要显示在背景图上的图片大小大于背景图:
造成 程序崩溃。原因:与上面差不多。
原理:
首先将背景图复制一份,那么我们就可以将复制 图从下到上(或者 从上到下)一点点的覆盖原图如果覆盖完了,就从头开始执行此过程即可。
图片演示:
那么 我们 就可以使用 十分接近的图来模糊人的肉眼感官,造成图片滚动的错觉。
滚动代码:
#include "stdafx.h" #include "cv.h" #include "highgui.h" #include "stdio.h" int main(int argc, char* argv[]) { IplImage *backImage,*backImageClone; //将要滚动的图片克隆一份 backImage = cvLoadImage(".\\timg.jpg"); backImageClone = cvCloneImage(backImage); int speed = -1; //滚动的速度 int mpos = 0; cvNamedWindow("123"); while(true) // 动态显示 { mpos += speed; // 随着程序的运行我们计算要刷新显示的长度 if (mpos<0) { mpos = mpos+backImageClone->height; //如果超过了范围就取模归位 } for (int i = 0;i<backImage->height;i++) //将克隆图的一部部分显示在背景图,造成滚动错觉 { int ti = (mpos+i)%backImageClone->height; for (int j= 0;j<backImage->width;j++) { int b = CV_IMAGE_ELEM(backImageClone,uchar,ti,j*3); int g = CV_IMAGE_ELEM(backImageClone,uchar,ti,j*3+1); int r = CV_IMAGE_ELEM(backImageClone,uchar,ti,j*3+2); CV_IMAGE_ELEM(backImage,uchar,i,j*3) = b; CV_IMAGE_ELEM(backImage,uchar,i,j*3+1) = g; CV_IMAGE_ELEM(backImage,uchar,i,j*3+2) = r; } } cvWaitKey(20); //每20毫秒更新一次显示 cvShowImage("123",backImage); } printf("Hello World!\n"); return 0; }
这样就ok了。
注意:《图片路径要改的》。