請問從擷圖到影像相減怎麼做比較快 |
答題得分者是:arisaka_matsuri
|
ciy
一般會員 發表:10 回覆:19 積分:5 註冊:2006-10-26 發送簡訊給我 |
以下是我的程式部分
麻煩各位大大看看 有沒有其他地方要改進或是有其他比較快的寫法 感恩~ <textarea class="cpp" rows="10" cols="60" name="code">//先抓一張背景圖------------------------------------------------------------- capFileSaveDIB(ghCapWnd1,"Picture\\pic.bmp"); Form1->Image2->Picture->LoadFromFile("Picture\\pic.bmp"); Graphics::TBitmap *Bitmap2=new Graphics::TBitmap; Byte *ptr2; Bitmap2= Image2->Picture->Bitmap; //以下寫在Timer裡---------------------------------------------------------- hDC = GetDC(Form1->Panel1->Handle); csBuf->Handle = hDC; Bitmap1->Width = Form1->Panel1->Width; Bitmap1->Height = Form1->Panel1->Height; Bitmap1->PixelFormat= pf24bit; Bitmap1->Canvas->CopyRect(Rect(0, 0, Bitmap1->Width, Bitmap1->Height), csBuf, Rect(0, 0, Form1->Panel1->Width, Form1->Panel1->Height)); Image1->Picture->Bitmap = Bitmap1 ; for ( y = Ymin; y < Ymax; y ) { ptr1 = (Byte *)Bitmap1->ScanLine[y]; ptr2 = (Byte *)Bitmap2->ScanLine[y]; for ( x = Xmin; x < Xmax; x ) { // 影像灰階化&影像相減 show1[x][y]=abs(0.299*(ptr1[x*3]-ptr2[x*3]) 0.587*(ptr1[x*3 1]-ptr2[x*3 1]) 0.114*(ptr1[x*3 2]-ptr2[x*3 2])); // 影像二值化閥值,用於過濾雜訊,將圖轉成白與黑------------------ if (show1[x][y] < TwoTh) //做第一張圖 { show1[x][y]=255; } else { show1[x][y]=0; } } </textarea><br /> ReleaseDC(0 , hDC); //最後少加了 |
taishyang
站務副站長 發表:377 回覆:5490 積分:4563 註冊:2002-10-08 發送簡訊給我 |
|
ciy
一般會員 發表:10 回覆:19 積分:5 註冊:2006-10-26 發送簡訊給我 |
|
taishyang
站務副站長 發表:377 回覆:5490 積分:4563 註冊:2002-10-08 發送簡訊給我 |
抱歉沒仔細看你的註解
我想能改的地方應該有 1.因為Timer的interval有極限,可以改用Thread 2.相減前轉灰階的地方可以用下面的方式(減少乘法與除法的運算)可以快一些 for (int x=0; x { BYTE grayVal = (Ptr[x] Ptr[x 1] Ptr[x 2])/3; ... } ===================引 用 ciy 文 章=================== 謝謝 taishyang 大大的回覆 可是我從檔案抓到 Image2 只抓了一次,就沒洗掉當背景圖 之後都由 hDC = GetDC(Form1->Panel1->Handle)....在抓圖相減 降會變慢嗎??
編輯記錄
taishyang 重新編輯於 2007-07-03 12:51:04, 註解 無‧
|
ciy
一般會員 發表:10 回覆:19 積分:5 註冊:2006-10-26 發送簡訊給我 |
謝謝 taishyang 大大的方法
我用了那個灰階化的方式似乎沒什麼變 速度依然維持在0.051秒 而關於Timer,我是用下方這種MMTimer的方式 不太懂 taishyang 大大說的thread...抱歉~ 因為我目前是要做即時處理 所以速度起碼要0.03秒才夠 經測試發現在影像擷取及相減這部分佔用最多時間 故希望能從此地方改進 <textarea class="cpp" rows="10" cols="60" name="code">int a = 0; HANDLE hEvent = CreateEvent(NULL, false, false, NULL); int TimerID = timeSetEvent(1, 0, (LPTIMECALLBACK)hEvent, 0, TIME_PERIODIC | TIME_CALLBACK_EVENT_SET); do { WaitForSingleObject(hEvent, INFINITE); Application->ProcessMessages(); Canvas->TextOut(400, 300, a); ////////////////////// // 放置主要程式碼 // a ; ////////////////////// } while (a <= 10000); timeKillEvent(TimerID); CloseHandle(hEvent); </body></html></textarea><br /> |
arisaka_matsuri
高階會員 發表:25 回覆:205 積分:231 註冊:2003-10-19 發送簡訊給我 |
要改善速度其實大有空間
影像擷取的部分可以參考taishyang版主的建議 用另外一個thread的方式運作 避免目前的thread都在等待影像資料從裝置進入記憶體的時間(我認為這應該是瓶頸) 另外就是影像相減部分的改善方式 以下是我的一點心得 測試環境:WinXP SP2 BCB 6.0 SP4 @ CPU 2.0G / dual core 測試影像:兩張640*480 24bpp RGB 影像相減取絕對值並取臨界值後,存成另一張640*480 24bpp RGB 計算執行時間方法:利用WinAPI QueryPerformanceFrequency() 與 QueryPerformanceCounter() 測試結果: Project Options / Compiler : Full Debug ciy's code:16~19 ms For-loop:6~7 ms While-loop : 6~7 ms Project Options / Compiler : Release ciy's code:13~14 ms For-loop:~3.1 ms While-loop : ~2.6 ms 以上結果可歸納成兩點結論 1. 善用compiler最佳化code的功能,同時關閉debug模式,會節省不少時間 2. 避免浮點數運算,簡化乘除法,或將乘除法改以bit shift達成 還可不可以更快?我想無庸置疑的是可以的 利用OpenMP(VC 8.0支援)或是多thread處理,有希望再省下30%時間 使用Intel IPP套件(MMX, SSE, SSE2指令),上述的處理不用花到1ms 還想再快?那就去找GPU來幫你吧! 測試程式碼 僅供參考,不代表可以在任何情況下執行 特別是While-loop的寫法需要對影像在記憶體中的排列方式很清楚,否則不建議使用 For-loop <textarea name="code" class="cpp" rows="10" cols="60"> Graphics::TBitmap *IMG1 = Image1->Picture->Bitmap; Graphics::TBitmap *IMG2 = Image2->Picture->Bitmap; Graphics::TBitmap *BMP = Image3->Picture->Bitmap; BYTE *ptr1; BYTE *ptr2; BYTE *ptr3; int value, lgray; for (int r = 0; r < 480; r) { ptr1 = (BYTE *)IMG1->ScanLine[r]; ptr2 = (BYTE *)IMG2->ScanLine[r]; ptr3 = (BYTE *)BMP->ScanLine[r]; for (int c = 0; c < 640; c) { lgray = abs((ptr1[c*3]-ptr2[c*3]) * 29 (ptr1[c*3 1]-ptr2[c*3 1]) * 150 (ptr1[c*3 2]-ptr2[c*3 2]) * 77); value = lgray >> 8; if (value < 64) { ptr3[c*3 0] = 0; ptr3[c*3 1] = 0; ptr3[c*3 2] = 0; } else { ptr3[c*3 0] = 255; ptr3[c*3 0] = 255; ptr3[c*3 0] = 255; } } } </textarea> While-loop <textarea cols="60" rows="10" class="cpp" name="code"> BYTE *EOM; ptr1 = (BYTE *)IMG1->ScanLine[479]; ptr2 = (BYTE *)IMG2->ScanLine[479]; ptr3 = (BYTE *)BMP->ScanLine[479]; EOM = (BYTE *)BMP->ScanLine[0] 640 * 3; while (ptr3 < EOM) { lgray = abs((*(ptr1)-*(ptr2)) * 29 (*(ptr1 1)-*(ptr2 1)) * 150 (*(ptr1 2)-*(ptr2 2)) * 77); value = lgray >> 8; if (value < 64) { *(ptr3 ) = 0; *(ptr3 ) = 0; *(ptr3 ) = 0; } else { *(ptr3 ) = 255; *(ptr3 ) = 255; *(ptr3 ) = 255; } ptr1 = 3; ptr2 = 3; } </textarea>
編輯記錄
arisaka_matsuri 重新編輯於 2007-07-05 15:56:48, 註解 無‧
arisaka_matsuri 重新編輯於 2007-07-05 15:58:16, 註解 無‧ arisaka_matsuri 重新編輯於 2007-07-05 16:01:13, 註解 無‧ |
ciy
一般會員 發表:10 回覆:19 積分:5 註冊:2006-10-26 發送簡訊給我 |
哇~~感謝 arisaka_matsuri 大大的回覆,
你說的那些數據 讓我又重新燃起希望! 試了For-loop程式碼和Full Debug和Release模式 真的有變快 不過只快了1~3 ms 可能跟我的硬體有關吧? 以下為我的測試環境:WinXP SP2 BCB 6.0 SP4 CPU 2.8G / Celeron(R) 測試影像:兩張320*240 RGB 影像相減取絕對值並取臨界值後算差異像素形心 另外關於你兩點結論底下提供的方法有點看不懂?可以發mail問你嗎? 也感謝taishyang 大大先前的回答~
編輯記錄
ciy 重新編輯於 2007-07-06 12:39:55, 註解 無‧
|
pwipwi
版主 發表:68 回覆:629 積分:349 註冊:2004-04-08 發送簡訊給我 |
您好:
程式碼中有一些可以再加快的地方: 1. x的indexing用x =3,之後ptr1[x*3]改為ptr1[x],ptr1[x*3 1]改為ptr1[x 1 2. 去除不必要的浮點數運算, abs(0.299*(ptr1[x*3]-ptr2[x*3]) 0.587*(ptr1[x*3 1]-ptr2[x*3 1]) 0.114*(ptr1[x*3 2]-ptr2[x*3 2])); 改成 int r = ptr1[x]-ptr2[x]; r *= 299; int g = ptr1[x 1]-ptr2[x 1]; g *= 587; int b = ptr1[x 2]-ptr2[x 2]; b *= 114; 以上的程式碼等於是用1000倍的整數運算 3.用一維陣列來存結果,可以使每一次indexing時少一個乘法運算 4.你抓圖的程式碼是抓取Panel上顯示的圖,速度會慢很多, 要是你是用Camera的我記得站上有標準的影像擷取程式碼 |
ciy
一般會員 發表:10 回覆:19 積分:5 註冊:2006-10-26 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |