2008年6月12日 星期四

OpenCV程式設計介紹(1)

OpenCV(Open Source Computer Vision)
由Intel公司所開發出來的Open Source圖形演算法的函式庫(Image Process Libary)可以製做圖片,視訊,矩陣運算,統計,圖論,資料儲存的相關C語言程式設計,相關的領域為:影像處理,電腦視覺,圖形識別,電腦圖學,資訊檢索或遊戲設計,比較有名的製作為物體追蹤,人臉辨識,傅立葉轉換,紋理分析,可以整合不同圖檔格式的矩陣運算,應用在靜態圖片(BMP,JPG,TIF,PNG),動態Webcam的影像處理.

OpenCV的組成為許多圖形處理的資料結構及演算法所疊合而成,因此需要一些基本的資料結構基礎,比如說struct怎麼使用,如何release資料結構的空間等基本操作,會使用到linked list的算少數,算是C語言中級程式設計,有興趣玩的話,國內影像處理領域相關論文演算法幾乎都可以在OpenCV找的到,方便學術界用c語言推演更進階的影像處理演算法,功能好比Matlab,但比Matlab快上許多倍,更可以整合c語言相關函式庫,做更多元強大的功能應用,然而它最大的門檻是比Matlab的進入障礙還高一些,運用到許多資料結構,指標運算,記憶體位址,學完OpenCV,相信程式設計的功力更可以技高一籌.

OpenCV提供了簡單的GUI介面,他無法像MicroSoft Visual C++的MFC及Borland C++builder的VCL那麼完整,但如果是對於學術領域的研究是夠用的,他也可以整合在Visual C++及C++ builder的環境上,而本人是以Dev - C++為主,屬於最基本簡單又不須付費的Complier.

接下來進入OpenCV最基礎的入門,OpenCV最常用的函式庫為"cv.h","highgui.h","cxcore.h"及"cvaux.h.h","cv.h"代表Computer Vision,電腦視覺函式庫,"highgui.h",當然就是GUI介面的函式庫啦,當路徑都設定好之後(第一篇安裝方法),直接在開頭include進去就好啦,就跟stdio.h的使用方法一樣
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
#include <cxcore.h>
#include <cvaux.h>
接著,就介紹最基本的資料結構,IplImage,此資料結構是所有圖檔的一個中介,圖檔格式有很多種(bmp,jpg,png,tif),此資料結構的內容既不是bmp,也不是jpg,而是一個藉由cvLoadImage()所轉換的自定義格式如下所示:



讀入圖片之後,要怎麼知道圖片真的讀入了呢,就利用"highgui.h"的功能來檢視看看吧.
cvNamedWindow("Show Image",0);
cvResizeWindow("Show Image",300,400);
cvShowImage("Show Image",Image1);
要使用OpenCV的GUI時,要先給視窗名稱命名,這算是比較好寫的GUI之ㄧ了,裡面"Show Image"就是這個視窗的名稱,cvResizeWindow()就是調整視窗大小,視窗大小被設定在300*400,並指定視窗的名稱,再來,就是顯示視窗的圖片cvShowImage(),並且給予IplImage資料結構的結構變數,Image1裡面必須要先用cvLoadImage()存入圖檔,接著,再用鍵盤事件cvWaitKey(0)來做阻斷,一張圖片就可以被開啟啦,這是OpenCV最基本的操作之ㄧ,也像是c語言的"hello world"的開始,恭喜跨入第一步.

當資料結構被創立之後,當然要做回收的動作啦,在這邊IplImage的資料結構被創立,視窗介面的資料結構也被創立,當執行完就要做回收的動作啦,所有的資料結構都會被malloc()的副程式配置空間,而cvLoadImage()只是把一連串的動作隱藏起來,cvLoadImage()不但做了配置IplImage的資料結構空間,也把所有副檔名格式的資料初始化,將所有的數值及一些簡單的分析都存在IplImage的資料結構內,方便做一些圖形演算法的運算,而視窗介面被cvNamedWindow()給創立,視窗的資料結構被隱含在cvNamedWindow()中,使用者只要使用"Show Image"等命名操控就可以使用GUI視窗的控制,這是一種分層抽象的概念,比較複雜的部份被程式碼包再它的下一層,因此,我只要操控該視窗的字串名稱("Show Image")就可以做任何想要的動作了.

