예제 #1
0
 /// <summary>
 /// Marks a color space tag.
 /// </summary>
 /// <param name="cube">The cube.</param>
 /// <param name="label">A label.</param>
 private void Mark(ColorRange cube, byte label)
 {
     for (int r = cube.R0 + 1; r <= cube.R1; r++)
     {
         for (int g = cube.G0 + 1; g <= cube.G1; g++)
         {
             for (int b = cube.B0 + 1; b <= cube.B1; b++)
             {
                 tag[GetIndex(r, g, b)] = label;
             }
         }
     }
 }
예제 #2
0
        /// <summary>
        /// Builds the cube.
        /// </summary>
        /// <param name="colorCount">The color count.</param>
        private ColorRange[] BuildCube(ref int colorCount)
        {
            var cube = new ColorRange[colorCount];

            double[] vv = new double[colorCount];

            for (int i = 0; i < colorCount; i++)
            {
                cube[i] = new ColorRange();
            }

            cube[0].R0 = cube[0].G0 = cube[0].B0 = 0;
            cube[0].R1 = cube[0].G1 = cube[0].B1 = IndexCount - 1;

            int next = 0;

            for (int i = 1; i < colorCount; i++)
            {
                if (Cut(cube[next], cube[i]))
                {
                    vv[next] = cube[next].Volume > 1 ? Variance(cube[next]) : 0.0;
                    vv[i]    = cube[i].Volume > 1 ? Variance(cube[i]) : 0.0;
                }
                else
                {
                    vv[next] = 0.0;
                    i--;
                }

                next = 0;

                double temp = vv[0];
                for (int k = 1; k <= i; k++)
                {
                    if (vv[k] > temp)
                    {
                        temp = vv[k];
                        next = k;
                    }
                }

                if (temp <= 0.0)
                {
                    colorCount = i + 1;
                    break;
                }
            }

            return(cube);
        }
예제 #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="cube">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="wholeW">The whole weight.</param>
        /// <returns>The result.</returns>
        private double Maximize(ColorRange cube, int direction, int first, int last, out int cut, double wholeR, double wholeG, double wholeB, double wholeW)
        {
            long baseR = Bottom(cube, direction, vmr);
            long baseG = Bottom(cube, direction, vmg);
            long baseB = Bottom(cube, direction, vmb);
            long baseW = Bottom(cube, direction, vwt);

            double max = 0.0;

            cut = -1;

            for (int i = first; i < last; i++)
            {
                double halfR = baseR + Top(cube, direction, i, vmr);
                double halfG = baseG + Top(cube, direction, i, vmg);
                double halfB = baseB + Top(cube, direction, i, vmb);
                double halfW = baseW + Top(cube, direction, i, vwt);

                if (halfW == 0)
                {
                    continue;
                }

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

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

                if (halfW == 0)
                {
                    continue;
                }

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

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

            return(max);
        }
예제 #4
0
        /// <summary>
        /// Computes the weighted variance of a box.
        /// </summary>
        /// <param name="cube">The cube.</param>
        /// <returns>The result.</returns>
        private double Variance(ColorRange cube)
        {
            double dr = Volume(cube, vmr);
            double dg = Volume(cube, vmg);
            double db = Volume(cube, vmb);

            double xx = m2[GetIndex(cube.R1, cube.G1, cube.B1)]
                        - m2[GetIndex(cube.R1, cube.G1, cube.B0)]
                        - m2[GetIndex(cube.R1, cube.G0, cube.B1)]
                        + m2[GetIndex(cube.R1, cube.G0, cube.B0)]
                        - m2[GetIndex(cube.R0, cube.G1, cube.B1)]
                        + m2[GetIndex(cube.R0, cube.G1, cube.B0)]
                        + m2[GetIndex(cube.R0, cube.G0, cube.B1)]
                        - m2[GetIndex(cube.R0, cube.G0, cube.B0)];

            return(xx - (((dr * dr) + (dg * dg) + (db * db)) / Volume(cube, vwt)));
        }
예제 #5
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(ColorRange set1, ColorRange set2)
        {
            double wholeR = Volume(set1, vmr);
            double wholeG = Volume(set1, vmg);
            double wholeB = Volume(set1, vmb);
            double wholeW = Volume(set1, vwt);

            int cutr;
            int cutg;
            int cutb;

            double maxr = Maximize(set1, 2, set1.R0 + 1, set1.R1, out cutr, wholeR, wholeG, wholeB, wholeW);
            double maxg = Maximize(set1, 1, set1.G0 + 1, set1.G1, out cutg, wholeR, wholeG, wholeB, wholeW);
            double maxb = Maximize(set1, 0, set1.B0 + 1, set1.B1, out cutb, wholeR, wholeG, wholeB, wholeW);

            int dir;

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

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

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

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

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

            // Blue
            case 0:
                set2.B0 = set1.B1 = cutb;
                set2.R0 = set1.R0;
                set2.G0 = set1.G0;
                break;
            }

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

            return(true);
        }