Пример #1
0
        public Node(Tree tree, int x, int y, int width, int height)
        {
            if (width < 1 || height < 1) {
                throw new ArgumentOutOfRangeException();
            }

            this.mX = x; this.mY = y;
            this.mWidth = width; this.mHeight = height;

            // Test if this node requires splitting.
            if (tree.IsNodeSplitRequired(this) == false) {

                // Assign colour - this is a leaf.
                mColour = tree.GetColourForNode(this);
            }
            else {

                // Split into four (half width, half height) sections.
                int newWidth = width / 2;
                int newHeight = height / 2;

                mChildNodes = new Node[4] { null, null, null, null };

                Node childNW = new Node(tree, x, y, newWidth, newHeight);
                mChildNodes[Node.NorthWest] = childNW;

                Node childSW = new Node(tree, x, y + newHeight, newWidth, newHeight);
                mChildNodes[Node.SouthWest] = childSW;

                Node childSE = new Node(tree, x + newWidth, y + newHeight, newWidth, newHeight);
                mChildNodes[Node.SouthEast] = childSE;

                Node childNE = new Node(tree, x + newWidth, y, newWidth, newHeight);
                mChildNodes[Node.NorthEast] = childNE;
            }
        }
Пример #2
0
        private void recursivelyGenerateTable(Node current, TableData tbd)
        {
            if (current.IsLeaf == false) {

                // If not a leaf, introduce a nested table.
                Table tbl = new Table();
                tbl.BackgroundColour = tbd.BackgroundColour;
                tbd.ChildElement = tbl;

                // Add children to this nested table in NW, NE, SW, SE order.
                TableRow tbr = null;
                for (int i = 0; i < 4; ++i) {

                    if (i % 2 == 0) {
                        tbr = new TableRow();
                        tbl.Rows.Add(tbr);
                    }

                    TableData tbdd = new TableData();
                    tbr.Cells.Add(tbdd);

                    recursivelyGenerateTable(current.ChildNodes[i], tbdd);

                }

            }
            else {

                // If a leaf, simply set the colour on the current element.
                tbd.BackgroundColour = current.Colour;
                tbd.Height = current.Height;
                tbd.Width = current.Width;
                tbd.ColumnSpan = 1;
            }
        }
Пример #3
0
        public bool IsNodeSplitRequired(Node node)
        {
            // Minimum width check.
            if (node.Width / 2 < mMinSize) {
                return false;
            }

            // Minimum height check.
            if (node.Height / 2 < mMinSize) {
                return false;
            }

            // Variance check.
            float variance = 0;

            unsafe {
                byte* imagePtr;

                // Calculate node average per channel.
                imagePtr = (byte*) (mImage.Scan0 + (mImage.Stride * node.Y) + (node.X * 3));

                float tR = 0, tG = 0, tB = 0;
                for (int i = 0; i < node.Height; ++i) {

                    for (int j = 0; j < node.Width; ++j) {

                        // Bitmap data held in BGR.
                        tR += imagePtr[2]; tG += imagePtr[1]; tB += imagePtr[0];

                        imagePtr += 3;
                    }

                    imagePtr += mImage.Stride - (node.Width * 3);
                }

                tR /= node.Area; tG /= node.Area; tB /= node.Area;

                // Now calculate variance over all channels.
                imagePtr = (byte*) (mImage.Scan0 + (mImage.Stride * node.Y) + (node.X * 3));

                for (int i = 0; i < node.Height; ++i) {

                    for (int j = 0; j < node.Width; ++j) {

                        // Bitmap data held in BGR.
                        float cR = imagePtr[2] - tR;
                        float cG = imagePtr[1] - tG;
                        float cB = imagePtr[0] - tB;

                        variance += (cR * cR) + (cG * cG) + (cB * cB);

                        imagePtr += 3;
                    }

                    imagePtr += mImage.Stride - (node.Width * 3);
                }
            }

            // If avg. variance is over threshold (multiplied by 3 due to 3 channels) split.
            if (variance >= mThreshold * mThreshold * 3 * node.Area) {
                return true;
            }

            return false;
        }
Пример #4
0
        /// <summary>
        /// Gets the average colour for this noe from the image.
        /// </summary>
        /// <returns>
        /// The colour for node.
        /// </returns>
        /// <param name='node'>
        /// Node.
        /// </param>
        public Color GetColourForNode(Node node)
        {
            int tR = 0, tG = 0, tB = 0;

            unsafe {
                byte* imagePtr = (byte*) (mImage.Scan0 + (mImage.Stride * node.Y) + (node.X * 3));

                for (int i = 0; i < node.Height; ++i) {

                    for (int j = 0; j < node.Width; ++j) {

                        // Bitmap data held in BGR.
                        tR += imagePtr[2]; tG += imagePtr[1]; tB += imagePtr[0];

                        imagePtr += 3;
                    }

                    imagePtr += mImage.Stride - (node.Width * 3);
                }
            }

            tR /= node.Area; tG /= node.Area; tB /= node.Area;

            return Color.FromArgb(tR, tG, tB);
        }
Пример #5
0
        public Tree(BitmapData img, int minSize, int threshold)
        {
            if (minSize < 1) {
                throw new ArgumentOutOfRangeException();
            }

            this.mMinSize = minSize;
            this.mImage = img;
            this.mThreshold = threshold;

            this.mRootNode = new Node(this, 0, 0, img.Width, img.Height);
        }