初次接触OpenCV 笔记(程序综合设计课程——贪吃蛇游戏)

在这次学习OpenCV写贪吃蛇代码的过程中,好几次自己不知道怎么了VC就崩了,或者是自己写的东西不能运行了。因为自己是把一个一个版本复制再编的,有时还会回以前的版本修改些内容发现一遇到这种情况就会出错,今天才搞明白原因……都是预编译头文件惹的祸,想想自己还是XXX,这点常识都不懂……
 
环境:VC
执行:编译程序
问题描述:Cannot open precompiled header file: 'Debug/****.pch': No such file or directory
解决方案:
①可以使用右键点击项目工程中的该cpp文件,选择setting,在c/c++栏,选择PreCompiled headers,然后设置第一选项,选择不使用预编译头,解决这个问题。     
 
②在菜单->工程(project)->设置(settings)->c/c++ ->在category下选 ->预编译头文件(precompiled headers)->选不使用预编译头文件(Not using precompiled headers)
 
 


 
项目设置
每创建一个将要使用OpenCV的VC Project,都需要给它指定需要的lib。
1.菜单:Project->Settings,然后将Setting for选为All Configurations
2.然后选择右边的link标签,在Object/library modules附加上 
cxcore.lib cv.lib ml.lib cvaux.lib highgui.lib cvcam.lib
如果你不需要这么多lib,你可以只添加你需要的lib。 
 
动态库设置:
   OPenCV启动时需要一些动态库的支持,这些动态库必须放在系统目录下或者当前目录下。有时有些下载的代码无法运行,就是编译器找不到这些动态链接库,只要放在当前目录就即可。
 
Cv097.dll,cvaux097.dll,cvcam097.dll,cxcore097.dll, highguid097.dll,libguide40.dll 
 
头文件:
#include "stdafx.h"
#define WIN32_LEAN_AND_MEAN       //建议加上:不需加载MFC所需的模块
#include"stdio.h"
#include"cv.h"
#include"highgui.h"


编写任何.cpp文件 首先要包含stdafx.h
 
 
 
部分基本函数:
cvNamedWindow("X");//,CV_WINDOW_AUTOSIZE);//,0);用于在屏幕上创建一个窗口,函数中的第一个参数指定了该窗口的窗口标题,若需要使用其他函数与该窗口进行交互时,即使用该参数值引用这个窗口。函数中的第二个参数定义了窗口的属性,该参数可以被设置为0(默认值)或CV_WINDOW_AUTOSIZE。
 
 cvLoadImage(要被读入的文件的文件名,指定读入图像的颜色和深度)从文件中读取图像  
颜色:转为3信道(CV_LOAD_IMAGE_COLOR), 单信道 (CV_LOAD_IMAGE_GRAYSCALE), 或者保持不变(CV_LOAD_IMAGE_ANYCOLOR)。
-1默认读取图像的原通道数 0强制转化读取图像为灰度图       1
深度:转为每个颜色信道每象素8位,或者同输入的图像一样保持不变。
+++++++++++++++载入最真实的图像,选择CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR。
函数cvLoadImage从指定文件读入图像,返回读入图像的指针。
 
 cvWaitKey()函数的功能是使程序暂停,等待用户触发一个按键操作。如果将该函数参数设为一个正数,则程序将暂停一段时间,时间长度为该整数值个毫秒单位,然后继续执行程序,即使用户没有按下任何按键。当设置该函数参数为0或者负数时,程序将一直等待用户触发按键操作。
 
*********************           int main(int argc, char* argv[])
 
 
 
 cvReleaseImage()函数在用完加载到内存的文件后可以用来释放为文件分配的内存,在对cvReleaseImage()函数的调用执行完毕后,img指针将被设置为空。


 cvDestoryWindow()函数用来关闭窗口,同时释放为该窗口所分配的所有内存。
 
