線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2850
推到 Plurk!
推到 Facebook!

如何加快動態輪廓(Active contour)的運算效率? (附程式碼)

答題得分者是:plihui
skybow
一般會員


發表:10
回覆:10
積分:4
註冊:2004-04-30

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-06-28 16:52:57 IP:140.116.xxx.xxx 未訂閱
請教各位前輩,以下是我寫的動態輪廓演算法中,    用於計算輪廓上各點的8鄰近能量值的基礎部分~     此法用於萃取影像物體邊緣(segmentation),常用於醫學影像找出器官的輪廓~    我使用的初始輪廓是80點的橢圓形, 疊代次數10次,鄰近區域是3x3的範圍    但是由於程式功力有限,一值無法在33ms內完成10次的疊代,    (即使目前使用Celeron 2.6G處理器也需要62ms!! )    以致無法用於即時影像處理,不知各位是否有一些小技巧可以增進程式效率?    謝謝!    註一:本程式有使用Mil; 以下的核心公式主要就是計算輪廓上每一點的八鄰近各點的3個能量,共80點,重複10次=> 80點x9格x10次=7200次; 但是我這3個能量計算式就耗掉許多時間~ 不知是否有更快的寫法? 註二: initial_contour_x[80],initial_contour_y[80]是在別的函數定義的,指的是初始輪廓橢圓的X,Y座標點資料.         
 
 #define SNAKE_DIM 3 
 
 float  Image_Intensity_of_nbpoint_I[SNAKE_DIM][SNAKE_DIM],//外部能量
        Cont_of_nbpoint_I[SNAKE_DIM][SNAKE_DIM],//內部能量
        Curv_of_nbpoint_I[SNAKE_DIM][SNAKE_DIM],//內部能量
        avgdis_contour;//輪廓上每一點距離之平均     long ImagePitch;
 unsigned char *ImageDataPtr,*NowImageDataPtr;     MbufInquire(MilBuffer2Edge,M_HOST_ADDRESS,&ImageDataPtr);//取得影像起始位置
 MbufInquire(MilBuffer2Edge,M_PITCH,&ImagePitch);//取得影像pitch     //疊代10次
 for(int a=0;a<10;a  )
    {
     /*Start--of--SNAKE*/
     for(int i=0;i<80;i  ) //依序共80點
     {            
       for(int m=0;m<=2;m  ) //3x3的範圍
        {
          for(int n=0;n<=2;n  )
          {
             Cont_of_nbpoint_I[m][n]=fabs(avgdis_contour-float(sqrt(pow(double((initial_contour_x[i]-1 m)-initial_contour_x[i-1]),2.0) pow(double((initial_contour_y[i]-1 n)-initial_contour_y[i-1]),2.0))));
             Curv_of_nbpoint_I[m][n]=pow(double(initial_contour_x[i-1]-2*(initial_contour_x[i]-1 m) initial_contour_x[i 1]),2.0) pow(double(initial_contour_y[i-1]-2*(initial_contour_y[i]-1 n) initial_contour_y[i 1]),2.0);                 NowImageDataPtr=ImageDataPtr ImagePitch*(initial_contour_y[i]-1 n);
             Image_Intensity_of_nbpoint_I[m][n]=NowImageDataPtr[initial_contour_x[i]-1 m];              }
        }
         
     }/*End--of--SNAKE*/        }//end of the redo loop
發表人 - skybow 於 2004/06/28 17:12:04 發表人 - skybow 於 2004/06/28 17:14:39 發表人 - skybow 於 2004/06/28 17:15:40
dean
一般會員


發表:24
回覆:60
積分:21
註冊:2003-08-23

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-06-29 10:05:18 IP:192.192.xxx.xxx 未訂閱
skybow您好: 小弟對影像處理不是很了解,但看您的需求,小弟認為是不是可以用簡單的測邊演算法呢?應該可以用拉普拉資或是SOBEL等等之類的,小弟不是很了解,所以回答您的問題可能不是您所要的,可能您想過這個不是您要的,那小弟就很抱歉了!因為很可能沒幫到您!< > 下面的程式是小弟在站上看到某位大大的文章所教導的,小弟忘記是哪位前輩了,若有哪位前輩知道是誰的程式,請幫小弟提供來源,感激! < >
 for(int j=1; jHeight-1; j  ) {             //sobel
        ptr = (Byte *)Bmp->ScanLine[j];
        for(int i=1; iWidth-1; i  ) {
            sx = -1*Temp[j-1][i-1]   Temp[j 1][i-1] -2*Temp[j-1][i]  
                  2*Temp[j 1][i] - Temp[j-1][i 1]   Temp[j 1][i 1];                sy = -1*Temp[j-1][i-1] - 2*Temp[j][i-1] -1* Temp[j 1][i-1]  
                 Temp[j-1][i 1]   2*Temp[j][i 1]   Temp[j 1][i 1];                //if(sqrt(sx*sx sy*sy)>RealThreshold)
            if((abs(sx) abs(sy))>(int)RealThreshold) //gradient(梯度,梯度變化曲線)就是abs(sx) abs(sy)
            {
                ptr[i*3] = 255;
                ptr[i*3 1] = 255;
                ptr[i*3 2] = 255;
            }
            else
            {
                ptr[i*3] = 0;
                ptr[i*3 1] = 0;
                ptr[i*3 2] = 0;
            }
        }
    }
