2013-11-15 123 views
2

我需要實現Single Scale retinex and multiscale retinex algorithm在C#中,
我搜索了一下,但找不到任何有用的實踐項目和artilces代碼爲
我的理解正確我應該:的Retinex算法實現

  1. 轉換RGB爲YUV
  2. 模糊使用高斯模糊過濾器
  3. 使用I'(X,Y)= 255 *日誌10的圖像(I(X,Y)/ G(X,Y))+ 127.5
    I - 是照明,G - 高斯核函數,I' - 結果圖像
  4. Сonvert回YUV到RGB

此代碼不

public static Image<Bgr, byte> SingleScaleRetinex(this Image<Bgr, byte> img, int gaussianKernelSize, double sigma) 
      { 
       var radius = gaussianKernelSize/2; 
       var kernelSize = 2 * radius + 1; 

       var ycc = img.Convert<Ycc, byte>(); 

       var sum = 0f; 
       var gaussKernel = new float[kernelSize * kernelSize]; 
       for (int i = -radius, k = 0; i <= radius; i++, k++) 
       { 
        for (int j = -radius; j <= radius; j++) 
        { 
         var val = (float)Math.Exp(-(i * i + j * j)/(sigma * sigma)); 
         gaussKernel[k] = val; 
         sum += val; 
        } 
       } 
       for (int i = 0; i < gaussKernel.Length; i++) 
        gaussKernel[i] /= sum; 

       var gray = new Image<Gray, byte>(ycc.Size); 
       CvInvoke.cvSetImageCOI(ycc, 1); 
       CvInvoke.cvCopy(ycc, gray, IntPtr.Zero); 

       // Размеры изображения 
       var width = img.Width; 
       var height = img.Height; 

       var bmp = gray.Bitmap; 
       var bitmapData = bmp.LockBits(new Rectangle(Point.Empty, gray.Size), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); 

       unsafe 
       { 
        for (var y = 0; y < height; y++) 
        { 
         var row = (byte*)bitmapData.Scan0 + y * bitmapData.Stride; 
         for (var x = 0; x < width; x++) 
         { 
          var color = row + x; 

          float val = 0; 

          for (int i = -radius, k = 0; i <= radius; i++, k++) 
          { 
           var ii = y + i; 
           if (ii < 0) ii = 0; if (ii >= height) ii = height - 1; 

           var row2 = (byte*)bitmapData.Scan0 + ii * bitmapData.Stride; 
           for (int j = -radius; j <= radius; j++) 
           { 
            var jj = x + j; 
            if (jj < 0) jj = 0; if (jj >= width) jj = width - 1; 

            val += *(row2 + jj) * gaussKernel[k]; 

           } 
          } 

          var newColor = 127.5 + 255 * Math.Log(*color/val); 
          if (newColor > 255) 
           newColor = 255; 
          else if (newColor < 0) 
           newColor = 0; 
          *color = (byte)newColor; 
         } 
        } 
       } 
       bmp.UnlockBits(bitmapData); 

       CvInvoke.cvCopy(gray, ycc, IntPtr.Zero); 
       CvInvoke.cvSetImageCOI(ycc, 0); 

       return ycc.Convert<Bgr, byte>(); 

      } 
+0

你是否修復了你的代碼? – Abc

回答

0

對不起,necro-posting,但似乎在你的程序的第3步中有一個錯誤,可能會誤導過路的人。

爲了應用修正,您希望將源圖像除以高斯濾波的副本,而不是高斯內核本身。大約,在僞代碼:

I_filtered(x,y) = G(x,y) * I(x,y) 
I'(x,y) = log(I(x,y)/I_filtered(x,y)) 

,然後應用鑄造I'(x,y)所需數值類型(uint8,因爲我可以從原來的職位參考)。

更多關於該主題可以在this paper找到:

Ri(x, y) = log(Ii(x, y)) − log(Ii(x, y) ∗ F(x, y))

其中Ii 是第i個色通道中的輸入圖像,Ri 是第i對的Retinex輸出圖像 頻道和F是規範化的環繞聲功能。 。

+0

請在論文中包含鏈接中的相關部分。 – aiao

+0

更新了評論。 – melodisease