HSL components.
The class encapsulates HSL color components.
Example #1
0
        /// <summary>
        /// Convert from HSL to RGB color space.
        /// </summary>
        ///
        /// <param name="hsl">Source color in <b>HSL</b> color space.</param>
        /// <param name="rgb">Destination color in <b>RGB</b> color space.</param>
        ///
        public static void ToRGB(HSL hsl, RGB rgb)
        {
            if (hsl.Saturation == 0)
            {
                // gray values
                rgb.Red = rgb.Green = rgb.Blue = (byte)(hsl.Luminance * 255);
            }
            else
            {
                float v1, v2;
                float hue = (float)hsl.Hue / 360;

                v2 = (hsl.Luminance < 0.5) ?
                     (hsl.Luminance * (1 + hsl.Saturation)) :
                     ((hsl.Luminance + hsl.Saturation) - (hsl.Luminance * hsl.Saturation));
                v1 = 2 * hsl.Luminance - v2;

                rgb.Red   = (byte)(255 * Hue_2_RGB(v1, v2, hue + (1.0f / 3)));
                rgb.Green = (byte)(255 * Hue_2_RGB(v1, v2, hue));
                rgb.Blue  = (byte)(255 * Hue_2_RGB(v1, v2, hue - (1.0f / 3)));
            }
            rgb.Alpha = 255;
        }
Example #2
0
        /// <summary>
        /// Paint the controls.
        /// </summary>
        /// 
        /// <param name="e">Paint event arguments.</param>
        /// 
        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Rectangle rc = this.ClientRectangle;
            Rectangle rcPie;
            Brush brush;
            RGB rgb = new RGB();
            HSL hsl = new HSL();

            // get pie rectangle
            rcPie = new Rectangle(4, 4, System.Math.Min(rc.Right, rc.Bottom) - 8, System.Math.Min(rc.Right, rc.Bottom) - 8);

            // init HSL value
            hsl.Luminance = 0.5f;
            hsl.Saturation = 1.0f;

            if (type == HuePickerType.Value)
            {
                // draw HSL pie
                for (int i = 0; i < 360; i++)
                {
                    hsl.Hue = i;
                    // convert from HSL to RGB
                    Accord.Imaging.HSL.ToRGB(hsl, rgb);
                    // create brush
                    brush = new SolidBrush(rgb.Color);
                    // draw one hue value
                    g.FillPie(brush, rcPie, -i, -1);

                    brush.Dispose();
                }
            }
            else
            {
                // draw HSL pie
                for (int i = 0; i < 360; i++)
                {
                    if (
                        ((min < max) && (i >= min) && (i <= max)) ||
                        ((min > max) && ((i >= min) || (i <= max))))
                    {
                        hsl.Hue = i;
                        // convert from HSL to RGB
                        Accord.Imaging.HSL.ToRGB(hsl, rgb);
                        // create brush
                        brush = new SolidBrush(rgb.Color);
                    }
                    else
                    {
                        brush = new SolidBrush(Color.FromArgb(128, 128, 128));
                    }

                    // draw one hue value
                    g.FillPie(brush, rcPie, -i, -1);

                    brush.Dispose();
                }
            }

            //
            double halfWidth = (double)rcPie.Width / 2;
            double angleRad = -min * System.Math.PI / 180;
            double angleCos = System.Math.Cos(angleRad);
            double angleSin = System.Math.Sin(angleRad);

            double x = halfWidth * angleCos;
            double y = halfWidth * angleSin;

            ptCenter.X = rcPie.Left + (int)(halfWidth);
            ptCenter.Y = rcPie.Top + (int)(halfWidth);
            ptMin.X = rcPie.Left + (int)(halfWidth + x);
            ptMin.Y = rcPie.Top + (int)(halfWidth + y);

            // draw MIN pointer
            g.FillEllipse(blackBrush,
                rcPie.Left + (int)(halfWidth + x) - 4,
                rcPie.Top + (int)(halfWidth + y) - 4,
                8, 8);
            g.DrawLine(blackPen, ptCenter, ptMin);

            // check picker type
            if (type == HuePickerType.Range)
            {
                angleRad = -max * System.Math.PI / 180;
                angleCos = System.Math.Cos(angleRad);
                angleSin = System.Math.Sin(angleRad);

                x = halfWidth * angleCos;
                y = halfWidth * angleSin;

                ptMax.X = rcPie.Left + (int)(halfWidth + x);
                ptMax.Y = rcPie.Top + (int)(halfWidth + y);

                // draw MAX pointer
                g.FillEllipse(whiteBrush,
                    rcPie.Left + (int)(halfWidth + x) - 4,
                    rcPie.Top + (int)(halfWidth + y) - 4,
                    8, 8);
                g.DrawLine(whitePen, ptCenter, ptMax);
            }

            base.OnPaint(e);
        }
