標籤:
1.OpenCV的配置:
要求:
Win7 Win8 Win10系統。
opencv的安裝路徑為預設。
電腦為 64 位元。
1.安裝Opencv1.0和VC6.0++ :
VC6.0++的安裝路徑可以改變,但是Opencv的安裝路徑最預設,不要改變其安裝路徑,不然會很麻煩。
2.添加環境變數:
右鍵我的電腦->屬性->進階系統設定->環境變數->使用者變數的Path添加 C:\Program Files (x86)\OpenCV\bin;
3.進入VC6.0++ 進行配置:
工具->選項->目錄
選擇Include files
添加以下:
C:\PROGRAM FILES (X86)\OPENCV\CXCORE\INCLUDE
C:\PROGRAM FILES (X86)\OPENCV\CVAUX\INCLUDE
C:\PROGRAM FILES (X86)\OPENCV\ML\INCLUDE
C:\PROGRAM FILES (X86)\OPENCV\OTHERLIBS\HIGHGUI
C:\PROGRAM FILES (X86)\OPENCV\OTHERLIBS\CVCAM\INCLUDE
C:\PROGRAM FILES (X86)\OPENCV\CV\INCLUDE
選擇Library files
添加以下:
C:\PROGRAM FILES (X86)\OPENCV\LIB
選擇Source files
添加以下:
C:\PROGRAM FILES (X86)\OPENCV\CV\SRC
C:\PROGRAM FILES (X86)\OPENCV\CVAUX\SRC
C:\PROGRAM FILES (X86)\OPENCV\CXCORE\SRC
C:\PROGRAM FILES (X86)\OPENCV\OTHERLIBS\HIGHGUI
C:\PROGRAM FILES (X86)\OPENCV\OTHERLIBS\CVCAM\SRC\WINDOWS
完成後建立工程:
檔案->建立->工程->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;}注意:《圖片路徑要改的》。
(如果是安裝 配置成功的話,會彈出來一個視窗)。
內容:
1.函數 講解:(1)cvNamedWindow :建立視窗
函數原型:
int cvNamedWindow( const char* name, int flags=CV_WINDOW_AUTOSIZE );
name :
視窗的名字,它被用來區分不同的視窗,並被顯示為視窗標題。
flags :
視窗屬性標誌。目前唯一支援的標誌是CV_WINDOW_AUTOSIZE。當這個標誌被設定後,使用者不能手動改變視窗大小,視窗大小會自動調整以適合被顯示映像(參考cvShowImage)。
函數cvNamedWindow建立一個可以放置映像的視窗。被建立的視窗可以通過它們的名字被引用。
如果已經存在這個名字的視窗,這個函數將不做任何事情。
(2)cvLoadImage :從檔案中讀取映像
函數原型:
IplImage* cvLoadImage( const char* filename, filename ,int flags=CV_LOAD_IMAGE_COLOR)
要被讀入的檔案的檔案名稱。
flags :
指定讀入映像的顏色和深度: );
filename :
要被讀入的檔案的檔案名稱。
flags :
指定讀入映像的顏色和深度:預設為 1,是圖片按照本身的大小。int flags=CV_LOAD_IMAGE_COLOR 這句話不用深究,只需要記著預設參數為1,圖片大小為本身即可。
(3)cvShowImage :在指定視窗中顯示映像
函數原型:
void cvShowImage( const char* name, const CvArr* image );
name:
視窗的名字。
image:
被顯示的映像。
函數cvShowImage 在指定視窗中顯示映像。如果視窗建立的時候被設定標誌CV_WINDOW_AUTOSIZE,那麼映像將以原始大小顯示;否則,映像將被伸縮以適合視窗大小。
(4)cvWaitKey :等待按鍵事件
函數原型:
int cvWaitKey( int delay=0 );
delay :
延遲的毫秒數。
函數cvWaitKey無限制的等待按鍵事件(delay<=0時);或者延遲"delay"毫秒。返回值為被按鍵的值,如果超過指定時間則返回-1。
(5)cvDestroyWindow :銷毀一個視窗
函數原型:
void cvDestroyWindow( const char* name );
name :
要被銷毀的視窗的名字。
函數cvDestroyWindow銷毀指定名字的視窗。
(6):擷取像素資料:
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
2.在一張 圖片上顯示另一張圖片:
#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,就會造成崩潰。因為你在 試圖找到一個根本找不到的位置。
二、要顯示在背景圖上的圖片大小大於背景圖:
造成 程式崩潰。原因:與上面差不多。
3.圖片滾動顯示:
原理:
首先將背景圖複製一份,那麼我們就可以將複製 圖從下到上(或者 從上到下)一點點的覆蓋原圖如果覆蓋完了,就從頭開始執行此過程即可。
圖片示範:
那麼 我們 就可以使用 十分接近的圖來模糊人的肉眼感官,造成圖片滾動的錯覺。
滾動代碼:
#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了。
注意:《圖片路徑要改的》。
OpenCV做飛機射擊類遊戲(一)