سؤال

أحتاج إلى التنفيذ خوارزمية ريتينكس أحادية النطاق وخوارزمية ريتينكس متعددة النطاق شركة#،
لقد بحثت قليلاً ولكن لم أتمكن من العثور على أي مشاريع تدريبية مفيدة ومقالات تحتوي على التعليمات البرمجية
كما فهمت بشكل صحيح يجب أن:

  1. تحويل RGB إلى YUV
  2. قم بطمس الصورة باستخدام مرشح التمويه Gaussian
  3. استخدم I'(x, y) = 255*log10( I(x, y)/G(x, y)) + 127.5
    I - هي الإضاءة، G - النواة الغوسية، I - الصورة الناتجة
  4. تحويل مرة أخرى 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>();

            }
هل كانت مفيدة؟

المحلول

إلقاء نظرة على: http://www.fer.unizg.hr/ipg/resources/color_constancy

هذه الخوارزميات هي تعديلات لخوارزمية Retinx (مع تحسين السرعة) على الرغم من أن المؤلف أعطاهم أسماء مضحكة :)

هناك شفرة مصدر كامل (C ++، ولكنها مكتوبة بشكل جيد للغاية).

نصائح أخرى

نأسف على النشر غير الدقيق، ولكن يبدو أن هناك خطأ في الخطوة 3 من الإجراء الخاص بك والذي يمكن أن يضلل أي شخص يمر.

من أجل تطبيق التصحيح، تحتاج إلى تقسيم الصورة المصدر على نسخة منها تمت تصفيتها بواسطة Gauss، وليس على النواة Gaussian نفسها.تقريبًا، بالرمز الزائف:

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, ، كما أستطيع أن أشير من المشاركة الأصلية).

المزيد عن هذا الموضوع يمكن العثور عليها في هذه الورقة:

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

أين Iiهي صورة الإدخال على قناة الألوان i، Riهل صورة إخراج Retinex على القناة I-Th و F هي وظيفة الصوت المحيطي الطبيعية..

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top