Example #3
0
        // Gather statistics for the specified image
        private unsafe void ProcessImage(UnmanagedImage image, byte *mask, int maskLineSize)
        {
            // get image dimension
            int width  = image.Width;
            int height = image.Height;

            pixels = pixelsWithoutBlack = 0;

            int[] s   = new int[256];
            int[] l   = new int[256];
            int[] swb = new int[256];
            int[] lwb = new int[256];
            RGB   rgb = new RGB();
            HSL   hsl = new HSL();

            int pixelSize  = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
            int offset     = image.Stride - width * pixelSize;
            int maskOffset = maskLineSize - width;

            // do the job
            byte *p = (byte *)image.ImageData.ToPointer();

            if (mask == null)
            {
                // for each line
                for (int y = 0; y < height; y++)
                {
                    // for each pixel
                    for (int x = 0; x < width; x++, p += pixelSize)
                    {
                        rgb.Red   = p[RGB.R];
                        rgb.Green = p[RGB.G];
                        rgb.Blue  = p[RGB.B];

                        // convert to HSL color space
                        Accord.Imaging.HSL.FromRGB(rgb, ref hsl);

                        s[(int)(hsl.Saturation * 255)]++;
                        l[(int)(hsl.Luminance * 255)]++;
                        pixels++;

                        if (hsl.Luminance != 0.0)
                        {
                            swb[(int)(hsl.Saturation * 255)]++;
                            lwb[(int)(hsl.Luminance * 255)]++;
                            pixelsWithoutBlack++;
                        }
                    }
                    p += offset;
                }
            }
            else
            {
                // for each line
                for (int y = 0; y < height; y++)
                {
                    // for each pixel
                    for (int x = 0; x < width; x++, p += pixelSize, mask++)
                    {
                        if (*mask == 0)
                        {
                            continue;
                        }

                        rgb.Red   = p[RGB.R];
                        rgb.Green = p[RGB.G];
                        rgb.Blue  = p[RGB.B];

                        // convert to HSL color space
                        Accord.Imaging.HSL.FromRGB(rgb, ref hsl);

                        s[(int)(hsl.Saturation * 255)]++;
                        l[(int)(hsl.Luminance * 255)]++;
                        pixels++;

                        if (hsl.Luminance != 0.0)
                        {
                            swb[(int)(hsl.Saturation * 255)]++;
                            lwb[(int)(hsl.Luminance * 255)]++;
                            pixelsWithoutBlack++;
                        }
                    }
                    p    += offset;
                    mask += maskOffset;
                }
            }

            // create histograms
            saturation = new ContinuousHistogram(s, new Range(0, 1));
            luminance  = new ContinuousHistogram(l, new Range(0, 1));

            saturationWithoutBlack = new ContinuousHistogram(swb, new Range(0, 1));
            luminanceWithoutBlack  = new ContinuousHistogram(lwb, new Range(0, 1));
        }
