第三章 嵌入式系統移植
3.2 輸入影像擷取
3.2.2 圖像擷取轉換
跟個人電腦相比的話,在嵌入式系統底下,其開發過程中如欲額外增加其它 函式庫,像OpenCV、FreeImage 等針對個人電腦環境開發的函式庫,其會遭遇到 下述困難:
z Embedded Visual C++並不完全支援所有的 C/C++函式,僅支援基本的 C/C++
函式,如果其它函式庫裡有使用到其不支援的函式的話,則會增加編譯過程
中的困難度。
z Embedded Visual C++其編譯過程複雜,且使用特定格式,如需使用寬字元,
採用Unicode 顯示,而 ASCII 則需額外處理等,此外,其可參考的資源不多,
常常是利用嘗試錯誤的方式來除錯,若是因為函式庫內部資料型態宣告導致 程式錯誤,會增加開發時程。
z 嵌入式環境的資源受到嚴格限制,若是函式庫內宣告太多記憶體空間則會導 致嵌入式系統執行上的不穩定,甚至導致嵌入式系統當機狀況產生。
z 無法確定在不同的嵌入式系統下皆支援所使用開發的函式庫。
根據上述等因素,為確保開發過程順利,故採用另一變通的方式,來確保不 會因為其它函式庫導致錯誤的發生,如直接針對輸入的畫面進行擷取。其流程如 圖3.4 所示,當螢幕上顯示輸入影像時,利用螢幕擷圖的方式將螢幕上資訊另存成 BMP 檔案格式,其中為確保其圖像大小為完整的影像大小,所以透過設定有效區 域的方法,來擷取顯示在螢幕上的影像,考量SDRAM 的存取時間遠小於 Flash Disk 存取和系統需偵測大量的輸入影像,而偵測完的影像輸出後即不具意義的情形 下,所以將螢幕上的像素值擷取至宣告好的 SDRAM 空間中存放,每次處理完的 資料可暫存在Flash Disk 中來減少 SDRAM 記憶體空間的使用。
此方式目的主要用來克服JPEG 轉 BMP 的不便之處,在無需透過任何額外函 式庫狀況下,僅需關心螢幕上各點位置的像素值,大幅縮短JPEG 解碼的時間,如 圖3.4 所示。
Screen Set Valid Rectangle
Get Screen Information
Copy from Screen to Memory
Set BMPInfo
Set BMPFileHeader
Write BMP File to Flash
圖3.4、圖像擷取轉換流程 接著,流程主要可概分為三部份,如圖3.5 所示
Set Valid Rectangle
Get Screen Information Copy from Screen to Memory
Write BMP File to Flash
圖3.5、圖像擷取轉換架構示意圖 (1) 設定有效區域
以螢幕解析度 640x480 環境下來說,為了演算法運算及輸出畫面容易辨識,
我們設定其影像輸入解析度為320x240,針對其影像輸入大小,有效區域也設定為 320x240,而在有效區域下的各像素點位置也就是欲進行擷取的目標,如圖 3.6 所 示。
圖3.6、有效區域設定 (2) 擷取螢幕資訊
進行擷取螢幕資訊前,如圖3.7 所示,首先需針對所採用的函式或變數有初步 了解
HDC - 為一被 Graphics Device Interface (GDI)所呼叫使用的記憶體空間,其主 要存放設備內容中所描繪的點、直線或圖形,當描繪視窗介面時,常被用來存放 此介面的相關屬性設定。
HBITMAP - 為一資源標識值,針對所載入的圖片進行標識 如欲在視窗下顯
示一圖片時,首先呼叫 CreateCompatibleDC 創建一視窗的空間 DC,接著利用函 式 SHLoadDIBitmap 將 圖 片 載 入 至 HBITMAP , 再 利 用 函 式 SelectObject 將 HBITMAP 載入至 DC 視窗空間中,最後呼叫函式 BitBlt 重繪視窗。
CreateDIBSection - 此 函 式 用 來 創 建 一 與 設 備 無 關 的 bitmap 檔 (device-independent bitmap DIB)供程式使用其函式結構為
HBITMAP CreateDIBSection(
HDC hdc, //視窗內容空間
const BITMAPINFO *pbmi, //指向BITMAPINFO指標
UINT iUsage, //設定BITMAPINFO內的顏色
void *ppvBits, //指標內容為存放的像素值
HANDLE hSection, //現已不支援,設為NULL
DWORD dwOffset //現已不支援,設為0
);
BitBlt - 此函式用來轉移從特定來源區域的像素值到特定的目標區域,其函式 結構包含
BOOL BitBlt(
HDC hdcDest, //目標端裝置內容
int nXDest, //目標端區域內容起始x座標
int nYDest, //目標端區域內容起始y座標
int nWidth, //來源端及目標端區域寬度
int nHeight, //來源端及目標端區域高度
HDC hdcSrc, //來源端裝置內容
int nXSrc, //來源端區域內容起始x座標
int nYSrc, //來源端區域內容起始x座標
DWORD dwRop //結合來源端與目標端的顏色為最終呈現顏色
);
圖3.7、擷取螢幕資訊存放至記憶體中 (3) 轉存檔案格式
過程中可將執行結果輸出暫存在Flash Disk 中,原因在於可利用此暫存圖像供 本系統進一步運用,或繼續開發其他演算法,故在存放時需依BMP 標準格式存放 為24-bit RGB 彩色圖像,其大小為輸入影像的寬高,此為 320x240。
更進一步來說,如圖3.6 所示拆解整體流程為
a. 將攝影機擷取的 MJPEG 影像載入到系統記憶體中(1),接著在透過函式呼叫顯 示在螢幕上(2)。
b. 透過擷取螢幕上的像素點,將各像素值資料轉為 RGB 值(3、4),並且將其另存 為BMP 資料格式在 Flash Disk 下供演算法存取使用(5)。
c. 演算法運算擷取到的像素值(6),並將結果回存(7),再由函式將結果輸出顯示在 螢幕上(8)
在a 中又分為
1. 從環境擷取 320x240 影像至 SDRAM 中 ( StartStreaming() ) 2. 從 SDRAM 中顯示 320x240 影像至螢幕 (ReadFrameThread() ) 在b 中又分為
3. 從螢幕擷取 320x240 影像至 SDRAM 中 ( OnScreenSave() ) 4. 替擷取影像宣告 BMPHeader 及 BMPInfo
( BITMAPINFO、BITMAPFILEHEADER )
5. 將宣告 BMP 檔頭及擷取好的像素(BMPData)寫入 Flash Disk 中 ( fwrite() ) 在c 中又分為
6. CPU 從 Flash Disk 中讀取 BMP File,執行演算法 ( LaneDetection() ) 7. CPU 將運算結果寫回 Flash Disk ( fwrite() )
8. 將結果顯示在螢幕上 ( Draw() )
圖3.8、轉存檔案格式流程