Example #1
0
        // Universal method for dust, mist, fog
        // Source: http://colorimaginglab.ugr.es/pages/pdfs/ao_2015_B222/!
        public BaseMethodResponse RecoveringOfWeatherDegradedImagesBasedOnRGBResponseRatioConstancyMethod(
            Image <Bgr, Byte> image,
            RGBResponseRatioConstancyMethodParams _params
            )
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            Image <Bgr, Byte> result      = new Image <Bgr, byte>(image.Size);
            Image <Bgr, Byte> resultToAll = new Image <Bgr, byte>(image.Size);

            //Apply mean shift clustering
            MeanShiftClusteringAcordParams msParams = new MeanShiftClusteringAcordParams()
            {
                Kernel = _params?.MeanShiftParams?.Kernel ?? 5,
                Sigma  = _params?.MeanShiftParams?.Sigma ?? 0.13
            };
            var msResult = Clustering.MeanShiftAccord(image, msParams);
            var labels   = msResult.Labels.Distinct().ToArray(); //regions numbers

            //Find regions pixels coordinates
            var regionPixelsCoordinates = Clustering.GetRegionsPixelsCoordinates(msResult);

            //Loop through regions
            for (int region = 0; region < msResult.RegionCount; region++)
            {
                //Find min and max values for each channel
                var regionPixels = regionPixelsCoordinates[region].Select(coordinates => image[coordinates.X, coordinates.Y]).ToArray();

                var regionBValues = regionPixels.Select(p => p.Blue).ToArray();
                var regionGValues = regionPixels.Select(p => p.Green).ToArray();
                var regionRValues = regionPixels.Select(p => p.Red).ToArray();

                double[] minValues = new double[3] {
                    regionBValues.Min(), regionGValues.Min(), regionRValues.Min()
                };
                double[] maxValues = new double[3] {
                    regionBValues.Max(), regionGValues.Max(), regionRValues.Max()
                };

                int pixelsCountInRegion = regionPixelsCoordinates[region].Count;

                double B_min = minValues[0];
                double G_min = minValues[1];
                double R_min = minValues[2];

                double B_max = maxValues[0];
                double G_max = maxValues[1];
                double R_max = maxValues[2];

                if (_params.Imin != null)
                {
                    B_min = _params.Imin.Value;
                    G_min = _params.Imin.Value;
                    R_min = _params.Imin.Value;
                }
                if (_params.Imax != null)
                {
                    B_max = _params.Imax.Value;
                    G_max = _params.Imax.Value;
                    R_max = _params.Imax.Value;
                }

                //Apply formula
                for (int i = 0; i < pixelsCountInRegion; i++)
                {
                    var pixelCoordinates = regionPixelsCoordinates[region][i];
                    Bgr pixel            = image[pixelCoordinates.X, pixelCoordinates.Y];

                    double B = (pixel.Blue - B_min) * (B_max / (B_max - B_min));
                    double G = (pixel.Green - G_min) * (G_max / (G_max - G_min));
                    double R = (pixel.Red - R_min) * (R_max / (R_max - R_min));

                    result[pixelCoordinates.X, pixelCoordinates.Y] = new Bgr(B, G, R);
                }
            }

            //apply for all image

            //Find min and max values for each channel
            double[] minValues2;
            double[] maxValues2;
            Point[]  minLocations2;
            Point[]  maxLocations2;
            image.MinMax(out minValues2, out maxValues2, out minLocations2, out maxLocations2);

            double B_min2 = minValues2[0];
            double G_min2 = minValues2[1];
            double R_min2 = minValues2[2];

            double B_max2 = maxValues2[0];
            double G_max2 = maxValues2[1];
            double R_max2 = maxValues2[2];

            if (_params.Imin != null)
            {
                B_min2 = _params.Imin.Value;
                G_min2 = _params.Imin.Value;
                R_min2 = _params.Imin.Value;
            }
            if (_params.Imax != null)
            {
                B_max2 = _params.Imax.Value;
                G_max2 = _params.Imax.Value;
                R_max2 = _params.Imax.Value;
            }

            for (int m = 0; m < image.Rows; m++)
            {
                for (int n = 0; n < image.Cols; n++)
                {
                    Bgr pixel = image[m, n];

                    double B = (pixel.Blue - B_min2) * (B_max2 / (B_max2 - B_min2));
                    double G = (pixel.Green - G_min2) * (G_max2 / (G_max2 - G_min2));
                    double R = (pixel.Red - R_min2) * (R_max2 / (R_max2 - R_min2));

                    resultToAll[m, n] = new Bgr(B, G, R);
                }
            }

            if (_params.ShowWindows)
            {
                EmguCvWindowManager.Display(image, "1. image");
                EmguCvWindowManager.Display(msResult.Image, "2. MS");
                EmguCvWindowManager.Display(resultToAll, "3. resultToAll");
                EmguCvWindowManager.Display(result, "4. result");
            }

            stopwatch.Stop();

            return(new BaseMethodResponse
            {
                EnhancementResult = result,
                DetectionResult = new Image <Gray, byte>(image.Size),
                DetailedResults = new List <IInputArray> {
                    image, msResult.Image, resultToAll, result
                },
                ExecutionTimeMs = stopwatch.ElapsedMilliseconds
            });
        }
