2013-11-15 80 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