2016-11-04 120 views
1

我一直在嘗試用特定半徑rs =((int)2.75 * sigma + 0.5)的高斯核函數實現nxn圖像的高斯模糊函數。圍繞圖像邊緣的高斯模糊的「不連續」

for (x=0;x<n;x++){ 
    for (y=0;y<n;y++){ 

     sum=0.0,wsum=0.0; 

     //Position correction at the edges 

     if(x-rs<0){ 
      ix=0; 
     } 
     else ix=rs; 

     if(y-rs<0){ 
      iy=0; 
     } 
     else iy=rs; 

     if (x+rs>n-1){ 
      jx=n-1-x; 
     } 
     else jx=rs; 

     if (y+rs>n-1){ 
      jy=n-1-y; 
     } 
     else jy=rs; 
     //Kernel mean value correction at the edges 

     if (x-rs < 0){ 
      meanx=x+((int)rs/2); 
     } 
     else meanx=x; 

     if(y-rs<0){ 
      meany=y+((int)rs/2); 
     } 
     else meany=y; 

     if (x+rs>n-1){ 
      meanx=x-((int)rs/2); 
     } 
     else meanx=x; 

     if (y+rs>n-1){ 
      meany=y-((int)rs/2); 
     } 
     else meany=y; 


     for (i=x-ix;i<=x+jx;i++){ 
      for (j=y-iy;j<=y+jy;j++){ 

       weight=1/(2*M_PI*sigma*sigma)*exp(-((meanx-i)*(meanx-i)+(meany-j)*(meany-j))/(2*sigma*sigma)); 
       sum+=pic1.intenzity[i][j]*weight; 
       wsum+=weight; 
      } 
     } 

     pic2->intenzity[x][y]=((int)sum/wsum+0.5); 

     fprintf(fw,"%d\n",pic2->intenzity[x][y]); 
    } 

當我沒有在邊緣處使用平均值修正的結果是這樣的:

without mean value correction

,當我試圖轉移內核的平均值它創建一個間斷也是在圖像的右下方邊緣:

with shifting the mean value to rs/2

我不得不做出邊緣positio n的修正,因爲總和會溢出。現在看來,高斯卷積在某些原因下突然跳躍,當它位於rs和x和y的上邊和左邊時。我想讓它的行爲與它在圖像「內部」中的行爲相同,或者在位置接近邊緣時使強度消失爲0。

我可能會通過rs放大圖像,但它會導致邊緣位置的問題。

感謝您

+0

我沒有看到你的計算有什麼問題,但它可能是一個舍入誤差。如果您將所有數據存儲爲浮點數或雙精度執行計算,則您將轉換爲整數每一步的整數,然後在最後將其舍入到最接近的整數。每次你轉換爲int的方式都有很大的錯誤餘量。 –

+0

我嘗試將sum/wghtsum存儲到單獨的浮點矩陣中,然後再將它寫入int中的像素,但它做了同樣的事情。 – Martin

+0

我指的是你在幾乎每一步都要做的「int」投射。確保所有類型爲double的變量,並刪除每個「(int)」實例,這會在包含重要數據時截斷小數,尤其是因爲您執行了多次計算。你可能會被大量消費。 –

回答

0

讓我們來看看一個典型的濾波器內核應用於圖像的任何有見地的幫助:),在僞代碼。允許使用變量

# source[y][x] Old image (read-only) 
# target[y][x] New image (write-only) 
# image_height Image height (y = 0 .. image_height-1) 
# image_width  Image width (x = 0 .. image_width-1) 
# filter[y][x] Filter (weights) to be applied 
# filter_height Filter height (y = 0 .. filter_height-1) 
# filter_width Filter width (x = 0 .. filter_width-1) 
# filter_y  Target pixel y coordinate in filter (filter_height/2) 
# filter_x  Target pixel x coordinate in filter (filter_width/2) 

其中filter_y = floor(filter_width/2)filter_x = floor(filter_height/2)如果過濾器上的目標的像素(即,對稱的)居中。中的僞碼是大致然後

For base_y = 0 to image_height - 1: 

    # y range relative to base_y ... 
    min_y = -filter_y 
    max_y = filter_height - 1 - filter_y 

    # ... must not exceed the image boundaries. 
    If min_y + base_y < 0: 
     min_y = -base_y 
    End If 

    If max_y + base_y < 0: 
     max_y = -base_y 
    End If 

    If min_y + base_y >= image_height: 
     min_y = image_height - 1 - base_y 
    End If 

    If max_y + base_y >= image_height: 
     max_y = image_height - 1 - base_y 
    End If 

    For base_x = 0 to image_width - 1: 

     # x range relative to base_x ... 
     min_x = -filter_x 
     max_x = filter_width - 1 - filter_x 

     # ... must not exceed the image boundaries. 
     If min_x + base_x < 0: 
      min_x = -base_x 
     End If 

     If max_x + base_x < 0: 
      max_x = -base_x 
     End If 

     If min_x + base_x >= image_width: 
      min_x = image_width - 1 - base_x 
     End If 

     If max_x + base_x >= image_height: 
      max_x = image_width - 1 - base_x 
     End If 

     ValueSum = 0 
     WeightSum = 0 

     For y = min_y to max_y: 
      For x = min_x to max_x: 
       Value = source[y + base_y][x + base_x] 
       Weight = filter[y + filter_y][x + filter_x] 
       ValueSum = ValueSum + Value * Weight 
       WeightSum = WeightSum + Weight 
      End For 
     End For 

     If WeightSum != 0: 
      target[base_y][base_x] = ValueSum/WeightSum 
     End If 

    End For 
End For 

裏面的最內層循環,[base_y][base_x]指目標像素,我們計算一個;而[y+base_y][x+base_x]指的是由[y+filter_y][x+filter_x]加權的源像素。 xy是相對值,分別從-filter_x-filter_yfilter_width-1-filter_xfilter_height-1-filter_y

只要ValueSumWeightSum有足夠的範圍,相同的代碼工作,無論圖像和過濾器數據是整數還是浮點數。

最棘手的部分,並導致OP看到文物的一部分,是如何正確計算min_ymax_ymin_xmax_x

要調試,刪除這兩個內部循環,而是打印出類似這樣

printf("y = %d, ymin = %d (%d), ymax = %d (%d)\n", 
     base_y, min_y, min_y + base_y, max_y, max_y + base_y); 

外環(無需打印,每base_x!)裏面,

printf("x = %d, xmin = %d (%d), xmax = %d (%d)\n", 
     base_x, min_x, min_x + base_x, max_x, max_x + base_x); 

一次在最裏面的循環中(不需要再爲每個base_y打印一遍),例如if (y == 0) printf("...");。這將輸出image_width + image_height行,並讓您驗證您定義的範圍是否正確。

在OP的情況下,範圍在圖像邊緣附近是不正確的;即它們對應於上述僞代碼的一些if子句計算/分配不正確的min_x,max_x,min_ymax_y值。