OpenCV 例子代碼的講解、簡介及庫的安裝 .
轉載請標明是引用于 http://blog.csdn.net/chenyujing1234
歡迎大家提出意見,一起討論!
一、OpenCV介紹:
OpenCV是由Intel性能基元(IPP)團隊主持,而且幾個主要開發者都與IPP團隊保持良好的關系,所以OpenCV利用了IPP高度手工優化的代碼來實現加速。
使用IPP獲得提速是很顯著的。
OpenCV使用了優化了的C和C++代碼實現,它對IPP不存在任何依賴。但如果安裝了IPP,那么OpenCV將會通過自動載入IPP動態鏈接庫獲取IPP的優勢。
獲得IPP并安裝: http://www.itel.com/software/products/ipp/index.htm ; 請使用5.1或更新版本,請確認二進制文件路徑(eg:c/program files/intel/ipp/5.1/ia32/bin)
被添加到系統環境變量的PATH中。現在OpenCV會自動探測到IPP,并在運行時裝載IPP了。
1 、 OpenCV的結構和內容
OpenCV主體分為五個模塊:
OpenCV的CV模塊包含基本的圖像處理函數和高級的計算機視覺算法。
ML是機器學習庫,包含一些基于統計的分析和聚類工具。
HighGUI包含圖像和視頻輸入/輸出的函數。
CXCore包含OpenCV的一些基本數據結構和相關函數。
CvAux模塊,該模塊一般存放一些即將被淘汰的算法和函數(如嵌入式隱馬爾可夫模型的人臉識別算法),同時還有一些新出現的實驗性的算法(如背景和前景的分割)
二、OpenCV庫的獲得及編譯
1、 OpenCV可以直接下載安裝文件安裝得到lib與dll文件及源碼
OpenCV安裝的下載(下載最新版本的OpenCV2.1.0)http://sourceforge.net/projects/opencv/
如果是1.1版本的那么安裝文件是:
下載安裝程序后,運行安裝程序。安裝程序將安裝openCV并注冊DirectShow filter,然后進行一些安裝后的處理。
現在可以進入.../opencv/_make,使用MSVC++akg MSVC.NET 2005打開opencv.sln,然后生成Debug版本的庫或Release版的庫。
2、當然也可去下載它的源碼來通過CMake自己編譯.
轉自: http://hi.baidu.com/zgzhaobo/blog/item/5e0df6263d4499058b82a114.html
OpenCV2.1.0編譯詳細講解
準備工作
-
OpenCV源文件的下載(下載最新版本的OpenCV2.1.0)http://sourceforge.net/projects/opencv/
-
CMake的安裝(2.8.1)http://www.cmake.org/cmake/resources/software.html
-
CodeBlock安裝http://sourceforge.net/projects/codeblocks/
-
3rdparty庫文件的更新
由于videoInput庫文件是基于gcc 4.4.*之前版本編譯,所以在Mingw4.4.*編譯OpenCV時出現sjlj相應錯誤。
所以在我們編譯OpenCV前務必要更新videoInput的庫文件
文件下載:http://code.google.com/p/pyopencv/downloads/list
下載videoInput.a,覆蓋OpenCV的解壓路徑/3rdparty/lib/libvideoInput.a
處理OpenCV源文件
- Cmake交叉編譯
按照下面的設置進行配置,上面一行是解壓后的OpenCV的路徑
下面一行是你需要編譯后存放動態鏈接庫的文件目錄,可供自由選擇
注意:這里兩個路徑都不能有空格或者中文,不然編譯會出現錯誤
點擊下面configure進行配置(第一次點擊的時候會挑選編譯環境的工具,我們選擇codeblock:mingw),會出現上面紅色區域內容,勾選你需要的組建,然后再次點擊configure,進行配置相關文件。
接下來Generate按鈕呈現可用狀態,點擊Generate進行生成相應的編譯環境的工程文件。
到此,我們可以關閉cmake工具,交由codeblock進行處理了。
打開codeblock工具,打開工程文件,選擇剛才cmake輸出的文件夾下的對應工程文件。界面如下:
工程上面點擊右鍵,進行build,等待漫長的編譯過程完成。
此時OpenCV編譯完成!
=============================================================================================
當然大家也可以把CMake的編譯環境配置成VS的。這樣CMake后會產生編譯VC工程文件:
三、入門程序的實現
在VC開發環境中,我們要配置它的各項設置,以使OpenCV開發包中的highgui.lib cxcore.lib ml.lib cv.lib庫能被正確外國投資,并保證編譯器的預處理器能搜索到
opencv/*/include 目錄下的各個頭文件。
它們一般位于:
D:\Program Files\OpenCV\cv\include
D:\Program Files\OpenCV\cxcore\include
D:\Program Files\OpenCV\ml\include
D:\Program Files\OpenCV\otherlibs\highgui
1、 第一個例子-------顯示圖像
從磁盤中加載并在屏幕上顯示一幅圖像的簡單OpenCV程序
[cpp] view plaincopyprint?- #include "highgui.h"
- int main( int argc, char** argv )
- {
- // 是一個高層調用接口,它通過文件名確定被加載文件的格式;
- // 且該函數自動分配圖像數據結構所需的內存。
- // cvLoadImage可以讀取大多數格式的圖像文件,BMP、DIB、JPEG、JPE、PNG、BBM、PPM
- // SR、RAS、TIFF
- // 函數執行完后返回一個指針,此指針指向一塊為描述該圖像文件的數據結構而分配的內存塊。
- IplImage* img = cvLoadImage( argv[1] );
- // cvNamedWindow由HighGUI庫提供,用于在屏幕上創建一個窗口,將被顯示的圖像包含于該窗口中。
- // 函數第一個參數指定了窗口的的窗口標題。
- // 如果要使用HighGUI庫所提供的其他函數與該窗口進行交互,我們將通過該參數值引用這個窗口中。
- cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE );
- // 顯示該圖像
- cvShowImage("Example1", img );
- // 使程序暫停,等待用戶觸發一個按鍵操作,但如果該函數參數設為一個正數,則程序將暫停一段時間,
- // 時間長為該整數值個毫秒單位
- // 如果設置為0,那么將一直等待用戶觸發按鍵操作。
- cvWaitKey(0);
- // 內存釋放功能
- cvReleaseImage( &img );
- // 關閉窗口
- cvDestroyWindow("Example1");
- }
2、 第二個例子------播放AVI視頻
[cpp] view plaincopyprint?
- #include "highgui.h"
- int main( int argc, char** argv ) {
- cvNamedWindow( "Example2", CV_WINDOW_AUTOSIZE );
- // cvCaptureFromAVI()通過參數設置要讀入的AVI文件,返回一個指向cvCapture結構的指針
- // 這個指針包括了所有關于讀入AVI文件的信息,其中包括狀態信息。
- // 在調用這個函數后,返回指針指向的CvCapture結構被初始化到所對應的AVI文件的開頭。
- //CvCapture* capture = cvCaptureFromAVI( argv[1] ); // either one will work
- CvCapture* capture = cvCreateFileCapture( argv[1] );
- IplImage* frame;
- while(1) {
- // 用來將下一幀視頻文件載入內存(實際上是填充或更新CvCapture結構中),返回一個
- // 對應當前幀的指針
- // 與cvLoadImage不同的是,cvLoadImage為圖像分配內存空間,而cvQueryFram使用已經在
- // cvCapture結構中分配好的內存,這樣的話沒必要通過cvReleaseImage()對返回值釋放。
- frame = cvQueryFrame( capture );
- if( !frame ) break;
- cvShowImage( "Example2", frame );
- char c = cvWaitKey(33);
- if( c == 27 ) break;
- }
- cvReleaseCapture( &capture );
- cvDestroyWindow( "Example2" );
- }
2、1 視頻播放控制
上例中我們無法在視頻播放時進行快速拖動,我們接下來通過加入一個滾動條來實現這個功能。
HighGUI不僅提供了簡單的顯示函數,還包括一些圖像和視頻控制方法,其中之一個經常用到的是滾動條,它可以使我們方便地從視頻一幀跳到另外一幀。
我們通過調用cvCreateTrackbar()來創建一個滾動條,并通過設置參數確定滾動條所屬于的窗口。
[cpp] view plaincopyprint?- /* License:
- Oct. 3, 2008
- Right to use this code in any way you want without warrenty, support or any guarentee of it working.
- BOOK: It would be nice if you cited it:
- Learning OpenCV: Computer Vision with the OpenCV Library
- by Gary Bradski and Adrian Kaehler
- Published by O'Reilly Media, October 3, 2008
- AVAILABLE AT:
- http://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134
- Or: http://oreilly.com/catalog/9780596516130/
- ISBN-10: 0596516134 or: ISBN-13: 978-0596516130
- OTHER OPENCV SITES:
- * The source code is on sourceforge at:
- http://sourceforge.net/projects/opencvlibrary/
- * The OpenCV wiki page (As of Oct 1, 2008 this is down for changing over servers, but should come back):
- http://opencvlibrary.sourceforge.net/
- * An active user group is at:
- http://tech.groups.yahoo.com/group/OpenCV/
- * The minutes of weekly OpenCV development meetings are at:
- http://pr.willowgarage.com/wiki/OpenCV
- */
- #include "highgui.h"
- /*
- int main( int argc, char** argv )
- {
- // 是一個高層調用接口,它通過文件名確定被加載文件的格式;
- // 且該函數自動分配圖像數據結構所需的內存。
- // cvLoadImage可以讀取大多數格式的圖像文件,BMP、DIB、JPEG、JPE、PNG、BBM、PPM
- // SR、RAS、TIFF
- // 函數執行完后返回一個指針,此指針指向一塊為描述該圖像文件的數據結構而分配的內存塊。
- IplImage* img = cvLoadImage( argv[1] );
- // cvNamedWindow由HighGUI庫提供,用于在屏幕上創建一個窗口,將被顯示的圖像包含于該窗口中。
- // 函數第一個參數指定了窗口的的窗口標題。
- // 如果要使用HighGUI庫所提供的其他函數與該窗口進行交互,我們將通過該參數值引用這個窗口中。
- cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE );
- // 顯示該圖像
- cvShowImage("Example1", img );
- // 使程序暫停,等待用戶觸發一個按鍵操作,但如果該函數參數設為一個正數,則程序將暫停一段時間,
- // 時間長為該整數值個毫秒單位
- // 如果設置為0,那么將一直等待用戶觸發按鍵操作。
- cvWaitKey(0);
- // 內存釋放功能
- cvReleaseImage( &img );
- // 關閉窗口
- cvDestroyWindow("Example1");
- }
- */
- /* License:
- Oct. 3, 2008
- Right to use this code in any way you want without warrenty, support or any guarentee of it working.
- BOOK: It would be nice if you cited it:
- Learning OpenCV: Computer Vision with the OpenCV Library
- by Gary Bradski and Adrian Kaehler
- Published by O'Reilly Media, October 3, 2008
- AVAILABLE AT:
- http://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134
- Or: http://oreilly.com/catalog/9780596516130/
- ISBN-10: 0596516134 or: ISBN-13: 978-0596516130
- OTHER OPENCV SITES:
- * The source code is on sourceforge at:
- http://sourceforge.net/projects/opencvlibrary/
- * The OpenCV wiki page (As of Oct 1, 2008 this is down for changing over servers, but should come back):
- http://opencvlibrary.sourceforge.net/
- * An active user group is at:
- http://tech.groups.yahoo.com/group/OpenCV/
- * The minutes of weekly OpenCV development meetings are at:
- http://pr.willowgarage.com/wiki/OpenCV
- */
- #include <stdio.h>
- #include <iostream>
- #include <fstream>
- #include "cv.h"
- #include "highgui.h"
- /*
- OK, you caught us. Video playback under linux is still just bad. Part of this is due to FFMPEG, part of this
- is due to lack of standards in video files. But the position slider here will often not work. We tried to at least
- find number of frames using the "getAVIFrames" hack below. Terrible. But, this file shows something of how to
- put a slider up and play with it. Sorry.
- */
- using namespace std;
- int g_slider_position = 0;
- CvCapture* g_capture = NULL;
- // 定義全局回調函數,它在滾動條被拖動時調用
- // 滾動條位置會被作為參數傳入。
- void onTrackbarSlide(int pos) {
- // 允許我們設置CvCapture對象的各種屬性
- // CV_CAP_PROP_POS_FRAMES表我們以幀數來設置讀入位置。
- // 如果我們想通過視頻長度比例來設置讀入位置,我們可以通過用AVI_RATIO代替FRAMES。
- cvSetCaptureProperty(
- g_capture,
- CV_CAP_PROP_POS_FRAMES,
- pos
- );
- }
- //Hack because sometimes the number of frames in a video is not accessible.
- //Probably delete this on Widows
- int getAVIFrames(char * fname) {
- char tempSize[4];
- // Trying to open the video file
- ifstream videoFile( fname , ios::in | ios::binary );
- // Checking the availablity of the file
- if ( !videoFile ) {
- cout << "Couldn’t open the input file " << fname << endl;
- exit( 1 );
- }
- // get the number of frames
- videoFile.seekg( 0x30 , ios::beg );
- videoFile.read( tempSize , 4 );
- int frames = (unsigned char ) tempSize[0] + 0x100*(unsigned char ) tempSize[1] + 0x10000*(unsigned char ) tempSize[2] + 0x1000000*(unsigned char ) tempSize[3];
- videoFile.close( );
- return frames;
- }
- int main( int argc, char** argv ) {
- cvNamedWindow( "Example2_3", CV_WINDOW_AUTOSIZE );
- g_capture = cvCreateFileCapture("E:\\OpenCV\\openCV1.1Test\\tree.avi" /*argv[1]*/ );
- IplImage *foo = cvQueryFrame( g_capture);
- // 獲得視頻文件的總幀數以對滾動條進行設置。
- int frames = (int) cvGetCaptureProperty(
- g_capture,
- CV_CAP_PROP_FRAME_COUNT
- );
- // 獲得寬
- int tmpw = (int) cvGetCaptureProperty(
- g_capture,
- CV_CAP_PROP_FRAME_WIDTH
- );
- // 獲得高
- int tmph = (int) cvGetCaptureProperty(
- g_capture,
- CV_CAP_PROP_FRAME_HEIGHT
- );
- printf("opencv frames %d w %d h %d\n",frames,tmpw,tmph);
- // 分析視頻文件來獲得總共有幾幀
- frames = getAVIFrames("E:\\OpenCV\\openCV1.1Test\\tree.avi"/*argv[1]*/); //This is a hack because on linux, getting number of frames often doesn't work
- printf("hacked frames %d w %d h %d\n",frames,tmpw,tmph);
- // 創建滾動條
- // 可以設置滾動條名稱并確定滾動條的所屬窗口。
- // 將一個變量綁定到這個滾動條來表示滾動條的最大值和一個回調函數
- cvCreateTrackbar(
- "Position",
- "Example2_3",
- &g_slider_position,
- frames,
- onTrackbarSlide
- );
- IplImage* frame;
- frames = 0;
- while(1) {
- frame = cvQueryFrame( g_capture );
- if( !frame ) break;
- // int frames = cvGetCaptureProperty( g_capture, CV_CAP_PROP_POS_FRAMES);//This should work, sometimes it does not on linux
- frames++; //My cheat
- printf("\nFrame number=%d\n",frames);
- cvSetTrackbarPos("Position","Example2_3",frames);
- cvShowImage( "Example2_3", frame );
- char c = (char)cvWaitKey(10);
- if( c == 27 ) break;
- }
- cvReleaseCapture( &g_capture );
- cvDestroyWindow( "Example2_3" );
- return(0);
- }
2、2 對圖像進行簡單的變換
現在我們要對視頻的播放中的每一幀進行圖像平滑處理,通過對圖像數據與高斯或者其他核函數進行卷積有效地減少圖像信息內容。
OpenCV使得這個卷積操作非常容易。
我們先創建一個窗口“Example4-out" 用來顯示處理后的圖像。然后在我們調用cvShowImage()來顯示新捕捉的圖像以后,我們可以計算
和在輸出窗口中顯示平滑處理后的圖像。
效果如下:
- #include "cv.h"
- #include "highgui.h"
- void example2_4( IplImage* image )
- {
- // Create some windows to show the input
- // and output images in.
- //
- cvNamedWindow( "Example2_4-in", CV_WINDOW_AUTOSIZE );
- cvNamedWindow( "Example2_4-out", CV_WINDOW_AUTOSIZE );
- // Create a window to show our input image
- //
- cvShowImage( "Example2_4-in", image );
- // 分配自己的圖像結構空間用來存儲平滑處理后的圖像
- // 第一個參數說明了當前圖像結構的大小
- // 第二個參數告訴了我們各通道每個像素點的數據類型
- // 最后一個參數說明了通道的總數。
- IplImage* out = cvCreateImage(
- cvGetSize(image),
- IPL_DEPTH_8U,
- 3
- );
- // 我們通過使用每個像素周圍3*3區域進行高斯平滑處理
- cvSmooth( image, out, CV_GAUSSIAN, 5,5 );
- // 輸入與輸出可以是相同的,這將會使我們的程序更加有效。
- cvSmooth( out, out, CV_GAUSSIAN, 5, 5);
- // Show the smoothed image in the output window
- //
- cvShowImage( "Example2_4-out", out );
- // Be tidy
- //
- cvReleaseImage( &out );
- // Wait for the user to hit a key, then clean up the windows
- //
- cvWaitKey( 0 );
- cvDestroyWindow("Example2_4-in" );
- cvDestroyWindow("Example2_4-out" );
- }
- int main( int argc, char** argv )
- {
- IplImage* img = cvLoadImage("adrian.jpg");
- cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE );
- cvShowImage("Example1", img );
- example2_4( img );
- // cvWaitKey(0);
- cvReleaseImage( &img );
- cvDestroyWindow("Example1");
- }
2、3 對圖像進行復雜一點的變換
這里我們將用輸出來覆蓋輸入變量。在OpenCV中我們通過函數cvPyrDown()來完成上述功能。
從舊的圖像中讀取所需的信息;在OpenCV中,所有的重要數據結構都是以結構體的形式實現的,并以結構體指針的形式傳遞。
openCV中沒有私有數據!
[cpp] view plaincopyprint?
- #include "cv.h"
- #include "highgui.h"
- IplImage* doPyrDown(
- IplImage* in,
- int filter = IPL_GAUSSIAN_5x5)
- {
- // 確保輸入的寬高能被2整除.
- //
- //assert( in->width%2 == 0 && in->height%2 == 0 );
- // 從舊的圖像中讀取所需的信息
- // 在OpenCV中,所有的重要數據結構都是以結構體的形式實現的,并以結構體指針的形式傳遞。
- // openCV中沒有私有數據!
- IplImage* out = cvCreateImage(
- cvSize( in->width/2, in->height/2 ),
- in->depth,
- in->nChannels
- );
- cvPyrDown( in, out );
- return( out );
- };
- int main( int argc, char** argv )
- {
- IplImage* img = cvLoadImage("adrian.jpg" );
- IplImage* img2 = cvCreateImage( cvSize( img->width/2,img->height/2 ), img->depth, img->nChannels);
- cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE );
- cvNamedWindow("Example2", CV_WINDOW_AUTOSIZE );
- cvShowImage("Example1", img );
- img2 = doPyrDown( img );
- cvShowImage("Example2", img2 );
- cvWaitKey(0);
- cvReleaseImage( &img );
- cvReleaseImage( &img2 );
- cvDestroyWindow("Example1");
- cvDestroyWindow("Example2");
- }
2、4 Canny邊緣檢測
在進行Canny處理前得先進行灰度處理
cvCvtColor(img_rgb, img_gry ,CV_BGR2GRAY);
- #include "cv.h"
- #include "highgui.h"
- IplImage* doCanny(
- IplImage* in,
- double lowThresh,
- double highThresh,
- double aperture)
- {
- if (in->nChannels != 1)
- return(0); // Canny 僅處理多通道圖像
- IplImage* out = cvCreateImage(
- cvGetSize( in ),
- in->depth, //IPL_DEPTH_8U,
- 1);
- cvCanny( in, out, lowThresh, highThresh, aperture );
- return( out );
- };
- int main( int argc, char** argv )
- {
- IplImage* img_rgb = cvLoadImage( "adrian.jpg" );
- IplImage* img_gry = cvCreateImage( cvSize( img_rgb->width,img_rgb->height ), img_rgb->depth, 1);
- cvCvtColor(img_rgb, img_gry ,CV_BGR2GRAY);
- cvNamedWindow("Example Gray", CV_WINDOW_AUTOSIZE );
- cvNamedWindow("Example Canny", CV_WINDOW_AUTOSIZE );
- cvShowImage("Example Gray", img_gry );
- IplImage* img_cny = doCanny( img_gry, 10, 100, 3 );
- cvShowImage("Example Canny", img_cny );
- cvWaitKey(0);
- cvReleaseImage( &img_rgb);
- cvReleaseImage( &img_gry);
- cvReleaseImage( &img_cny);
- cvDestroyWindow("Example Gray");
- cvDestroyWindow("Example Canny");
- }
接下來我們想縮放圖像兩次,然后在縮放后的圖像中尋找邊緣,具體如下所示:
[cpp] view plaincopyprint?
- #include "cv.h"
- #include "highgui.h"
- IplImage* doCanny(
- IplImage* in,
- double lowThresh,
- double highThresh,
- double aperture)
- {
- IplImage* out = cvCreateImage(
- cvGetSize( in ),
- in->depth, //IPL_DEPTH_8U,
- 1);
- cvCanny( in, out, lowThresh, highThresh, aperture );
- return( out );
- };
- IplImage* doPyrDown(
- IplImage* in,
- int filter = IPL_GAUSSIAN_5x5)
- {
- // Best to make sure input image is divisible by two.
- //
- //assert( in->width%2 == 0 && in->height%2 == 0 );
- IplImage* out = cvCreateImage(
- cvSize( in->width/2, in->height/2 ),
- in->depth,
- in->nChannels
- );
- cvPyrDown( in, out );
- return( out );
- };
- int main( int argc, char** argv )
- {
- IplImage* img_rgb = cvLoadImage( "adrian.jpg" );
- IplImage* img_gry = cvCreateImage( cvSize( img_rgb->width,img_rgb->height ), img_rgb->depth, 1);
- cvCvtColor(img_rgb, img_gry ,CV_BGR2GRAY);
- IplImage* img_pyr = doPyrDown( img_gry, IPL_GAUSSIAN_5x5 );
- IplImage* img_pyr2 = doPyrDown( img_pyr, IPL_GAUSSIAN_5x5 );
- IplImage* img_cny = doCanny( img_pyr2, 10, 100, 3 );
- cvNamedWindow("Example Gray", CV_WINDOW_AUTOSIZE );
- cvNamedWindow("Example Pyr", CV_WINDOW_AUTOSIZE );
- cvNamedWindow("Example Canny", CV_WINDOW_AUTOSIZE );
- cvShowImage("Example Gray", img_gry );
- cvShowImage("Example Pyr", img_pyr2 );
- cvShowImage("Example Canny", img_cny );
- cvWaitKey(0);
- cvReleaseImage( &img_rgb);
- cvReleaseImage( &img_gry);
- cvReleaseImage( &img_pyr);
- cvReleaseImage( &img_pyr2);
- cvReleaseImage( &img_cny);
- cvDestroyWindow("Example Gray");
- cvDestroyWindow("Example Pyr");
- cvDestroyWindow("Example Canny");
- }
2、4、1 內存釋放考慮方面的改進
(1)像下面這樣進行嵌套調用是一個不好的主意,因為內存空間的釋放會成為一個很困難的問題。
IplImage* img_pyr = doPyrDown( img_gry, IPL_GAUSSIAN_5x5 );
IplImage* img_pyr2 = doPyrDown( img_pyr, IPL_GAUSSIAN_5x5 );
IplImage* img_cny = doCanny( img_pyr2, 10, 100, 3 );
(2) 在OpenCV中我們必須確認被釋放的空間必須是我們分配,但在我們上面的例子中卻釋放了非顯示分配的內存
cvReleaseImage( &img_pyr);
cvReleaseImage( &img_pyr2);
cvReleaseImage( &img_cny);
所以我們把例子改為:
[cpp] view plaincopyprint?- int main( int argc, char** argv )
- {
- IplImage* img_rgb = cvLoadImage( "adrian.jpg" );
- IplImage* img_gry = cvCreateImage( cvSize( img_rgb->width,img_rgb->height ), img_rgb->depth, 1);
- cvCvtColor(img_rgb, img_gry ,CV_BGR2GRAY);
- /*
- IplImage* img_pyr = doPyrDown( img_gry, IPL_GAUSSIAN_5x5 );
- IplImage* img_pyr2 = doPyrDown( img_pyr, IPL_GAUSSIAN_5x5 );
- IplImage* img_cny = doCanny( img_pyr2, 10, 100, 3 );
- cvNamedWindow("Example Gray", CV_WINDOW_AUTOSIZE );
- cvNamedWindow("Example Pyr", CV_WINDOW_AUTOSIZE );
- cvNamedWindow("Example Canny", CV_WINDOW_AUTOSIZE );
- cvShowImage("Example Gray", img_gry );
- cvShowImage("Example Pyr", img_pyr2 );
- cvShowImage("Example Canny", img_cny );
- cvWaitKey(0);
- cvReleaseImage( &img_rgb);
- cvReleaseImage( &img_gry);
- cvReleaseImage( &img_pyr);
- cvReleaseImage( &img_pyr2);
- cvReleaseImage( &img_cny);
- cvDestroyWindow("Example Gray");
- cvDestroyWindow("Example Pyr");
- cvDestroyWindow("Example Canny");
- */
- // 像上面這樣進行嵌套調用是一個不好的主意,因為內存空間的釋放會成為一個很困難的問題。
- IplImage* out;
- cvNamedWindow("Example Gray", CV_WINDOW_AUTOSIZE );
- cvNamedWindow("Example Pyr", CV_WINDOW_AUTOSIZE );
- cvNamedWindow("Example Canny", CV_WINDOW_AUTOSIZE );
- // 第一次縮放
- cvShowImage("Example Gray", img_gry );
- out = doPyrDown( img_gry, IPL_GAUSSIAN_5x5 );
- // 第一次縮放
- cvShowImage("Example Pyr", out );
- out = doPyrDown( out, IPL_GAUSSIAN_5x5 );
- // Canny處理
- out = doCanny( out, 10, 100, 3 );
- cvShowImage("Example Canny", out );
- cvWaitKey(0);
- cvReleaseImage( &img_rgb);
- cvReleaseImage( &img_gry);
- // 在OpenCV中我們必須確認被釋放的空間必須是我們分配的
- cvReleaseImage( &out);
- cvDestroyWindow("Example Gray");
- cvDestroyWindow("Example Pyr");
- cvDestroyWindow("Example Canny");
- }