part D: 透過預覽回呼函數將圖片置入視訊擷取視窗之中
2009S 的課程中, 我花了很多時間在網路上找龍珠的圖片, 最後終於在 伊莉討論區 的這張圖中找到, 如圖 4-D-1。
圖 4-D-1
然後用 Photoshop 把龍珠擷取出來, 並且, 將四星龍珠, 一一修改成下列一星至七星龍珠。由於龍珠圖片中, 左上及右下各有一塊白色區域, 因此若背景色設定為白色, 將來將龍珠放進視訊時, 這兩塊白色區域就會也一併變成背景, 無法呈現出來, 因此, 我們將背景色改成純紅色。如圖 4-D-2。
圖 4-D-2
接著, 新增一個 TImage 元件到 Capture Window 分頁之中, 如圖 4-D-3。
圖 4-D-3
並將其 Name Property 改為 imDragonBall4, 然後點選兩下 Property Picture, 開啟如圖 4-D-4 的畫面, 並按 Button Load... 將四星龍珠讀取進來。
圖 4-D-4
最後, 按下 Button OK 之後, 就會呈現圖 4-D-5 的畫面, 四星龍珠已經顯示在影像元件 imDragonBall4 之中了。
圖 4-D-5
如果繼續將影像元件 imDragonBall4 的 Property Transparent 設定為 true, 這時四星龍珠圖片的背景色 - 紅色, 就不會顯示出來, 如圖 4-D-6。
圖 4-D-6
將影像載入(Load)之後, 還必須先將影像的色彩資料用陣列儲存起來備用。因此, 必須宣告一個四維陣列, 來儲存七顆龍珠的色彩資料。
unsigned char ucDragonBallRGB[7][50][50][3];
unsigned char ucDragonBallYUV[7][50][50][3];
然後將色彩讀取到陣列的程式, 寫在功能表 preview callback function | Object | Image 的事件處理程序中, 如圖 4-D-7 的功能表 。詳見範例程式 Webcam Programming (4), 程式中比較特殊的指令是 ScanLine[j]。透過 ScanLine 的位址, 可以將存在影像元件的像素色彩値讀取出來, 放到預先宣告的陣列 ucDragonBallRGB 之中。然後再將其轉換成 YUV 色彩値存入與先宣告的 ucDragonBallYUV 陣列之中。
圖 4-D-7
在預覽回呼函數 FrameCallBackImage 要注意的是: 只要介於座標 (iObjectX1, iObjectY1) 與 (iObjectX2, iObjectY2) 之間的區域就要置入龍珠圖片, 但龍珠圖片的背景區域必須忽略, 無須置入。如此, 就可以完成將龍珠圖片放進視訊擷取視窗了, 如圖 4-D-8。
圖 4-D-8
接下來, 要示範的是: 無須更改預覽回呼函數, 就可以隨使用者的設定, 變換在視訊擷取視窗的圖片的程式寫法。先將七顆龍珠的圖片, 放到視訊擷取視窗的分頁之中, 然後宣告一個變數來儲存使用者所選定的龍珠編號。
int iDragonBallID;
當使用者選定了某顆龍珠, 只要將變數 iDragonBallID 改成使用者所選定的編號即可。然後將預覽回呼函數 FrameCallBackImage 中, 原先寫定的値, 用變數取代, 這樣就可以讓使用者隨時改變要顯示的龍珠了, 如圖 4-D-9。
圖 4-D-9
延伸思考: 如何讓龍珠動起來?
4. 作業三(a) : 為你的視訊製作一個美麗的畫框, 如圖 4-D-10。
Step 1: 製作一張 640*480 的畫框 bmp 影像, 並選定特定顏色為顯示視訊區域之特定顏色。
Step 2: 在 C++ Builder 新增一個 TImage 影像元件, 並將畫框影像載入影像元件之中。
Step 3: 宣告一個陣列作為存放影像色彩值之用。
Step 4: 在設定預覽回呼函數之前, 將影像色彩值讀入陣列之中。
Step 5: 撰寫預覽回呼函數
提醒: 視訊大小與畫框大小目前是一樣大的, 因此只要去判斷畫框的顏色是否為特定顏色即可, 只要是特定顏色, 就顯示視訊內容, 否則, 則顯示畫框內容。
圖 4-D-10
作業 : 將視訊擷取視窗設定成特定色調, 如棕色色調的復古模式, 藍色色調的海洋模式, 綠色色調的大自然模式...等等。
2 則留言:
老師您好,關於將龍珠放入圖像中的程式碼.有個地方不是很懂..
將龍珠放入圖像中的兩個迴圈中其中的迴圈
for (int i=0;i<iVideoWidth;i=i+2)
她的 i為什麼要用i+2而不是i++呢?
(若是使用i++的話 則龍珠的位置會跑掉..而且整個龍珠會變大擴散到圖像的右下角)
wiki 了一下!!
YUY2在水平採樣的時候是每兩個採樣一次!!所以迴圈設i=i+2才對!!
若是用i++ 屆時顯示上會整個散開~
張貼留言