Click here to Skip to main content
15,891,253 members
Articles / Programming Languages / C#

Split a Single-Pixel-Width Connected Line Graph Into Line Segments by The Hit-and-Miss Transformation

Rate me:
Please Sign up or sign in to vote.
4.89/5 (13 votes)
16 Aug 20078 min read 58.9K   976   58  
Split a single-pixel-width connected line graph into line segments by the Hit-and-Miss transformation.
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace LineSegmentSplitter
{
    class FreeEndDetector
    {
        #region Fields
        private List<bool[,]> _kernelType1List; // one and only one neighbourhood * 8
        private List<bool[,]> _kernelType2List; // L shape ends * 8
        private List<bool[,]> _kernelType3List; // T shape ends * 8
        private List<Point> _freeEndList;  // free end points list
        #endregion

        #region Fields
        public List<Point> FreeEndList { get { return _freeEndList; } }
        #endregion

        #region Constructor
        public FreeEndDetector()
        {
            PrepareKernels();
        }
        #endregion

        #region Apply
        public bool[,] Apply(bool[,] srcBoolMatrix)       
        {
            // AndTrue operations with 16 kernels
            List<bool[,]> dstMatrixList = new List<bool[,]>(20);
            for (int i = 0; i < 8; i++)
                dstMatrixList.Add(HitAndMissTransformation.AndTrueFalse2D(srcBoolMatrix, (bool[,])_kernelType1List[i]));
            for (int i = 0; i < 8; i++)
                dstMatrixList.Add(HitAndMissTransformation.AndTrueFalse2D(srcBoolMatrix, (bool[,])_kernelType2List[i]));
            for (int i = 0; i < 4; i++)
                dstMatrixList.Add(HitAndMissTransformation.AndTrueFalse2D(srcBoolMatrix, (bool[,])_kernelType3List[i]));

            // OR all dstMatrixs
            bool[,] dstMatrix = (bool[,])dstMatrixList[0];
            int height = dstMatrix.GetLength(1);
            int width = dstMatrix.GetLength(0);

            bool temp;
            for (int i = 1; i < 20; i++)
            // for each AndTrue output
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {

                        temp = ((bool[,])dstMatrixList[i])[x, y];
                        dstMatrix[x, y] = dstMatrix[x, y] || temp;
                    }
                }
            }

            _freeEndList = new List<Point>(0);
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    if (dstMatrix[x, y])
                        _freeEndList.Add(new Point(x, y));
                }
            }

            return dstMatrix;
        } // Apply()       
        #endregion

        #region prepare kernel
        /// <summary>
        /// prepare kernels
        /// </summary>
        private void PrepareKernels()
        {
            _kernelType1List = new List<bool[,]>(8);

            // have one and only one neighbour * 8 
            bool[,] kernel1 = new bool[,] 
            {
                {false, false, true},
                {false, true, false},
                {false, false, false}
            };
            _kernelType1List.Add(kernel1);

            bool[,] kernel2 = new bool[,]
            {
                {false, false, false},
                {false, true, true},
                {false, false, false}
            };
            _kernelType1List.Add(kernel2);

            bool[,] kernel3 = new bool[,]
            {
                {false, false, false},
                {false, true, false},
                {false, false, true}
            };
            _kernelType1List.Add(kernel3);

            bool[,] kernel4 = new bool[,]
            {
                {false, false, false},
                {false, true, false},
                {false, true, false}
            };
            _kernelType1List.Add(kernel4);

            bool[,] kernel5 = new bool[,]
            {
                {false, false, false},
                {false, true, false},
                {true, false, false}
            };
            _kernelType1List.Add(kernel5);

            bool[,] kernel6 = new bool[,]
            {
                {false, false, false},
                {true, true, false},
                {false, false, false}
            };
            _kernelType1List.Add(kernel6);

            bool[,] kernel7 = new bool[,]
            {
                {true, false, false},
                {false, true, false},
                {false, false, false}
            };
            _kernelType1List.Add(kernel7);

            bool[,] kernel8 = new bool[,]
            {
                {false, true, false},
                {false, true, false},
                {false, false, false}
            };
            _kernelType1List.Add(kernel8);

            _kernelType2List = new List<bool[,]>(8);
            // L shape ends, * 8
            bool[,] kernel9 = new bool[,] 
            {
                {false, false, true},
                {false, true, true},
                {false, false, false}
            };
            _kernelType2List.Add(kernel9);

            bool[,] kernel10 = new bool[,]
            {
                {false, false, false},
                {false, true, true},
                {false, false, true}
            };
            _kernelType2List.Add(kernel10);

            bool[,] kernel11 = new bool[,]
            {
                {false, false, false},
                {false, true, false},
                {false, true, true}
            };
            _kernelType2List.Add(kernel11);

            bool[,] kernel12 = new bool[,]
            {
                {false, false, false},
                {false, true, false},
                {true, true, false}
            };
            _kernelType2List.Add(kernel12);

            bool[,] kernel13 = new bool[,]
            {
                {false, false, false},
                {true, true, false},
                {true, false, false}
            };
            _kernelType2List.Add(kernel13);

            bool[,] kernel14 = new bool[,]
            {
                {true, false, false},
                {true, true, false},
                {false, false, false}
            };
            _kernelType2List.Add(kernel14);

            bool[,] kernel15 = new bool[,]
            {
                {true, true, false},
                {false, true, false},
                {false, false, false}
            };
            _kernelType2List.Add(kernel15);

            bool[,] kernel16 = new bool[,]
            {
                {false, true, true},
                {false, true, false},
                {false, false, false}
            };
            _kernelType2List.Add(kernel16);

            _kernelType3List = new List<bool[,]>(4);
            // T shape ends, * 8
            bool[,] kernel17 = new bool[,] 
            {
                {true, true, true},
                {false, true, false},
                {false, false, false}
            };
            _kernelType3List.Add(kernel17);

            bool[,] kernel18 = new bool[,]
            {
                {false, false, true},
                {false, true, true},
                {false, false, true}
            };
            _kernelType3List.Add(kernel18);

            bool[,] kernel19 = new bool[,]
            {
                {false, false, false},
                {false, true, false},
                {true, true, true}
            };
            _kernelType3List.Add(kernel19);

            bool[,] kernel20 = new bool[,]
            {
                {true, false, false},
                {true, true, false},
                {true, false, false}
            };
            _kernelType3List.Add(kernel20);
        } // PrepareKernels()
        #endregion

        #region I/O method
        /// <summary>
        /// return a free end image
        /// free ends are rendered in red, overlapping the srcImage
        /// </summary>
        /// <param name="srcImage"></param>
        /// <returns></returns>
        public Bitmap FreeEndImage(Bitmap srcImage)
        {
            Bitmap dstImage = new Bitmap(srcImage);
            int freeEndCount = _freeEndList.Count;
            for (int i = 0; i < freeEndCount; i++)
            {
                Point p = (Point)_freeEndList[i];
                dstImage.SetPixel((int)p.X, (int)p.Y, Color.Red);
            }

            return dstImage;
        } // FreeEndImage()
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Team Leader
United Kingdom United Kingdom
Ping is the Director of Technology Development of AI Speech Ltd. His main interests includes artificial intellegent, speech technologies, image processing technologies, and software engineering methodologies.

Comments and Discussions