這邊用cvDestroyWindow()及cvReleaseImage()回收給系統,回收的東西是記憶體,一般來說,不做記憶體回收也不會影響電腦的效能太大,作業系統也會自動的做垃圾收集,把一些沒意義的記憶體做刪除,因此程式碼不多這兩行也不會有太大的影響,不過這種東西畢竟是卡記憶體的,也不能確定它是不是永久卡位(電腦關機後一定消失),因此,養成良好的習慣是程式設計師必備的,尤其是再做一個大的應用程式的時候.

簡單的OpenCV讀取圖形檔案程式碼
#include <stdio.h>
#include <cv.h>
#include <highgui.h>

int main()
{
    char FileName[10]="rain.jpg";

    IplImage *Image1 = cvLoadImage(FileName,1);

    cvNamedWindow("Show Image",0);

    cvResizeWindow("Show Image",300,400);

    cvShowImage("Show Image",Image1);

    cvWaitKey(0);

    cvDestroyWindow("Show Image");

    cvReleaseImage(&Image1);
}

圖片:


執行結果:

30 意見:

匿名 提到...

你好,小弟就是用OpenCV撰寫論文的
本來國內不太好找到有人整理OpenCV的Code,看到你的文章真的讓人佩服。
雖然我論文已經完成,但最近剛好又要用來寫點小東西,所以來此拜文。

路人甲 提到...

請問一下 opencv 可以讀alpha channel 嗎

謝謝你

wa114040@gmail.com 提到...

您好^^
cvCvtColor()有提供alpha channel的使用,而IplImage資料結構也有alpha channel的型別,所以應該是可以讀的^^

匿名 提到...

拜读完您的文章,决定好好学习线形代数和openCV,对我来说,你你的文章就是最好的教程

匿名 提到...

您好!拜读了您的文章,收获很大~~ 谢谢您的归纳和分享!

JiaPing 提到...

想請教一下 我有照著您的教學安裝cv了
也有設定好dev-C++ ,
但當我在執行這個第一個範例時發現
編譯完沒有錯誤訊息
但是也不會秀出結果...
是我有漏步驟嗎?
我是用
dev-C++4.9.9.2
opencv 1.0

p.s只要程式碼中有call cv的函式庫
就無法秀出執行結果

匿名 提到...

感謝您,也感謝您的文章,

對我真的太有益處了!

我正在研究OpenCV裡的haartraining源碼,

假如有機會,也可以po上來,讓這裡的教學

更完整...

wa114040@gmail.com 提到...

呵呵~

我不知道我寫到haartraining會是幾個月以後的事了~

有興趣可以寫E-mail給我~
或是隨便聊也行:)

匿名 提到...

不好意思想請問一下
如果在上面的code
執行出的結果
影像畫面無法顯示出來(全灰)可能是怎樣的問題呢

喔屋 我是新手>"<
感謝

wa114040@gmail.com 提到...

沒有放圖片在執行檔的路徑上...或是圖片檔名取錯,或是沒寫cvShowImage或cvShowImage("Image",0);

匿名 提到...

請問圖檔路徑應該放在哪裡才能夠使它執行
我有看到您說ㄉ"執行檔的路徑"
那是什麼意思捏?

匿名 提到...

不好意思,想請問一下。

如果現在我想用opencv去做將原本的靜止的影像當作背景去掉。

然後只顯示後來進入畫面的動態影像,我該如何去實現這步驟。

wa114040@gmail.com 提到...

在C:\Program Files\OpenCV\samples\c
底下
與背景相減相關的有
bgfg_codebook.cpp
bgfg_segm.cpp
是用自動背景註冊的方法

下面這個是動作偵測
motempl.c
也有用到背景相減的技術,是用前一張frame減後一張frame

提到...

你好,请问opencv能读取dcm文件吗?谢谢