Example #4
0
        /// <summary>
        ///   Creates a color histogram discarding low intensity colors
        /// </summary>
        /// 
        private unsafe float[] createHistogram(UnmanagedImage frame, Rectangle area)
        {
            int width = frame.Width;
            int height = frame.Height;
            int stride = frame.Stride;
            int pixelSize = Bitmap.GetPixelFormatSize(frame.PixelFormat) / 8;
            int offset = stride - area.Width * pixelSize;
            float[] histogram = new float[histogramSize];

            // stay inside the image
            int areaX = Math.Max(area.X, 0);
            int areaY = Math.Max(area.Y, 0);
            int areaWidth = Math.Min(area.Width, width - areaX);
            int areaHeight = Math.Min(area.Height, height - areaY);


            if (mode == CamshiftMode.HSL)
            {
                // Process as HSL
                HSL hsl = new HSL();
                RGB rgb = new RGB();

                byte* src = (byte*)frame.ImageData.ToPointer() + areaX * pixelSize + areaY * stride;
                for (int y = 0; y < areaHeight; y++)
                {
                    for (int x = 0; x < areaWidth; x++, src += 3)
                    {
                        rgb.Red = (*(src + RGB.R));
                        rgb.Green = (*(src + RGB.G));
                        rgb.Blue = (*(src + RGB.B));

                        Accord.Imaging.HSL.FromRGB(rgb, hsl);

                        if ((hsl.Saturation >= hslSaturation.Min) && (hsl.Saturation <= hslSaturation.Max) &&
                            (hsl.Luminance >= hslLuminance.Min) && (hsl.Luminance <= hslLuminance.Max))
                            histogram[hsl.Hue] += 1;
                    }
                    src += offset;
                }
            }
            else if (mode == CamshiftMode.Mixed)
            {
                // Process in mixed mode
                HSL hsl = new HSL();
                RGB rgb = new RGB();

                byte* src = (byte*)frame.ImageData.ToPointer() + areaX * pixelSize + areaY * stride;
                for (int y = 0; y < areaHeight; y++)
                {
                    for (int x = 0; x < areaWidth; x++, src += 3)
                    {
                        rgb.Red = (*(src + RGB.R));
                        rgb.Green = (*(src + RGB.G));
                        rgb.Blue = (*(src + RGB.B));

                        Accord.Imaging.HSL.FromRGB(rgb, hsl);

                        if ((hsl.Saturation >= hslSaturation.Min) && (hsl.Saturation <= hslSaturation.Max) &&
                            (hsl.Luminance >= hslLuminance.Min) && (hsl.Luminance <= hslLuminance.Max))
                            histogram[(int)(hsl.Hue * 10 + hsl.Saturation * 100 + hsl.Luminance * 10)] += 1;
                    }
                    src += offset;
                }
            }
            else
            {
                // Process as RGB
                byte* src = (byte*)frame.ImageData.ToPointer() + areaX * pixelSize + areaY * stride;
                for (int y = 0; y < areaHeight; y++)
                {
                    for (int x = 0; x < areaWidth; x++, src += 3)
                    {
                        // (small values are discarded)
                        int r = (int)(*(src + RGB.R)) >> 4;
                        int g = (int)(*(src + RGB.G)) >> 4;
                        int b = (int)(*(src + RGB.B)) >> 4;
                        histogram[256 * r + 16 * g + b] += 1;
                    }
                    src += offset;
                }
            }

            return histogram;
        }
