論文的題目是用PTZ網路攝影機去追蹤目標物,因此第一件工作是控制攝影機讓他可以隨參數轉動,第二件工作是把攝影機拍攝的影像抓下來傳給openCV做分析。(openCV是由intel開發的函式庫用在影像分析處理上,可以省下很多影像處理的功夫)。
第一件工作就遭遇到很大的困難,原因是我從來沒有用過所謂的http API,所以我不懂廠商在說什麼,而廠商也惜字如金不肯多加提示。我用google尋尋覓覓多時,才在對岸同胞的部落格裡看到,不要再掙扎了就直接用curl吧!(所謂掙扎是用socket做http的工作,這個我看半天也看不懂),因此才懂得什麼是http API(就是在程式裡做平常大家在瀏覽器裡做的事情)。但是在無線網路不通的實驗室裡始終調不出來(遇到問題沒辦法google),後來才知道是我弄錯了密碼,所以他一直回傳沒有權限,我還覺得它很莫名其妙。
攝影機終於可以隨心所欲地轉動,接下來就要把影像抓回來。但是這次就像是撞牆一樣,怎麼樣都弄不出來。一開始是攝影機提供的元件和openCV相衝,只要一下openCV指令就出現錯誤。掙扎了好幾天,我終於發現是因為那個元件和我的開發環境不是同一個版本,應該是用VS2005編譯出來的。於是跟同事借了VS2005的光碟片,沒想到VS2005比Vista資深,要在Vista上用VS2005必須要再安裝兩個SP。沒想到我連裝這個都很離奇,網路上說裝VS2005 SP1會比較花時間,但是我星期六裝了一整天都還在解壓縮,我開始懷疑是我沒有裝好VS2005,去微軟找了移除的工具移除掉VS2005,但是卻沒有真的移除掉,做了幾次VS2005都還是文風不動。我想說會不會重開機就好了,沒想到我重開機之後他竟然說我裝好了,真是離奇到不行。
好不容易openCV和AMC(攝影機製造商提供的控制元件)可以和平共處,但是畫面還是沒辦法抓回來。於是瘋狂google,發現他難搞真是舉世聞名,網路上找到的大多是要怎麼辦才好,同病相憐的人一堆。我還是有找到一些方法,但是都不可行,連directShow都出來了,只有一個最接近,就是利用AMC的getCurrentImage功能去擷取影像,然後從記憶體轉換到openCV的格式,但是他出來的畫面是花的,只能影影約約看出一點點是現在的畫面。
今天我大膽沒有加班,因為我每天弄到快兩點,收工去睡覺又因為挫折和不安夜不安眠,這實在不是我這個生病的人能維持的狀態。沒想到在清醒的狀態下,我發現了一招,利用AMC的SaveCurrentImage,把畫面存成jpg檔再用openCV從硬碟開檔。沒想到這招竟然可行,openCV開出來的畫面幾乎和AMC開出來的畫面同步,但是這還得了,一直瘋狂存取硬碟,硬碟不很快掛了才怪,所以只能當成備案,還是要找出A計畫才行(這是工程師的堅持嗎?)。因為有了B計畫所以我篤定A計畫也一定可行,於是我著手去改網路上的範例,在我一陣亂改之後,做到某處就出現錯誤訊息,但是也因此讓我發現從AMC抓回來的影像大小和openCV要承接的變數的大小不一樣。很快我就發現應該是因為兩邊的畫面大小不一致,於是我找出B計畫存的檔案,將尺寸修改之後畫面就開出來了。
講了這麼多並不是要說我有多坎坷,只是想要把我痛苦萬分之後得到的成果和大家分享,如果有人有一樣的需求,找到這裡就能找到答案。以下是我改過的程式碼,請有緣人享用。我用的攝影機的型號是AXIS-215。
VARIANT var;
long bufferSize;
cvNamedWindow("axis", 1);
VariantInit(&var);
m_AMC.GetCurrentImage(1,&var,&bufferSize);
BYTE* buf = var.pbVal; // get the buffer as a byte array
buf += sizeof(BITMAPINFOHEADER); // seek the beginnig of the
image data
int imgW = 704;
int imgH = 480;
// create the image
IplImage* img = cvCreateImage(cvSize(imgW,imgH),8,3);
// copy the data to the image
memcpy(img->imageData,buf,img->imageSize);
cvFlip(img,img,0);
cvShowImage("axis",img);//create a window before!
VariantClear(&var);
留言列表