EMCV全稱為EmbeddedComputer Vision Library,是一個可在TI DM64x系列DSP上運作的計算機視覺庫。EMCV提供了跟OpenCV完全一緻的函數接口,通過EMCV,可以輕松地将原有的OpenCV算法移植到DSP,甚至不用改一行代碼。
目前EMCV已經支援IplImage,CvMat,CvSeq等基本資料結構,可使用cvCreateImage等建立和釋放圖像,以及contour檢測等。
考慮到OpenCV的複雜性,我們選用EMCV來替代OpenCV在DM6467上進行移植,在移植成功之後,如果需要使用某種圖像處理功能,隻需要将相關函數從OpenCV源代碼中移植到EMCV即可,非常友善。
1 在CCS中建立工程
1,下載下傳EMCV源碼。要建立調用EMCV算法的DSP工程,首先需要下載下傳EMCV源碼,下載下傳位址為https://emcv.svn.sourceforge.net/svnroot/emcv/,由于源碼使用SVN進行管理,是以需要使用SVN工具進行下載下傳,我選用的是TortoiseSVN,依照網絡上的教程進行checkout,成功将EMCV源碼下載下傳到本地。
2,建立工程。建立TMS320C6++系列DSP的工程,選擇out模式。
3,添加源檔案。将emcv源碼複制到建立工程的同級目錄,例如我的DSP路徑位于D:\OpenCV\projects,則将emcv源碼複制到該目錄下。由于暫時隻使用emcv的cv和cxcore兩部分,是以複制時可以隻選擇這兩個檔案夾。複制完畢之後,将cv和cxcore目錄下所有的.cpp檔案全部添加到工程中。然後,将C:\CCStudio_v3.3\C6000\cgtolls\lib\rts64plus.lib這個庫檔案添加到工程。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICdzFWRoRXdvN1LclHdpZXYyd2LcBzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CX90keOFTRUR2ck1mYoxGShZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jMxMjNwADNyITOxATMzEDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
4,修改編譯選項。首先需要設定預處理時頭檔案的搜尋路徑,也即在compiler指令中添加-i"..\emcv\cv" -i"..\emcv\cxcore”。然後,在linker指令中添加 --no_sym_merge,如果不添加會編譯出錯。
5,編寫cmd檔案。接下來需要編寫cmd檔案配置設定存儲區域,考慮到EMCV函數很占用記憶體,是以将各個段都放在DDR2上面。另外,需要特别注意stack和heap的大小設定,如果設定得太小,程式在運作時空間不夠很可能發生無法預料的結果,是以這裡設定stack大小為0x00020000,heap大小為0x00800000,最終的linker.cmd檔案如下所示。
-heap 0x00800000 -stack 0x00020000 MEMORY { VECS: o = 0x00000000 l = 0x00000080 IRAM: o = 0x00000080 l = 0x00007f80 DRAM: o = 0x00010000 l = 0x00008000 DDR2: o = 0x80000000 l = 0x08000000 } SECTIONS { .bss > DDR2 .cinit > DDR2 .cio > DDR2 .const > DDR2 .stack > DDR2 .far > DDR2 .switch > DDR2 .tables > DDR2 .sysmem > DDR2 .text > DDR2 .ddr2 > DDR2 } |
2 修改EMCV源檔案
由于EMCV中的源檔案是以C++格式編寫,很多地方與C不相容,在CCS中編譯時有些代碼無法編譯通過、或者即使編譯通過也無法運作,是以,需要修改EMCV中的一些檔案。到現在為止已經修改過的包括以下幾處。
1,cxmisc.h第259行
CV_INLINE CvSize cvGetMatSize( const CvMat* mat ) { CvSize size = { mat->width, mat->height }; return size; } |
修改為
CV_INLINE CvSize cvGetMatSize( const CvMat* mat ) { //CvSize size = { mat->width, mat->height }; CvSize size; size.width = mat->cols; size.height = mat->rows; return size; } |
2,cxmisc.h第247行
CV_INLINE void* cvAlignPtr( const void* ptr, int align=32 ) { assert( (align & (align-1)) == 0 ); return (void*)( ((size_t)ptr + align - 1) & ~(size_t)(align-1) ); } |
修改為
CV_INLINE void* cvAlignPtr( const void* ptr, int align CV_DEFAULT(32)) { assert( (align & (align-1)) == 0 ); return (void*)( ((size_t)ptr + align - 1) & ~(size_t)(align-1) ); } |
3,cxtypes.h第211行
CV_INLINE int cvRound( double value ) { if(value >= 0.0) { return int(floor(value + 0.5)); } return int(ceil(value - 0.5)); } CV_INLINE int cvFloor( double value ) { return int(floor(value)); } CV_INLINE int cvCeil( double value ) { return int(ceil(value)); } |
修改為
CV_INLINE int cvRound( double value ) { int a; if(value >= 0.0) { //return int(floor(value + 0.5)); a = floor(value + 0.5); return a; } //return int(ceil(value - 0.5)); a = ceil(value - 0.5); return a; } CV_INLINE int cvFloor( double value ) { //return int(floor(value)); int a = floor(value); return a; } CV_INLINE int cvCeil( double value ) { //return int(ceil(value)); int a = ceil(value); return a; } |
4,cxarray.cpp
将該檔案中所有出現if(!CvIPL.createHeader )的代碼按如下格式修改(紅色部分為添加的注釋符)。
CV_CALL( img = (IplImage *)cvAlloc( sizeof( *img ))); CV_CALL( cvInitImageHeader( img, size, depth, channels, IPL_ORIGIN_TL, CV_DEFAULT_IMAGE_ROW_ALIGN )); |
到現在為止,修改的地方還很少,因為大部分函數都還沒有用到,後面如果想要使用OpenCV的其他功能時很可能還需要大量修改代碼。
3 編寫測試程式
修改完EMCV源碼之後,需要編寫測試程式進行測試。這裡編寫的程式隻完成幾個很簡單的任務:建立圖像,在其中添加一個矩形框,釋放圖像。雖然程式很簡單,但是它也包含了一部分OpenCV的基礎資料結構,包括CvPoint,CvScalar,CvSize和IplImage,以及幾個基本的函數,包括cvCreateImage,cvRectangle和cvReleaseImage。如果這些代碼能夠運作,那麼表明EMCV移植到DSP上的工作初步完成了。最終的程式代碼如下所示。
#include <stdio.h> #include "cv.h" int main() { CvPoint point1, point2; point1.x = 0; point1.y = 0; point2.x = 10; point2.y = 10; CvScalar color = CV_RGB(0, 255, 0); CvSize size; size.height = 40; size.width = 40; IplImage* img; img = cvCreateImage(size, IPL_DEPTH_8U, 3); printf("%d %d %d\n", *(img->imageData), *(img->imageData + 1), *(img->imageData + 2)); cvRectangle(img, point1, point2, color, CV_AA, 0); printf("%d %d %d\n", *(img->imageData), *(img->imageData + 1), *(img->imageData + 2)); cvReleaseImage(&img); return 0; } |
4 測試結果分析
對于編寫的測試程式可以現在VS2010中進行測試,如果運作無誤再移植到DSP。
将測試程式添加進工程,編譯通過之後下載下傳到開發闆運作,最終輸出結果如下所示。其中第一行為建立圖像的第一個像素點的BGR三個分量值,第二行為将第一個像素點置為綠色之後的值,0 -1 0表示的是BGR(0, 255, 0),也即綠色,表明程式運作無誤,EMCV在DSP上的移植取得初步成功。