Example #5
0
        /// <summary>
        ///   Image histogram back-projection.
        /// </summary>
        /// 
        private unsafe void generateBackprojectionMap(UnmanagedImage frame, float[] ratioHistogram)
        {
            int width = frame.Width;
            int height = frame.Height;
            int stride = frame.Stride;
            int pixelSize = Bitmap.GetPixelFormatSize(frame.PixelFormat) / 8;
            int offset = stride - width * pixelSize;

            fixed (float* map_ptr = map)
            {
                byte* src = (byte*)frame.ImageData.ToPointer();
                float* dst = map_ptr;

                if (mode == CamshiftMode.HSL)
                {
                    // Process as HSL
                    HSL hsl = new HSL();
                    RGB rgb = new RGB();

                    for (int y = 0; y < height; y++)
                    {
                        for (int x = 0; x < width; x++, src += pixelSize, dst++)
                        {
                            // RGB
                            rgb.Red = (*(src + RGB.R));
                            rgb.Green = (*(src + RGB.G));
                            rgb.Blue = (*(src + RGB.B));

                            // Transform into HSL
                            Accord.Imaging.HSL.FromRGB(rgb, hsl);

                            if ((hsl.Saturation >= hslSaturation.Min) && (hsl.Saturation <= hslSaturation.Max) &&
                                (hsl.Luminance >= hslLuminance.Min) && (hsl.Luminance <= hslLuminance.Max))
                                *dst = ratioHistogram[hsl.Hue];
                            else *dst = 0;
                        }
                        src += offset;
                    }
                }
                else if (mode == CamshiftMode.Mixed)
                {
                    // Process in mixed mode
                    HSL hsl = new HSL();
                    RGB rgb = new RGB();

                    for (int y = 0; y < height; y++)
                    {
                        for (int x = 0; x < width; x++, src += pixelSize, dst++)
                        {
                            // RGB
                            rgb.Red = (*(src + RGB.R));
                            rgb.Green = (*(src + RGB.G));
                            rgb.Blue = (*(src + RGB.B));

                            // Transform into HSL
                            Accord.Imaging.HSL.FromRGB(rgb, hsl);

                            if ((hsl.Saturation >= hslSaturation.Min) && (hsl.Saturation <= hslSaturation.Max) &&
                                (hsl.Luminance >= hslLuminance.Min) && (hsl.Luminance <= hslLuminance.Max))
                                *dst = ratioHistogram[(int)(hsl.Hue * 10 + hsl.Saturation * 100 + hsl.Luminance * 10)];
                            else *dst = 0;
                        }
                        src += offset;
                    }
                }
                else
                {
                    // Process as RGB
                    for (int y = 0; y < height; y++)
                    {
                        for (int x = 0; x < width; x++, src += pixelSize, dst++)
                        {
                            // RGB
                            int r = (int)(*(src + RGB.R)) >> 4;
                            int g = (int)(*(src + RGB.G)) >> 4;
                            int b = (int)(*(src + RGB.B)) >> 4;
                            *dst = ratioHistogram[256 * r + 16 * g + b];
                        }
                        src += offset;
                    }
                }
            }
        }
Example #6
0
        /// <summary>
        /// Convert from HSL to RGB color space.
        /// </summary>
        /// 
        /// <param name="hsl">Source color in <b>HSL</b> color space.</param>
        /// <param name="rgb">Destination color in <b>RGB</b> color space.</param>
        /// 
        public static void ToRGB(HSL hsl, RGB rgb)
        {
            if (hsl.Saturation == 0)
            {
                // gray values
                rgb.Red = rgb.Green = rgb.Blue = (byte)(hsl.Luminance * 255);
            }
            else
            {
                float v1, v2;
                float hue = (float)hsl.Hue / 360;

                v2 = (hsl.Luminance < 0.5) ?
                    (hsl.Luminance * (1 + hsl.Saturation)) :
                    ((hsl.Luminance + hsl.Saturation) - (hsl.Luminance * hsl.Saturation));
                v1 = 2 * hsl.Luminance - v2;

                rgb.Red = (byte)(255 * Hue_2_RGB(v1, v2, hue + (1.0f / 3)));
                rgb.Green = (byte)(255 * Hue_2_RGB(v1, v2, hue));
                rgb.Blue = (byte)(255 * Hue_2_RGB(v1, v2, hue - (1.0f / 3)));
            }
            rgb.Alpha = 255;
        }
Example #7
0
 /// <summary>
 /// Convert from RGB to HSL color space.
 /// </summary>
 /// 
 /// <param name="rgb">Source color in <b>RGB</b> color space.</param>
 /// 
 /// <returns>Returns <see cref="HSL"/> instance, which represents converted color value.</returns>
 /// 
 public static HSL FromRGB(RGB rgb)
 {
     HSL hsl = new HSL();
     FromRGB(rgb, hsl);
     return hsl;
 }
