Domanda

Ho bisogno di implementare algoritmo retinesso retinex e multiscalzi singola scala in c #,
Ho cercato un po 'ma non ho trovato alcun utile progetti di pratica e artilze con il codice Come ho capito correttamente dovrei:

    .
  1. Converti RGB in YUV
  2. Blocca l'immagine utilizzando il filtro sfocatura gaussiano
  3. Usa I '(x, y)= 255 * log10 (i (x, y) / g (x, y)) + 127.5 Io - è l'illuminazione, G - Gaussian Kernel, io '- l'immagine dei risultati
  4. Сonvert Back yuv in rgb
  5. Questo codice non funziona correttamente

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

È stato utile?

Soluzione

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

Questi algoritmi sono modifiche dell'algoritmo reinesso (con miglioramento della velocità) sebbene l'autore abbia dato loro nomi divertenti :)

C'è un codice fonte completo (C ++, ma è scritto molto bene).

Altri suggerimenti

Ci scusiamo per la necro-post, ma sembra che ci sia un errore nel passaggio 3 della tua procedura che può ingannare qualcuno che passa.

Per applicare la correzione, si desidera dividere l'immagine di origine dalla copia filtrata Gauss, non il kernel gaussiano stesso.Approssimativamente, in pseudo-codice:

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

e quindi applicare la fusione di I'(x,y) al tipo numerico richiesto (uint8, poiché posso fare riferimento dal post originale).

Più su quell'argomento può essere trovato in Questo documento :

.

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

dove Ii L'immagine di input è sul canale di colore i-th, Ri L'immagine in uscita reinex è sull'i-th Channel e F è la funzione surround normalizzata. .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top