Esempio n. 1
0
        /// <summary>
        /// Computes the weighted variance of a box.
        /// </summary>
        /// <param name="c">The cube.</param>
        /// <returns>The result.</returns>
        private float Variance(ref Data.Box c)
        {
            float dr = WuQuant.Volume(ref c, this.vmr);
            float dg = WuQuant.Volume(ref c, this.vmg);
            float db = WuQuant.Volume(ref c, this.vmb);
            float da = WuQuant.Volume(ref c, this.vma);

            float xx =
                this.m2[WuQuant.GetIndex(c.R1, c.G1, c.B1, c.A1)]
                - this.m2[WuQuant.GetIndex(c.R1, c.G1, c.B1, c.A0)]
                - this.m2[WuQuant.GetIndex(c.R1, c.G1, c.B0, c.A1)]
                + this.m2[WuQuant.GetIndex(c.R1, c.G1, c.B0, c.A0)]
                - this.m2[WuQuant.GetIndex(c.R1, c.G0, c.B1, c.A1)]
                + this.m2[WuQuant.GetIndex(c.R1, c.G0, c.B1, c.A0)]
                + this.m2[WuQuant.GetIndex(c.R1, c.G0, c.B0, c.A1)]
                - this.m2[WuQuant.GetIndex(c.R1, c.G0, c.B0, c.A0)]
                - this.m2[WuQuant.GetIndex(c.R0, c.G1, c.B1, c.A1)]
                + this.m2[WuQuant.GetIndex(c.R0, c.G1, c.B1, c.A0)]
                + this.m2[WuQuant.GetIndex(c.R0, c.G1, c.B0, c.A1)]
                - this.m2[WuQuant.GetIndex(c.R0, c.G1, c.B0, c.A0)]
                + this.m2[WuQuant.GetIndex(c.R0, c.G0, c.B1, c.A1)]
                - this.m2[WuQuant.GetIndex(c.R0, c.G0, c.B1, c.A0)]
                - this.m2[WuQuant.GetIndex(c.R0, c.G0, c.B0, c.A1)]
                + this.m2[WuQuant.GetIndex(c.R0, c.G0, c.B0, c.A0)];

            return(xx - (((dr * dr) + (dg * dg) + (db * db) + (da * da)) / WuQuant.Volume(ref c, this.vwt)));
        }
Esempio n. 2
0
        private static int Top(ref Data.Box cube, int direction, int position, int[] moment)
        {
            switch (direction)
            {
            // Red
            case 3:
                return(moment[WuQuant.GetIndex(position, cube.G1, cube.B1, cube.A1)]
                       - moment[WuQuant.GetIndex(position, cube.G1, cube.B1, cube.A0)]
                       - moment[WuQuant.GetIndex(position, cube.G1, cube.B0, cube.A1)]
                       + moment[WuQuant.GetIndex(position, cube.G1, cube.B0, cube.A0)]
                       - moment[WuQuant.GetIndex(position, cube.G0, cube.B1, cube.A1)]
                       + moment[WuQuant.GetIndex(position, cube.G0, cube.B1, cube.A0)]
                       + moment[WuQuant.GetIndex(position, cube.G0, cube.B0, cube.A1)]
                       - moment[WuQuant.GetIndex(position, cube.G0, cube.B0, cube.A0)]);

            // Green
            case 2:
                return(moment[WuQuant.GetIndex(cube.R1, position, cube.B1, cube.A1)]
                       - moment[WuQuant.GetIndex(cube.R1, position, cube.B1, cube.A0)]
                       - moment[WuQuant.GetIndex(cube.R1, position, cube.B0, cube.A1)]
                       + moment[WuQuant.GetIndex(cube.R1, position, cube.B0, cube.A0)]
                       - moment[WuQuant.GetIndex(cube.R0, position, cube.B1, cube.A1)]
                       + moment[WuQuant.GetIndex(cube.R0, position, cube.B1, cube.A0)]
                       + moment[WuQuant.GetIndex(cube.R0, position, cube.B0, cube.A1)]
                       - moment[WuQuant.GetIndex(cube.R0, position, cube.B0, cube.A0)]);

            // Blue
            case 1:
                return(moment[WuQuant.GetIndex(cube.R1, cube.G1, position, cube.A1)]
                       - moment[WuQuant.GetIndex(cube.R1, cube.G1, position, cube.A0)]
                       - moment[WuQuant.GetIndex(cube.R1, cube.G0, position, cube.A1)]
                       + moment[WuQuant.GetIndex(cube.R1, cube.G0, position, cube.A0)]
                       - moment[WuQuant.GetIndex(cube.R0, cube.G1, position, cube.A1)]
                       + moment[WuQuant.GetIndex(cube.R0, cube.G1, position, cube.A0)]
                       + moment[WuQuant.GetIndex(cube.R0, cube.G0, position, cube.A1)]
                       - moment[WuQuant.GetIndex(cube.R0, cube.G0, position, cube.A0)]);

            // Alpha
            case 0:
                return(moment[WuQuant.GetIndex(cube.R1, cube.G1, cube.B1, position)]
                       - moment[WuQuant.GetIndex(cube.R1, cube.G1, cube.B0, position)]
                       - moment[WuQuant.GetIndex(cube.R1, cube.G0, cube.B1, position)]
                       + moment[WuQuant.GetIndex(cube.R1, cube.G0, cube.B0, position)]
                       - moment[WuQuant.GetIndex(cube.R0, cube.G1, cube.B1, position)]
                       + moment[WuQuant.GetIndex(cube.R0, cube.G1, cube.B0, position)]
                       + moment[WuQuant.GetIndex(cube.R0, cube.G0, cube.B1, position)]
                       - moment[WuQuant.GetIndex(cube.R0, cube.G0, cube.B0, position)]);

            default:
                throw new ArgumentOutOfRangeException("direction");
            }
        }