Example #2
0
        // Source - https://jivp-eurasipjournals.springeropen.com/articles/10.1186/s13640-016-0138-1
        public static Image <Bgr, Byte> Adaptive(Image <Bgr, Byte> image, bool showWindows = false)
        {
            Image <Hsv, Byte>    hsvImage;
            Image <Gray, Byte>   grayImage;
            Image <Gray, double> grayImageNormilized;
            Image <Gray, Byte>   grayImageEnhanced;
            Image <Gray, double> grayImageEnhancedNormilized;
            Image <Hsv, Byte>    hsvImageEnhanced;
            Image <Bgr, Byte>    result;

            // Color image?
            // FOR NOW CONSIDER ONLY COLOR IMAGES
            bool isColorImage = true;

            // RGB to HSV and take V
            hsvImage = ImageHelper.ToHsv(image);
            var hsvChannels = hsvImage.Split();

            grayImage = hsvChannels.ElementAt(2);

            // Normalize image
            grayImageNormilized = ImageHelper.NormalizeImage(grayImage);

            // Low contrast image?
            bool isLowContrastImage;
            bool isDarkImage;

            double[] pixelValues         = ImageHelper.GetImagePixels(grayImageNormilized);
            double[] positivePixelValues = pixelValues.Where(x => x > 0).ToArray();   // filter 0 values to retrieve more accurate results (according to article)
            double   mu    = StatisticsHelper.Average(positivePixelValues);           // mean of the image intensity
            double   sigma = StatisticsHelper.StandartDeviation(positivePixelValues); // standard deviation

            Func <List <string> > g = () =>
            {
                string Q1 = "Q1"; // low-contrast class
                string Q2 = "Q2"; // high (or moderate) contrast class

                string QSubclassDark   = "Dark";
                string QSubclassBright = "Bright";

                string Q;
                string QSubclass;

                // D=diff((μ+2σ),(μ−2σ))
                //double D = (mu + 2.0 * sigma) - (mu - 2.0 * sigma);
                double D = 4.0 * sigma; // seci=ond criteria

                //  τ is a parameter used for defining the contrast of an image
                double tao = 3.0; // τ=3 is a suitable choice for characterizing the contrasts of different images.

                if (D <= (1.0 / tao))
                {
                    Q = Q1;
                }
                else
                {
                    Q = Q2;
                }

                if (mu >= 0.5)
                {
                    QSubclass = QSubclassBright;
                }
                else
                {
                    QSubclass = QSubclassDark;
                }

                return(new List <string>()
                {
                    Q,
                    QSubclass
                });
            };

            List <string> imageClasses = g();

            isLowContrastImage = imageClasses[0] == "Q1" ? true : false;
            isDarkImage        = imageClasses[1] == "Dark" ? true : false;

            // Intensity transformation

            // c and γ are two parameters that control the shape of the transformation curve
            //  In contrast to traditional gamma correction, AGC sets the values of γ and c automatically using image information, making it an adaptive method
            double c     = default(double);
            double gamma = default(double);

            Func <double, double> Heaviside = (x) =>
            {
                if (x <= 0)
                {
                    return(0);
                }
                else // (x > 0)
                {
                    return(1);
                }
            };

            grayImageEnhancedNormilized = new Image <Gray, double>(grayImage.Size);

            for (int m = 0; m < grayImageNormilized.Rows; m++)
            {
                for (int n = 0; n < grayImageNormilized.Cols; n++)
                {
                    Gray   pixel = grayImageNormilized[m, n];
                    double I_in  = pixel.Intensity;

                    //// Enhancement of low-contrast image
                    if (isLowContrastImage)
                    {
                        // calc gamma
                        gamma = -Math.Log(sigma, newBase: 2);

                        // calc k
                        double I_gamma = Math.Pow(I_in, gamma);
                        double k       = I_gamma + (1 - I_gamma) * Math.Pow(mu, gamma);

                        // calc c
                        c = 1.0 / (1.0 + Heaviside(0.5 - mu) * (k - 1.0));

                        // Bright image in Q1
                        if (isDarkImage == false)
                        {
                            // mu  >= 0.5 => c = 1
                            //c = 1;
                        }
                        // Dark image in Q1
                        if (isDarkImage == true)
                        {
                            // mu < 0.5 => c = 1/k
                            //c = 1.0 / k;
                        }
                    }

                    ////  Enhancement of high- or moderate-contrast image
                    if (isLowContrastImage == false)
                    {
                        // calc gamma
                        gamma = Math.Exp((1.0 - (mu + sigma)) / 2.0);

                        // calc k
                        double I_gamma = Math.Pow(I_in, gamma);
                        double k       = I_gamma + (1.0 - I_gamma) * Math.Pow(mu, gamma);

                        // calc c
                        c = 1.0 / (1.0 + Heaviside(0.5 - mu) * (k - 1.0));

                        // Dark image in Q2
                        if (isDarkImage == true)
                        {
                            // For images with μ<0.5, (μ+σ)≤1, since both μ and σ are less than (or equal to) 0.5 which implies γ≥1
                        }

                        // Bright image in ϱ 2
                        if (isDarkImage == false)
                        {
                        }
                    }

                    // apply final formula
                    // I_out = c * I_in
                    double val = c * Math.Pow(I_in, gamma);
                    grayImageEnhancedNormilized[m, n] = new Gray(val);
                }
            }

            // DeNormalize image
            grayImage         = ImageHelper.DeNormalizeImage(grayImageNormilized);
            grayImageEnhanced = ImageHelper.DeNormalizeImage(grayImageEnhancedNormilized);

            // get enhanced hsv image
            hsvImageEnhanced = new Image <Hsv, byte>(new Image <Gray, Byte>[] { hsvChannels[0], hsvChannels[1], grayImageEnhanced });

            // convert hsv to rgb
            result = ImageHelper.ToBgr(hsvImageEnhanced);

            if (showWindows)
            {
                EmguCvWindowManager.Display(image, "AGC_V2_1 image");
                EmguCvWindowManager.Display(hsvImage, "AGC_V2_2 hsvImage");
                EmguCvWindowManager.Display(grayImage, "AGC_V2_3 grayImage");
                EmguCvWindowManager.Display(grayImageEnhanced, "AGC_V2_4 grayImageEnhanced");
                EmguCvWindowManager.Display(hsvImageEnhanced, "AGC_V2_5 hsvImageEnhanced");
                EmguCvWindowManager.Display(result, "AGC_V2_6 result");
            }

            return(result);
        }