Click here to Skip to main content
15,895,011 members
Articles / Multimedia / GDI+

OCR Line Detection

Rate me:
Please Sign up or sign in to vote.
4.86/5 (22 votes)
10 Jul 2010CPOL2 min read 106.6K   7.3K   54  
A simple algorithm for extracting lines in an image.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AForge.Imaging.Filters;
using Emgu.CV;
using Emgu.CV.Structure;
using System.IO;

namespace LineDetection
{
    public partial class LineDetection : Form
    {
        public LineDetection()
        {
            InitializeComponent();
        }

        private void SelectImage_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                SaveLinesInDestinationFolder(openFileDialog1.FileName);
            }

            MessageBox.Show("Line Detection finished successfully find lines images in output directory");

        }

        private void SaveLinesInDestinationFolder(string name)
        {
            Bitmap image = (Bitmap)Bitmap.FromFile(name);
            image = Threshold(image, 128);
            List<Belt> result = ExtractBeltsBasedonCoveredHeight(image);
            int index = 0;
            if (!Directory.Exists(outputDirectory.Text))
                Directory.CreateDirectory(outputDirectory.Text);
            foreach (Belt belt in result)
            {
                belt.Save(outputDirectory.Text.Trim('\\') + "\\" + index++ + ".bmp");
            }
        }

        public List<Belt> ExtractBeltsBasedonCoveredHeight(Bitmap mehrImage)
        {


            int y = 0;
            int x = 0;

            bool line_present = true;

            List<int> line_top = new List<int>(1000);
            List<int> line_bottom = new List<int>(1000);

            List<Belt> lines = new List<Belt>();



            while (line_present)
            {
                x = 0;
                y = FindNextLine(mehrImage, y, ref x) ;
                if (y == -1)
                    break;
                if (y >= mehrImage.Height)
                {
                    line_present = false;
                }
                if (line_present)
                {

                    line_top.Add(y);

                    y = FindBottomOfLine(mehrImage, y) + 1;
                    mehrImage.Save(@"d:\1.bmp");
                    line_bottom.Add(y);

                }
            }



            for (int line_number = 0; line_number < line_top.Count; line_number++)
            {

                int height = line_bottom[line_number] - line_top[line_number] + 1;
                Bitmap bmp = new Bitmap(mehrImage.Width, height + 2);
                FillImage(bmp, Brushes.White);
                bmp = GetSpecificAreaOfImage(
                    new Rectangle(0, line_top[line_number] - 1, mehrImage.Width, height + 2), mehrImage);
                Belt belt = new Belt(bmp);


                belt.RelativeTop = line_top[line_number];
                belt.RelativeBottom = line_bottom[line_number];

                lines.Add(belt);


            }


            lines = RemoveNoisyData(lines);


            return lines;
        }

        private Bitmap FillImage(Bitmap image, Brush brush)
        {
            Graphics g = Graphics.FromImage(image);
            g.FillRectangle(brush, new Rectangle(0, 0, image.Width, image.Height));
            return image;
        }

        public Bitmap GetSpecificAreaOfImage(Rectangle rectangleWhichYouWantFromSourceImage, Bitmap duplicate)
        {
            Bitmap Picture = new Bitmap(rectangleWhichYouWantFromSourceImage.Width, rectangleWhichYouWantFromSourceImage.Height);
            Graphics grPhoto = Graphics.FromImage(Picture);

            grPhoto.DrawImage(duplicate, new Rectangle(0, 0, rectangleWhichYouWantFromSourceImage.Width,
                rectangleWhichYouWantFromSourceImage.Height), rectangleWhichYouWantFromSourceImage, GraphicsUnit.Pixel);

            return Picture;
        }

        public int FindBottomOfLine(Bitmap bitmap, int topOfLine)
        {
            int x;
            bool no_black_pixel;
            no_black_pixel = false;
            while (no_black_pixel == false)
            {
                topOfLine++;
                no_black_pixel = true;
                for (x = 0; x < bitmap.Width && topOfLine < bitmap.Height; x++)
                {
                    if ((Convert.ToString(bitmap.GetPixel(x, topOfLine)) == Shape.BlackPixel))
                        no_black_pixel = false;
                }
            }
            return topOfLine - 1;
        }

        public int FindNextLine(Bitmap bitmap, int y, ref int x)
        {
            if (y >= bitmap.Height)
                return -1;
            while (Convert.ToString(bitmap.GetPixel(x, y)) == Shape.WhitePixel)
            {
                x++;
                if (x == bitmap.Width)
                {
                    x = 0;
                    y++;
                }
                if (y >= bitmap.Height)
                {
                    break;
                }
            }
            return y < bitmap.Height ? y : -1;
        }

        private static List<Belt> RemoveNoisyData(List<Belt> belts)
        {

            if (!Directory.Exists("temp"))
            {
                Directory.CreateDirectory("temp");
            }
            else
            {
                foreach (string file in Directory.GetFiles("temp"))
                {
                    try
                    {
                        //File.Delete(file);
                    }
                    catch
                    { }
                }
            }
            for (int i = 1; i < belts.Count; i++)
            {

                if (belts[i].RelativeTop - belts[i - 1].BaseHorizontalLine - belts[i - 1].RelativeTop <
                    Belt.UpAndDownWhiteSpaceRatio * belts[i].Height)
                {

                    Image<Gray, Byte> img1 = new Image<Gray, byte>(belts[i].Image);
                    Image<Gray, Byte> img2 = new Image<Gray, byte>(belts[i - 1].Image);


                    Image<Gray, Byte> img3 = img2.ConcateVertical(img1);


                    string path = @".\temp\" + System.Guid.NewGuid().ToString();
                    img3.Save(path);
                    belts[i - 1].Image = (Bitmap)Bitmap.FromFile(path);
                    belts[i - 1].RelativeBottom = belts[i].RelativeBottom;
                    belts[i - 1].BaseHorizontalLine = -1;
                    belts.RemoveAt(i);
                }
            }
            return belts;
        }	 
 

        public Bitmap Threshold(Bitmap bitmap, int thresholdValue)
        {
            byte thrByte = (byte)(thresholdValue);
            bitmap = ApplyFilter(new Threshold(thrByte), bitmap);
            bitmap = GetIndexedPixelFormat(bitmap);
            return bitmap;

        }

        public Bitmap ApplyFilter(IFilter filter, Bitmap bitmap)
        {
            if (bitmap == null)
                return null;
            try
            {
                Bitmap newImage = filter.Apply(bitmap);
                return newImage;
            }
            catch (ArgumentException)
            {
            }
            finally
            {
                // restore cursor
            }
            return null;
        }

        public Bitmap GetIndexedPixelFormat(Bitmap bitmap)
        {
            if (bitmap == null)
                return null;
            Bitmap tmp = new Bitmap(bitmap.Width, bitmap.Height);
            Graphics grPhoto = Graphics.FromImage(tmp);
            Rectangle rect = new Rectangle(0, 0, tmp.Width, tmp.Height);
            grPhoto.DrawImage(bitmap, rect, 0, 0, bitmap.Width, bitmap.Height, GraphicsUnit.Pixel);
            return tmp;
        }
    }
}

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader PDP
Iran (Islamic Republic of) Iran (Islamic Republic of)
Hands-on .Net developer with 8 years of working experience, as C# developer, software designer, Test developer and architect including 3 years of part time and project based and near 5 years of full time job, contributing to and leading all phases of the software development life cycle (SDLC) for a wide variety of enterprise systems and Web-based applications, particularly within the Automation / Data mining /Insurance sectors. Highly skilled in application design, architecture and development with strong expertise in server side programming as well as in the complete range of .net technologies.

I have got the rank 301 among 500,000 in math & physics university entrance exam of IRAN in 2003 and I was member of national elites of IRAN for one year ,I got my BS Of Information Technology from Tehran University in 2009. now I am in spending the last semester of my Master degree in the field of Software engineering at Shahid Beheshti University .

Comments and Discussions