Example #8
0
        /// <summary>
        /// Convert from RGB to HSL color space.
        /// </summary>
        /// 
        /// <param name="rgb">Source color in <b>RGB</b> color space.</param>
        /// <param name="hsl">Destination color in <b>HSL</b> color space.</param>
        /// 
        /// <remarks><para>See <a href="http://en.wikipedia.org/wiki/HSI_color_space#Conversion_from_RGB_to_HSL_or_HSV">HSL and HSV Wiki</a>
        /// for information about the algorithm to convert from RGB to HSL.</para></remarks>
        /// 
        public static void FromRGB(RGB rgb, HSL hsl)
        {
            float r = (rgb.Red / 255.0f);
            float g = (rgb.Green / 255.0f);
            float b = (rgb.Blue / 255.0f);

            float min = Math.Min(Math.Min(r, g), b);
            float max = Math.Max(Math.Max(r, g), b);
            float delta = max - min;

            // get luminance value
            hsl.Luminance = (max + min) / 2;

            if (delta == 0)
            {
                // gray color
                hsl.Hue = 0;
                hsl.Saturation = 0.0f;
            }
            else
            {
                // get saturation value
                hsl.Saturation = (hsl.Luminance <= 0.5) ? (delta / (max + min)) : (delta / (2 - max - min));

                // get hue value
                float hue;

                if (r == max)
                {
                    hue = ((g - b) / 6) / delta;
                }
                else if (g == max)
                {
                    hue = (1.0f / 3) + ((b - r) / 6) / delta;
                }
                else
                {
                    hue = (2.0f / 3) + ((r - g) / 6) / delta;
                }

                // correct hue if needed
                if (hue < 0)
                    hue += 1;
                if (hue > 1)
                    hue -= 1;

                hsl.Hue = (int)(hue * 360);
            }
        }
        // Gather statistics for the specified image
        private unsafe void ProcessImage(UnmanagedImage image, byte* mask, int maskLineSize)
        {
            // get image dimension
            int width = image.Width;
            int height = image.Height;

            pixels = pixelsWithoutBlack = 0;

            int[] s = new int[256];
            int[] l = new int[256];
            int[] swb = new int[256];
            int[] lwb = new int[256];
            RGB rgb = new RGB();
            HSL hsl = new HSL();

            int pixelSize = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
            int offset = image.Stride - width * pixelSize;
            int maskOffset = maskLineSize - width;

            // do the job
            byte* p = (byte*)image.ImageData.ToPointer();

            if (mask == null)
            {
                // for each line
                for (int y = 0; y < height; y++)
                {
                    // for each pixel
                    for (int x = 0; x < width; x++, p += pixelSize)
                    {
                        rgb.Red = p[RGB.R];
                        rgb.Green = p[RGB.G];
                        rgb.Blue = p[RGB.B];

                        // convert to HSL color space
                        Accord.Imaging.HSL.FromRGB(rgb, hsl);

                        s[(int)(hsl.Saturation * 255)]++;
                        l[(int)(hsl.Luminance * 255)]++;
                        pixels++;

                        if (hsl.Luminance != 0.0)
                        {
                            swb[(int)(hsl.Saturation * 255)]++;
                            lwb[(int)(hsl.Luminance * 255)]++;
                            pixelsWithoutBlack++;
                        }
                    }
                    p += offset;
                }
            }
            else
            {
                // for each line
                for (int y = 0; y < height; y++)
                {
                    // for each pixel
                    for (int x = 0; x < width; x++, p += pixelSize, mask++)
                    {
                        if (*mask == 0)
                            continue;

                        rgb.Red = p[RGB.R];
                        rgb.Green = p[RGB.G];
                        rgb.Blue = p[RGB.B];

                        // convert to HSL color space
                        Accord.Imaging.HSL.FromRGB(rgb, hsl);

                        s[(int)(hsl.Saturation * 255)]++;
                        l[(int)(hsl.Luminance * 255)]++;
                        pixels++;

                        if (hsl.Luminance != 0.0)
                        {
                            swb[(int)(hsl.Saturation * 255)]++;
                            lwb[(int)(hsl.Luminance * 255)]++;
                            pixelsWithoutBlack++;
                        }
                    }
                    p += offset;
                    mask += maskOffset;
                }
            }

            // create histograms
            saturation = new ContinuousHistogram(s, new Range(0, 1));
            luminance = new ContinuousHistogram(l, new Range(0, 1));

            saturationWithoutBlack = new ContinuousHistogram(swb, new Range(0, 1));
            luminanceWithoutBlack = new ContinuousHistogram(lwb, new Range(0, 1));
        }