2013-03-15 81 views
1

我正在ARM上工作,並且我正在嘗試優化縮減採樣圖像,我已經使用OpenCV cv :: resize和其緩慢〜3ms的1280 * 960到400 * 300,我正在嘗試使用OpenMP來加速它,但是,在放置並行語句時,圖像已被扭曲。我知道這與線程之間的私有變量和共享數據有關,但我找不到問題。使用OpenMP來優化雙線性插值

void resizeBilinearGray(uint8_t *pixels, uint8_t *temp, int w, int h, int w2, int h2) { 

    int A, B, C, D, x, y, index, gray ; 
    float x_ratio = ((float)(w-1))/w2 ; 
    float y_ratio = ((float)(h-1))/h2 ; 
    float x_diff, y_diff; 
    int offset = 0 ; 


#pragma omp parallel for 
    for (int i=0;i<h2;i++) { 
     for (int j=0;j<w2;j++) { 
      x = (int)(x_ratio * j) ; 
      y = (int)(y_ratio * i) ; 
      x_diff = (x_ratio * j) - x ; 
      y_diff = (y_ratio * i) - y ; 
      index = y*w+x ; 

      // range is 0 to 255 thus bitwise AND with 0xff 
      A = pixels[index] & 0xff ; 
      B = pixels[index+1] & 0xff ; 
      C = pixels[index+w] & 0xff ; 
      D = pixels[index+w+1] & 0xff ; 

      // Y = A(1-w)(1-h) + B(w)(1-h) + C(h)(1-w) + Dwh 
      gray = (int)(
         A*(1-x_diff)*(1-y_diff) + B*(x_diff)*(1-y_diff) + 
         C*(y_diff)*(1-x_diff) + D*(x_diff*y_diff) 
         ) ; 

      temp[offset++] = gray ; 
     } 
    } 

} 

回答

2

爲什麼不嘗試用temp [i * w2 + j]替換temp [offset ++]?

您的抵消有多個問題。對於一個它有一個競爭條件。但更糟糕的是,OpenMP爲每個線程分配了非常不同的i和j值,因此他們正在讀取內存的非相鄰部分。這就是爲什麼你的圖像扭曲。

除了OpenMP之外,還有幾種其他方法可以加速您的代碼,您可以試試。我不瞭解ARM,但在英特爾,您可以通過SSE加快速度。另外,你可以嘗試修正浮點數。我已經發現兩種雙線性插值都可以加速。 fastcpp.blogspot.no/2011/06/bilinear-pixel-interpolation-using-sse.html

+0

所以你認爲我,K應該是私人變量?另一個嵌套循環呢? 我嘗試後,我會嘗試ARM霓虹燈 – 2013-03-16 12:41:54

+0

我和j已經是私人變量,因爲它是在openmp編譯後定義的。你有沒有嘗試我的建議? – 2013-03-16 13:15:22

+0

如果您想了解更多關於循環嵌套的信息,請參閱此鏈接。但它不會解決您的圖像失真問題。這是由於你如何使用偏移量。你需要用temp [i * w2 + j]替換temp [offset ++] http://bisqwit.iki.fi/story/howto/openmp/#ReductionClause – 2013-03-16 13:19:52

2

我認爲你的問題是offset變量。由於許多線程可以同時工作,因此您永遠不會知道哪個線程會首先更新偏移量。這就是爲什麼產生的圖像失真。

更好的策略是迭代所得到的圖像像素。對於每個生成的像素,您可以找到源圖像像素的座標,執行插值並寫入結果。這樣,您就可以確定每個線程都可以在不同的像素上工作,並且在正確的像素上工作。