//** cvNamedWindow("GAME--TanChiShe",CV_WINDOW_AUTOSIZE);  //改成0 cvResizeWindow("GAME--TanChiShe",10,10);
 //cvResizeWindow("GAME--TanChiShe",750,600);
 
 
 
 
蛇头图像  逐个像素绘制到背景图像的特定位置,在加载背景图像。

灰度
CV_IMAGE_ELEM(image,uchar,y,x)
彩色
CV_IMAGE_ELEM(image,uchar,y,3*x+1)
 
 
设置窗口位置
cvMovewindow("win1",100,100);
改变窗口大小
cvResizeWindow("win1",100,100);
以下两个属性才可以
cvNamedWindow("GAME--TanChiShe",0);
cvResizeWindow("GAME--TanChiShe",10,10);
 
 
 //绘制蛇头
 for(i=0;iheight;i++)
 {
  for(j=0;jwidth;j++)
  {
   //将图片的3个通道存入r,g,b
   r = CV_IMAGE_ELEM(Shetou , uchar , i ,j*3);
   g = CV_IMAGE_ELEM(Shetou , uchar , i ,j*3+1);
   b = CV_IMAGE_ELEM(Shetou , uchar , i ,j*3+2);
   
   if( r < 230 && g < 230 && b <230 )  //接近白色部分不贴
   {
    //将图片贴到背景图片上
    CV_IMAGE_ELEM(Beijing ,uchar , i ,j*3) = r;
    CV_IMAGE_ELEM(Beijing ,uchar , i ,j*3+1) = g;
    CV_IMAGE_ELEM(Beijing ,uchar , i ,j*3+2) = b;
   }
  }
 }
 
 
1.背景图片
 //复制图片
 TmpBeijing=cvCreateImage(cvGetSize(Beijing),Beijing->depth,Beijing->nChannels);
 cvCopy(Beijing,TmpBeijing,NULL);
*****注意函数cvCopy()!!!
 
2.改变蛇的位置
 
 for(int i = shelong;i > 0;i--)
 { 
  move[i]=move[i-1];
 } 
 


 while(1){
  
  int key=cvWaitKey(0);
  switch(key)
  {
   case 'a':
   case 'A':
    shetou.Moveleft();
    DrawBeijing();
    break;


   case 'w':
   case 'W':
    shetou.Moveup();
    DrawBeijing();
    break;


   case 's':
   case 'S':
    shetou.Movedown();
    DrawBeijing();
    break;


   case 'd':
   case 'D':
    shetou.Moveright();
    DrawBeijing();
    break;
  } 
  


3.控制蛇一直运动
 
void Shetou::Change()



 for(int i = shelong;i > 0;i--)
 { 
  move[i]=move[i-1];
 } 
 
}


 if(key == 27)
   exit(0);     // 按esc键退出循环
 


初始化蛇果:
随机函数 rand  种子srand
srand((unsigned)time(NULL));    //初始化随机数
CvPoint 函数
 


 
绘制文字的函数cvPutText
编辑
函数cvPutText使用给定的字体和颜色在图像上显示文本字符串。这些显示的文本由感兴趣矩形包围着。不属于指定字体的符号将被这些矩形符号替代。
void cvPutText( CvArr* img, const char* text, CvPoint org, const CvFont* font,CvScalar color );
img:
输入图像
text:
要显示的字符串
org:
第一个字母左下角的坐标
font:
指向字体结构的指针
color:[1]文本的颜色.
 


随机数的产生:**********
头文件
std.h
time.h
srand设置随机种子
srand(time(NULL));以系统时间为准
srand((unsigned)time(NULL));
//控制产生不同的随机数
rand() + 90;
设置范围90-100
同一秒钟:定义静态变量q,每次q++
srand(q + (unsigned)time(NULL));
 
 
 