匿名 提到...

版大你好

我已經照你上面的說明

安裝好opencv而且也設定好c++的選項

但是範例打上去雖然沒錯誤

但是好像有呼叫到cv就會出現 [Linker error] undefined reference to `cvLoadImage' 這種問題

請問是哪種原因呢?

wa114040@gmail.com 提到...

沒有加-lhighgui的連結~

匿名 提到...

想請問一下 我是用Visual 2005
我也出現全灰畫面 且偵錯結果有許多dll檔未載入符號
'Try2.exe': 已載入 'C:\Windows\System32\ntdll.dll',未載入符號
'Try2.exe': 已載入 'C:\Windows\System32\kernel32.dll',未載入符號
'Try2.exe': 已載入 'C:\Windows\System32\cxcore100.dll',未載入符號

大概像這樣
請問是什麼問題呢
感謝~

wa114040@gmail.com 提到...

cxcore100.dll這個會是沒有設立OpenCV dll環境變數,除非你是拿OpenCV 1.1去跑OpenCV 1.0的執行檔,這些問題都可以用google去下載它們的執行檔然後放在System32裡面

匿名 提到...

請問一下要如何用OpenCV來開啟EXR的圖檔

匿名 提到...

您好﹕
本人正學習OpenCV﹐現有一問題﹐影像顯示出來﹐上下相反﹐可否請賜教﹐如何解決?

匿名 提到...

您好:
我的作業系統是Vista 環境是Devc++
安裝的是OpenCV-2.0.0a-win32
看到安裝說明實在不太懂,裡面大部分都沒有,請問該如何是好??

匿名 提到...

最近開始要用OPENCV來做專題,
完全不會寫程式,
來這嘗試第一步嚕.

想把數學學好的人 提到...

您的網誌寫得簡單明瞭,對初學者真是一大福音。
非常感謝啊^ ^

程式三兩事 提到...

LPSTR addr;
LPSTR IpBuff;
int i=0,j=0;
IpBuff=Question->imageData;
for(i=0;i<(Question->height)/2;i++)
{
for(j=0;j<(Question->width)/2;j++)
{

addr=IpBuff+(i*((Question->width))+j)*3;

*(addr)=0;
*(addr+1)=0;
*(addr+2)=0;

}

}
上述已經載入圖片QUESTION,我是想要載入圖片的四分之一,讓四分之一變成黑色。可是執行起來怪怪的,不適我想要的那塊。可不可以麻煩一下

小辰 提到...

真的很感謝大大你 讓我一步步成長 謝謝!

匿名 提到...

路過想請問一下一個小問題,
玩某款電腦遊戲時發生錯誤,
彈出錯誤視窗顯示如下:
OpenCV GUI Error Handler

Unknown error code -25(Bad input roi)
in function cvInitImageHeader, C:\User\VP\opencv\cxcore\src\cxarray.cpp(3363)

想請問這是哪個環節出了問題
且我在電腦內也找不到如上述路徑的檔案...
麻煩您了,謝謝!

曾華薇 提到...

你好,我現在接下學長寫的opencv程式,
並建置好環境,程式可以執行,但是連結載入外部圖片(cvLoadImage)的參數會有問題(顯示為定義的值),請問我是不是少載入某些opencv的函式?該如何解決這種問題呢?

風林 提到...

你好,我在網路上閒晃有關影像處理的資料,看到您的部落格讓我覺得挖到寶庫,雖然我還沒有開始詳細閱讀、利用,但想先做一些donation給您,金額可能不是很大,若您不嫌棄的話,再麻煩您與我聯絡,謝謝!

匿名 提到...

小弟執行此篇程式時,出現
cannot find -lcvcam
ld returned 1 exit status
的錯誤,跪求前輩指導!

謝謝!

Unknown 提到...

大大你好 小弟剛初學openCv 是使用VS2010在做編譯 在網路上複製一段程式來測試時,編譯的時候會找不到圖片,但是去資料夾找他編譯下來的檔案開啟時卻是成功的 想請問一下是怎麼回事??

Copyright 2008-2009,yester