2016-03-07 23 views
2

我正在爲我的項目製作卷積濾波器,並且我設法使它適用於任何大小的矩陣,但隨着它變得更大我注意到並不是所有的位都改變了。 這裏是顯示問題圖片:C#用於任何大小的矩陣(1x1,3x3,5x5,...)未完全應用的卷積濾波器

第一個是原來的 enter image description here 過濾器:模糊9x9的

過濾器:邊緣檢測9x9的: enter image description here

正如你所看到的,有一點點條紋這是永遠不會改變,隨着矩陣變大,條紋也變得更大(在3x3中它不可見)

我的卷積矩陣類:

public class ConvMatrix 
{ 
    public int Factor = 1; 
    public int Height, Width; 
    public int Offset = 0; 
    public int[,] Arr; 

    //later I assign functions to set these variables 
    ... 
} 

過濾功能:

Bitmap Conv3x3(Bitmap b, ConvMatrix m) 
{ 
    if (0 == m.Factor) 
     return b; 

    Bitmap bSrc = (Bitmap)b.Clone(); 
    BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), 
         ImageLockMode.ReadWrite, 
         PixelFormat.Format24bppRgb); 
    BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), 
         ImageLockMode.ReadWrite, 
         PixelFormat.Format24bppRgb); 
    int stride = bmData.Stride; 

    System.IntPtr Scan0 = bmData.Scan0; 
    System.IntPtr SrcScan0 = bmSrc.Scan0; 

     unsafe 
     { 
      byte* p = (byte*)(void*)Scan0; 
      byte* pSrc = (byte*)(void*)SrcScan0; 
      int nOffset = stride - b.Width * m.Width; 
      int nWidth = b.Width - (m.Size-1); 
      int nHeight = b.Height - (m.Size-2); 

      int nPixel = 0; 

      for (int y = 0; y < nHeight; y++) 
      { 
       for (int x = 0; x < nWidth; x++) 
       { 
        for (int r = 0; r < m.Height; r++) 
        { 
         nPixel = 0; 
         for (int i = 0; i < m.Width; i++) 
          for (int j = 0; j < m.Height; j++) 
          { 
           nPixel += (pSrc[(m.Width * (i + 1)) - 1 - r + stride * j] * m.Arr[j, i]); 
          } 

         nPixel /= m.Factor; 
         nPixel += m.Offset; 

         if (nPixel < 0) nPixel = 0; 
         if (nPixel > 255) nPixel = 255; 
         p[(m.Width * (m.Height/2 + 1)) - 1 - r + stride * (m.Height/2)] = (byte)nPixel; 
        } 
        p += m.Width; 
        pSrc += m.Width; 
       } 
       p += nOffset; 
       pSrc += nOffset; 
      } 
     } 

    b.UnlockBits(bmData); 
    bSrc.UnlockBits(bmSrc); 
    return b; 
} 

請幫

回答

1

的問題是,你的代碼明確停止短邊緣。對於外部循環的限制(nWidthnHeight)的計算不應該包含矩陣的大小,它們應該等於您的位圖的大小。

當你這樣做時,如果你想象在這種情況下你將矩陣的中心點放在每個像素上會發生什麼(因爲你需要讀取所有像素的大小),矩陣將部分地位於圖像靠近邊緣。

有幾種方法可以在邊緣附近做什麼,但合理的方法是將座標固定到邊緣。即當您最終從位圖外部讀取像素時,只需從邊緣(大小或角落)獲取最近的像素即可。

我也不明白爲什麼你需要五個循環 - 你似乎在循環矩陣的高度兩次。這看起來不正確。總體結構應該是這樣的:

for (int y = 0; y < bitmap.Height; y++) { 
    for (int x = 0; x < bitmap.Width; x++) { 
    int sum = 0; 

    for (int matrixY = -matrix.Height/2; matrixY < matrix.Height/2; matrixY++) 
     for (int matrixX = -matrix.Width/2; matrixX < matrix.Width/2; matrixX++) { 
     // these coordinates will be outside the bitmap near all edges 
     int sourceX = x + matrixX; 
     int sourceY = y + matrixY; 

     if (sourceX < 0) 
      sourceX = 0; 

     if (sourceX >= bitmap.Width) 
      sourceX = bitmap.Width - 1; 

     if (sourceY < 0) 
      sourceY = 0; 

     if (sourceY >= bitmap.Height) 
      sourceY = bitmap.Height - 1; 

     sum += source[x, y]; 
     } 
    } 

    // factor and clamp sum 

    destination[x, y] = sum; 
    } 
} 

您可能需要一個額外的循環來處理每個需要單獨處理的顏色通道。我無法立即看到您的代碼中可能會從所有隱含變量中執行此操作。

+0

正如你所說,我需要一個更多的循環顏色,這就是爲什麼你看到5個循環那裏;)我沒有意識到錯誤,感謝清除出來。至於解決方案,我不能只是添加一些if語句來使這個工作?我現在沒有任何其他想法。 –

+0

哪個循環完成顏色?額外的「m.Height」?難道不是寧願去紅色,綠色和藍色?是的,如果夾緊的話可以。 'if(x <0)x = 0;'等等。可能會有更高效的方法來避免循環內部的條件,但是在擔心這些之前應該嘗試正確地工作。 –

+0

這是計算顏色值的行:nPixel + =(pSrc [(m.Width *(i + 1)) - 1 - r + stride * j] * m.Arr [j,i]) ;' –