Frage

Ich muss implementieren Einzelskaliger Retinex- und mehrskaliger Retinex-Algorithmus unter C#,
Ich habe ein bisschen gesucht, konnte aber keine nützlichen Übungsprojekte und Artikel mit Code finden
Wie ich richtig verstanden habe, sollte ich:

  1. Konvertieren von RGB in YUV
  2. Verwischen Sie das Bild mit dem Gaußschen Weichzeichnungsfilter
  3. Verwenden Sie I'(x, y) = 255 * log10 ( I (x, y) / G (x, y)) + 127,5
    I - ist Beleuchtung, G - Gaußscher Kern, I' - das Ergebnisbild
  4. YUV zurück in RGB konvertieren

Dieser Code funktioniert nicht richtig

 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>();

            }
War es hilfreich?

Lösung

ansehen: http://www.fer.unizg.hr/ipg/resources/color_constancy

Diese Algorithmen sind Modifikationen des Retinex-Algorithmus (mit einer Geschwindigkeitsverbesserung), obwohl der Autor ihnen lustige Namen gegeben hat :)

Es gibt einen Vollquellcode (C ++, aber es ist sehr schön geschrieben).

Andere Tipps

Entschuldigung für das Nekro-Posting, aber es scheint, dass in Schritt 3 Ihres Verfahrens ein Fehler vorliegt, der jemanden, der vorbeigeht, irreführen kann.

Um die Korrektur anzuwenden, möchten Sie das Quellbild durch eine Gaußgefilterte Kopie davon teilen, nicht durch den Gaußschen Kernel selbst.Ungefähr im Pseudocode:

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

Und dann Casting von anwenden I'(x,y) zum erforderlichen numerischen Typ (uint8, wie ich aus dem Originalbeitrag entnehmen kann).

Mehr zu diesem Thema finden Sie in dieses Papier:

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

wo Ii ist das Eingabebild auf dem i-ten Farbkanal, Ri ist das Retinex-Ausgabebild auf dem i-ten kanal und F ist die normalisierte Surround-Funktion..

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top