Find the bounds of a letter

Post your questions regarding programming in C# in here.
5 posts Page 1 of 1
Contributors
User avatar
MrAksel
C# Coder
C# Coder
Posts: 1758
Joined: Fri Mar 26, 2010 12:27 pm

Find the bounds of a letter
MrAksel
How could I find the bounds of the different letters in a pure black/white image?
Lets say I have this image below, the bounds for the letter L is X 101, Y 23, W 40, H 65. Image
How could I detect that in code?
I would love to have it in C#, but VB is just as good.
LMAOSHMSFOAIDMT
Laughing my a** of so hard my sombrero fell off and I dropped my taco lmao;


Over 30 projects with source code!
Please give reputation to helpful members!

Image
Image
User avatar
Axel
Coding God
Coding God
Posts: 1928
Joined: Sun Jun 27, 2010 9:15 pm

Re: Find the bounds of a letter
Axel
You mean of a string or an image ? for a string with a certain font you can try Graphics.Measurestring();
http://vagex.com/?ref=25000
User avatar
MrAksel
C# Coder
C# Coder
Posts: 1758
Joined: Fri Mar 26, 2010 12:27 pm

Re: Find the bounds of a letter
MrAksel
I know of that, but I only have the image, no info about font, font size, font style, nothing but the image. I have to find a way to find the rectangle for each letter. Thats all I need, because I have the character recognition ready, I just need to find the right rectangle to take the data from.
LMAOSHMSFOAIDMT
Laughing my a** of so hard my sombrero fell off and I dropped my taco lmao;


Over 30 projects with source code!
Please give reputation to helpful members!

Image
Image
User avatar
mandai
Coding God
Coding God
Posts: 2585
Joined: Mon Apr 26, 2010 6:51 pm

Re: Find the bounds of a letter
mandai
To find the top-left character's rectangle you just need to look for pixel conditions, and keep track of the minimum/maximum coordinate types.
The right of the last character can be used to continue the search.
This basic method will only work for text on one line like above (otherwise overlapping will occur).

In short this algorithm will do all the work:
Code: Select all
        private void btnTest_Click(object sender, EventArgs e)
        {
            Bitmap bmp = new Bitmap("example.png");
            Rectangle range = new Rectangle(0, 0, bmp.Width, bmp.Height);

            BitmapData bd = bmp.LockBits(range, ImageLockMode.ReadOnly, bmp.PixelFormat);

            int cLeft = -1;
            int cTop = bd.Height;
            int cRight = -1;
            int cBottom = -1;

            List<Rectangle> regions = new List<Rectangle>();
            //search from top to bottom, left to right
            //note characters such as " will be seen as 2 seperate regions
            for (int x = 0; x < bd.Width; x++)
            {
                for (int y = 0; y < bd.Height; y++)
                {
                    //Format32bppArgb uses a BGRA pixel structure
                    IntPtr offset = (IntPtr)(bd.Scan0.ToInt32() + (x * 4) + (y * bd.Stride));

                    byte b = Marshal.ReadByte(offset);
                    if (b > 0)//see if blue is greater than 0. example pixel condition
                    {

                        if (cLeft == -1)
                        {
                            cLeft = x;
                        }

                        if (cBottom < y)
                        {
                            cBottom = y;
                        }

                        if (cTop > y)
                        {
                            cTop = y;
                        }

                        if (cRight < x)
                        {
                            cRight = x;
                        }

                    }
                    else if ((x - cRight) > 1)
                    {
                        //if there is more than 1 X pixel after the last successful condition then it can continue

                        if (cBottom > -1)
                        {
                            int cWidth = (x - 1) - cLeft;
                            int cHeight = cBottom - cTop;

                            Rectangle rect = new Rectangle(cLeft, cTop, cWidth, cHeight);
                            regions.Add(rect);

                            cTop = bd.Height;
                            cBottom = -1;
                            cRight = -1;
                            cLeft = cRight;//start from this region's right
                        }

                    }

                }
            }

            bmp.UnlockBits(bd);

            MessageBox.Show(regions.Count + " regions found");
            Graphics gfx = Graphics.FromImage(bmp);
            for (int i = 0; i < regions.Count; i++)
            {
                gfx.DrawRectangle(Pens.Green, regions[i]);//draw a green rectangle around each letter
            }
            gfx.Dispose();
            pictureBox1.Image = bmp;
        }
I have attached a screenshot of the result.

Edit: Improved efficiency!
You do not have the required permissions to view the files attached to this post.
Last edited by mandai on Thu Feb 09, 2012 2:19 pm, edited 5 times in total.
User avatar
MrAksel
C# Coder
C# Coder
Posts: 1758
Joined: Fri Mar 26, 2010 12:27 pm

Re: Find the bounds of a letter
MrAksel
Thanks, thats just what i needed. I had something similar in mind yesterday
Code: Select all
        private Letter[] FindLetters(byte[] d, int Stride, int Width, int Height)
        {
            List<Letter> l = new List<Letter>();
            
            bool inLetter = false;
            Rectangle temp = new Rectangle(new Point(int.MaxValue, int.MaxValue), new Size(int.MinValue, int.MinValue));

            for (int y = 0; y < Height; y++)
            {
                for (int x = 0; x < Width; x++)
                {
                    if (d[y * Stride + x * 3] > 245)
                    {
                        inLetter = true;
                        temp.X = Math.Min(temp.X, x);
                        temp.Y = Math.Min(temp.Y, y);
                        temp.Width = Math.Max(temp.Width, x);
                        temp.Height = Math.Max(temp.Height, y);
                    }
                    else 
                    { 
                        inLetter = false; 
                        l.Add(new Letter { x = temp.X, y = temp.Y, w = temp.Width, h = temp.Height }); 
                    }
                }
            }

            return l.ToArray();
        }
But t knew it missed something
LMAOSHMSFOAIDMT
Laughing my a** of so hard my sombrero fell off and I dropped my taco lmao;


Over 30 projects with source code!
Please give reputation to helpful members!

Image
Image
5 posts Page 1 of 1
Return to “General coding help”