Esempio n. 3
0
        /// <summary>
        /// We want to minimize the sum of the variances of two sub-boxes.
        /// The sum(c^2) terms can be ignored since their sum over both sub-boxes
        /// is the same (the sum for the whole box) no matter where we split.
        /// The remaining terms have a minus sign in the variance formula,
        /// so we drop the minus sign and maximize the sum of the two terms.
        /// </summary>
        /// <param name="c">The cube.</param>
        /// <param name="direction">The direction.</param>
        /// <param name="first">The first position.</param>
        /// <param name="last">The last position.</param>
        /// <param name="cut">The cutting point.</param>
        /// <param name="wholeR">The whole red.</param>
        /// <param name="wholeG">The whole green.</param>
        /// <param name="wholeB">The whole blue.</param>
        /// <param name="wholeA">The whole alpha.</param>
        /// <param name="wholeW">The whole weight.</param>
        /// <returns>The result.</returns>
        private float Maximize(ref Data.Box c, int direction, int first, int last, out int cut, float wholeR, float wholeG, float wholeB, float wholeA, float wholeW)
        {
            int baseR = Bottom(ref c, direction, this.vmr);
            int baseG = WuQuant.Bottom(ref c, direction, this.vmg);
            int baseB = WuQuant.Bottom(ref c, direction, this.vmb);
            int baseA = WuQuant.Bottom(ref c, direction, this.vma);
            int baseW = WuQuant.Bottom(ref c, direction, this.vwt);

            float max = 0.0f;

            cut = -1;

            for (int i = first; i < last; i++)
            {
                float halfR = baseR + WuQuant.Top(ref c, direction, i, this.vmr);
                float halfG = baseG + WuQuant.Top(ref c, direction, i, this.vmg);
                float halfB = baseB + WuQuant.Top(ref c, direction, i, this.vmb);
                float halfA = baseA + WuQuant.Top(ref c, direction, i, this.vma);
                float halfW = baseW + WuQuant.Top(ref c, direction, i, this.vwt);

                if (halfW == 0)
                {
                    continue;
                }

                float temp = ((halfR * halfR) + (halfG * halfG) + (halfB * halfB) + (halfA * halfA)) / halfW;

                halfR = wholeR - halfR;
                halfG = wholeG - halfG;
                halfB = wholeB - halfB;
                halfA = wholeA - halfA;
                halfW = wholeW - halfW;

                if (halfW == 0)
                {
                    continue;
                }

                temp += ((halfR * halfR) + (halfG * halfG) + (halfB * halfB) + (halfA * halfA)) / halfW;

                if (temp > max)
                {
                    max = temp;
                    cut = i;
                }
            }

            return(max);
        }
Esempio n. 4
0
 /// <summary>
 /// Marks a color space tag.
 /// </summary>
 /// <param name="c">The cube.</param>
 /// <param name="label">A label.</param>
 private void Mark(ref Data.Box c, byte label)
 {
     for (int r = c.R0 + 1; r <= c.R1; r++)
     {
         for (int g = c.G0 + 1; g <= c.G1; g++)
         {
             for (int b = c.B0 + 1; b <= c.B1; b++)
             {
                 for (int a = c.A0 + 1; a <= c.A1; a++)
                 {
                     tag[GetIndex(r, g, b, a)] = label;
                 }
             }
         }
     }
 }