這樣之後,輪廓應該就很明顯了,接下來應該可以使用區域搜尋法去跑輪廓,應該就滿快的!因為少了很多計算! **我很想學,但又很不懂,所以一直問蠢問題,希望不要不屑我的問題,嘻嘻嘻**
dean
一般會員


發表:24
回覆:60
積分:21
註冊:2003-08-23

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-06-29 10:08:42 IP:192.192.xxx.xxx 未訂閱
不好意思! 手邊沒有這本書,但裡面有寫關於輪廓追蹤法,小弟沒有去研究過! 但提供您可以去看看,說不定他的寫法會是您要的! http://www.cs.ntust.edu.tw/~klchung/contents.htm 第三章 測邊 3.6 輪廓追蹤法 <=應該就是它吧
skybow
一般會員


發表:10
回覆:10
積分:4
註冊:2004-04-30

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-06-29 11:23:33 IP:140.116.xxx.xxx 未訂閱
To Dean:    感謝您的回應,您第一篇PO的程式就是Sobel Edge Detector,這部分我沒有問題~~  而您說的這本書我剛好就有,他只有提到基本的演算法,我也寫出來了,上篇我附的程式碼即是計算能量的部分~    我想我應該簡化我的問題, 我只是想問,在我的計算公式裡, 有用到乘除/開根號/取絕對值/平方的地方能否有更快的寫法?    譬如說, A除B寫成"A乘以B的倒數" 或是pow(a,2)寫成a*a會不會比較快呢???    因為我不清楚是否計算過程的微小時間差異在疊代7200次後就被放大,造成時間上的延誤?    我只是想讓這幾行簡單的公式運算速度更快而已... anyway,感謝您的回應!    
引言: 不好意思! 手邊沒有這本書,但裡面有寫關於輪廓追蹤法,小弟沒有去研究過! 但提供您可以去看看,說不定他的寫法會是您要的! http://www.cs.ntust.edu.tw/~klchung/contents.htm 第三章 測邊 3.6 輪廓追蹤法 <=應該就是它吧
fnk
高階會員


發表:40
回覆:149
積分:102
註冊:2004-01-02

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-06-30 22:14:39 IP:140.124.xxx.xxx 未訂閱
有沒有想過, 使用Look Up Table的做法呢 !!    如你所舉的例子,     數值 a 的平方為 pow(a,2),    在程式的一開始, 或許可以先把 Look Up Table 建起來,    假設你知道 a 的範圍為 -100 <= a <= 100 之間的整數,    那麼在程式的一開始, 就只要用 for 廻圏將計算好的數值存到 buffer 中,    如,    1. 初使存入數值到buffer中,     
 for (i=0;i<201;i  )
  buffer[i]=pow(i-100,2);
2. 取值時, 只要配合 index 就可以取出之前的計算結果, 在使用 Look Up Table 之前, 若要算出 a=10 的平方, 需要呼叫 pow(10,2), 現在只要,
 buffer[110] 
, 就可以取出值了, 這算是 "用空間換取時間吧" !! 但, 看你的算式相當複雜, 要實現可能要花一下時間, 希望對你有幫助 !! ^^
plihui
初階會員


發表:88
回覆:96
積分:41
註冊:2003-07-03

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-06-30 23:59:30 IP:218.168.xxx.xxx 未訂閱
[quote] To Dean: 感謝您的回應,您第一篇PO的程式就是Sobel Edge Detector,這部分我沒有問題~~ 而您說的這本書我剛好就有,他只有提到基本的演算法,我也寫出來了,上篇我附的程式碼即是計算能量的部分~ 我想我應該簡化我的問題, 我只是想問,在我的計算公式裡, 有用到乘除/開根號/取絕對值/平方的地方能否有更快的寫法? 譬如說, A除B寫成"A乘以B的倒數" 或是pow(a,2)寫成a*a會不會比較快呢??? 因為我不清楚是否計算過程的微小時間差異在疊代7200次後就被放大,造成時間上的延誤? 我只是想讓這幾行簡單的公式運算速度更快而已... anyway,感謝您的回應! [quote] 是的..直接減少函數(ex: pow())的使用,可以減少主程式和函數之間 程式控制權交換和傳出入參數所造成的延遲時間...以作業系統的觀念 (好像改善不大) 查表可以更快速的節省運算時間
系統時間:2024-05-20 23:02:48
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!