(以下内容为搜索来的)
音乐:******************** 
#include
#pragma comment (lib,"winmm.lib")
mciSendString("play .\\1.mp3",NULL,0,NULL);
【转】mciSendSring的一些用法(老大给的那个链接里的)
mciSendString是用来播放多媒体文件的API指令,可以播放MPEG,AVI,WAV,MP3,等等,下面我们来介绍一
下它的使用方法:
一,打开多媒体文件。
首先在Dialog上面放一个Picture控件,MCISendString就在这个Picture控件的平面上播放多媒体文件,
设Picture控件的ID为IDC_STATIC1:
CStatic *pStatic=(CStatic*)GetDlgItem(IDC_STATIC1);HWND h=pStatic->GetSafeHwnd();
CString open1;
char buf[256];
open1.Format("open f:""mpeg""mpeg1.avi type MPEGVideo Alias movie parent %u Style %u notify",              h,WS_CHILD);
mciSendString(open1.GetBuffer(open1.GetLength()),buf,sizeof(buf),NULL);
这样F盘下面的mpeg目录下的mpeg1.avi就打开了,其中的type MPEGVideo是指打开MPEG,AVI等类型,如果不加
type MPEGVideo这一句,就是打开WAV,MP3等,Alias movie定义了mpeg1.avi的别名为movie,以后可以通过操
做movie就可以操作mpeg1.avi。
二,播放多媒体文件。
上面我们已经打开了f:"mpeg"mpeg1.avi,现在我们来播放它:
mciSendString("play movie",buf,sizeof(buf),NULL);
    如果想全屏播放:
mciSendString("play movie fullscreen",buf,sizeof(buf),NULL);


三,暂停播放。
mciSendString("pause movie",buf,sizeof(buf),NULL);
    四,停止播放。
mciSendString("close movie",buf,sizeof(buf),NULL);
    五,得到所播放文件的长度。
char sPosition[256];long lLength;
ciSendString("Status movie length", sPosition, 255,0);lLength=strtol(sPosition, NULL, 10);
其中lLength就是所播放文件的长度。
六,得到所播放文件的声音大小。
char chVolume[256];long lVolume;mciSendString("status movie volume",chVolume,255,0);lVolume=strtol(chVolume,NULL,10);其中lVolume就是所播放文件的声音大小。
七,到你指定的位置播放。
CString step1;long lPosition;
lPosition=100;
step1.Format("seek movie to %ld",lPosition);
mciSendString(step1.GetBuffer(step1.GetLength()),buf,sizeof(buf),0);
其中lPosition就是要到的播放位置,可以由你指定。
 
 
 
 
鼠标控制******************
void cvSetMouseCallback( const char* window_name(窗口的名字),
CvMouseCallback on_mouse(指定窗口里每次鼠标事件发生的时候,被调用的函数指针),
void* param=NULL );
on_mouse函数的原型应该为 void Foo(int event(CV_EVENT_*变量之一),
int x, int y,x和y是鼠标指针在图像坐标系的坐标(不是窗口坐标系)!!!!!OpenCV图像坐标系和窗口坐标系的区别!!!!
int flags(CV_EVENT_FLAG的组合),
void* param);param 是用户定义的传递到cvSetMouseCallback函数调用的参数,即用户定义的传递到回调函数的参数。
 


int  p  = 0;
void On_Mouse(int event , int x ,int y , int flag , void *param)
{
 switch(event)
 {
 case CV_EVENT_LBUTTONDOWN://鼠标左键
  if(x>690 && x<755 && y>500 && y<550 && p == 0)
  {
   p++;
   game.Init();
  }
  else if(x>780 && x<810 && y>10 && y<40 && p != 0)
  {
   game.PlayMusic();
  }
 }
}


在函数中用cvSetMouseCallback("TanChiShe GAME",On_Mouse,0/NULL);
on_mouse 指定窗口里每次鼠标事件发生的时候,被调用的函数指针。
param是用户定义的传递到cvSetMouseCallback函数调用的参数。


程序代碼如下:
#include
#include
#include
 
void onMouse(int event,int x,int y,int flags,void* param );