Esempio n. 5
0
 private static float Volume(ref Data.Box cube, int[] moment)
 {
     return((float)(moment[GetIndex(cube.R1, cube.G1, cube.B1, cube.A1)]
                    - moment[GetIndex(cube.R1, cube.G1, cube.B1, cube.A0)]
                    - moment[GetIndex(cube.R1, cube.G1, cube.B0, cube.A1)]
                    + moment[GetIndex(cube.R1, cube.G1, cube.B0, cube.A0)]
                    - moment[GetIndex(cube.R1, cube.G0, cube.B1, cube.A1)]
                    + moment[GetIndex(cube.R1, cube.G0, cube.B1, cube.A0)]
                    + moment[GetIndex(cube.R1, cube.G0, cube.B0, cube.A1)]
                    - moment[GetIndex(cube.R1, cube.G0, cube.B0, cube.A0)]
                    - moment[GetIndex(cube.R0, cube.G1, cube.B1, cube.A1)]
                    + moment[GetIndex(cube.R0, cube.G1, cube.B1, cube.A0)]
                    + moment[GetIndex(cube.R0, cube.G1, cube.B0, cube.A1)]
                    - moment[GetIndex(cube.R0, cube.G1, cube.B0, cube.A0)]
                    + moment[GetIndex(cube.R0, cube.G0, cube.B1, cube.A1)]
                    - moment[GetIndex(cube.R0, cube.G0, cube.B1, cube.A0)]
                    - moment[GetIndex(cube.R0, cube.G0, cube.B0, cube.A1)]
                    + moment[GetIndex(cube.R0, cube.G0, cube.B0, cube.A0)]));
 }
Esempio n. 6
0
        /// <summary>
        /// Cuts a box.
        /// </summary>
        /// <param name="set1">The first set.</param>
        /// <param name="set2">The second set.</param>
        /// <returns>Returns a value indicating whether the box has been split.</returns>
        private bool Cut(ref Data.Box set1, ref Data.Box set2)
        {
            float wholeR = WuQuant.Volume(ref set1, this.vmr);
            float wholeG = WuQuant.Volume(ref set1, this.vmg);
            float wholeB = WuQuant.Volume(ref set1, this.vmb);
            float wholeA = WuQuant.Volume(ref set1, this.vma);
            float wholeW = WuQuant.Volume(ref set1, this.vwt);

            int cutr;
            int cutg;
            int cutb;
            int cuta;

            float maxr = this.Maximize(ref set1, 3, set1.R0 + 1, set1.R1, out cutr, wholeR, wholeG, wholeB, wholeA, wholeW);
            float maxg = this.Maximize(ref set1, 2, set1.G0 + 1, set1.G1, out cutg, wholeR, wholeG, wholeB, wholeA, wholeW);
            float maxb = this.Maximize(ref set1, 1, set1.B0 + 1, set1.B1, out cutb, wholeR, wholeG, wholeB, wholeA, wholeW);
            float maxa = this.Maximize(ref set1, 0, set1.A0 + 1, set1.A1, out cuta, wholeR, wholeG, wholeB, wholeA, wholeW);

            int dir;

            if ((maxr >= maxg) && (maxr >= maxb) && (maxr >= maxa))
            {
                dir = 3;

                if (cutr < 0)
                {
                    return(false);
                }
            }
            else if ((maxg >= maxr) && (maxg >= maxb) && (maxg >= maxa))
            {
                dir = 2;
            }
            else if ((maxb >= maxr) && (maxb >= maxg) && (maxb >= maxa))
            {
                dir = 1;
            }
            else
            {
                dir = 0;
            }

            set2.R1 = set1.R1;
            set2.G1 = set1.G1;
            set2.B1 = set1.B1;
            set2.A1 = set1.A1;

            switch (dir)
            {
            // Red
            case 3:
                set2.R0 = set1.R1 = cutr;
                set2.G0 = set1.G0;
                set2.B0 = set1.B0;
                set2.A0 = set1.A0;
                break;

            // Green
            case 2:
                set2.G0 = set1.G1 = cutg;
                set2.R0 = set1.R0;
                set2.B0 = set1.B0;
                set2.A0 = set1.A0;
                break;

            // Blue
            case 1:
                set2.B0 = set1.B1 = cutb;
                set2.R0 = set1.R0;
                set2.G0 = set1.G0;
                set2.A0 = set1.A0;
                break;

            // Alpha
            case 0:
                set2.A0 = set1.A1 = cuta;
                set2.R0 = set1.R0;
                set2.G0 = set1.G0;
                set2.B0 = set1.B0;
                break;
            }

            set1.Volume = (set1.R1 - set1.R0) * (set1.G1 - set1.G0) * (set1.B1 - set1.B0) * (set1.A1 - set1.A0);
            set2.Volume = (set2.R1 - set2.R0) * (set2.G1 - set2.G0) * (set2.B1 - set2.B0) * (set2.A1 - set2.A0);

            return(true);
        }