int main(int argc, char** argv)
{
     CvCapture *capture;
     IplImage *frame;
     capture =cvCaptureFromCAM(0) ;
     cvNamedWindow("Webcam",0);
     cvSetMouseCallback("Webcam",onMouse,NULL);
    while(true)
     {
         frame = cvQueryFrame(capture);
        cvShowImage("Webcam",frame);
        if(cvWaitKey(10)>=0)
         {
            break;
         }
     }
     cvReleaseCapture(&capture);
     cvDestroyWindow("Webcam");
     return 0;
}
void onMouse(int Event,int x,int y,int flags,void* param )
{
     printf("( %d, %d) ",x,y);
     printf("The Event is : %d ",Event);
     printf("The flags is : %d ",flags);
     printf("The param is : %d\n",param);
}
這邊每當滑鼠在視訊視窗介面點擊一下的時候,都會有固定三個動作
1.點擊(Click)
2.放開(Down)
3.滑動(move)
因此,程式執行滑鼠在點擊的時候onMouse()都會連續跑三次,代表滑鼠在點擊的時候連續的三個事件,而
void onMouse(int Event,int x,int y,int flags,void* param ) 副程式的引數分成四個不同的分類,分別為
1.事件回傳代號(int Event)
2.座標(int x,int y)
3.flags代號(int flags)
4.Mouse事件的代號名稱(param)
Event代表的是滑鼠回傳的事件號碼,每當滑鼠有動作,Event就會回傳一個整數訊息到onMouse(),也順便回傳滑鼠移動的座標,flags代表的是拖曳事件,param則是自己定義onMouse()事件的ID,就跟GUI介面的視窗介面ID一樣(cvGetWindowHandle()),不過這邊是自己給的編號,而視窗介面的ID則是系統自動隨機分配的ID,而滑鼠事件的執行可以細分的分類為
Event:
#define CV_EVENT_MOUSEMOVE 0                   滑動
#define CV_EVENT_LBUTTONDOWN 1           左鍵點擊
#define CV_EVENT_RBUTTONDOWN 2           右鍵點擊
#define CV_EVENT_MBUTTONDOWN 3           中鍵點擊
#define CV_EVENT_LBUTTONUP 4                 左鍵放開
#define CV_EVENT_RBUTTONUP 5                 右鍵放開
#define CV_EVENT_MBUTTONUP 6                 中鍵放開
#define CV_EVENT_LBUTTONDBLCLK 7         左鍵雙擊
#define CV_EVENT_RBUTTONDBLCLK 8         右鍵雙擊
#define CV_EVENT_MBUTTONDBLCLK 9         中鍵雙擊
flags:
#define CV_EVENT_FLAG_LBUTTON 1           左鍵拖曳
#define CV_EVENT_FLAG_RBUTTON 2           右鍵拖曳
#define CV_EVENT_FLAG_MBUTTON 4           中鍵拖曳
#define CV_EVENT_FLAG_CTRLKEY 8     (8~15)按Ctrl不放事件
#define CV_EVENT_FLAG_SHIFTKEY 16   (16~31)按Shift不放事件
#define CV_EVENT_FLAG_ALTKEY 32       (32~39)按Alt不放事件
上面的#define是OpenCV自行定義的參數,要做事件捕捉的時候,可以用參數,亦可以用純數字表示.簡單的介紹mouse相關的東西.
cvSetMouseCallback()
滑鼠事件呼叫函式,需要給它一個Handler,也就是事件驅動的副程式名稱,Handler必須要符合void xxx(int event,int x,int y,int flags,void* param )格式.
cvSetMouseCallback("視窗名稱",自行定義副程式名稱,自行定義副程式名稱的ID);
onMouse()
自行定義的滑鼠事件名稱,可以接受滑鼠訊息做相關控制.
void xxx(事件訊息整數代號,滑鼠x軸座標,滑鼠y軸座標,拖曳事件訊息整數代號,自行給予xxx這副程式的ID編號)

版权声明:本文为u011394136原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。