13,259,194 members (49,136 online)
alternative version

#### Stats

59.5K views
52 bookmarked
Posted 10 Jul 2010

# OCR Line Detection

 Rate this:
A simple algorithm for extracting lines in an image.

## Introduction

One of the first steps in developing OCR systems is line detection. Farsi/Arabic text has some properties which make them difficult to recognize. For example, there are characters in Farsi like "i" in English which has two parts but are recognized as one character. And I have covered this problem in the following code.

## Background

The reader is assumed to have basic GDI skills and knowledge of elementary concepts of image processing.

## Using the code

First of all, you should take it into account that this algorithm does not detect lines of characters covered vertically by a line like in the image below:

The algorithm is so easy:

• Threshold image
• Consider horizontal projection of line of character as a continuous vertical line
• Scan image from top to bottom and find the top and bottom of each vertical line from the previous phase
• Because characters like ? are identified as two lines, we merge those lines whose distance to the next line is a fraction of their height
• Save lines in the output directory

First, we should threshold the image. I used a trivial thresholding algorithm, but algorithms like the famous Otsu thresholding will result in a better image.

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

In the second step, we try to project all black cells horizontally to extract the horizontal projection of the image. This will result in a discontinuous collection of black points which we consider the top and bottom of each collection, as the top and bottom of the line:

```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)
{
y = FindBottomOfLine(mehrImage, y) + 1;
}
}

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 = RemoveNoisyData(lines);
return lines;
}```

To find the bottom and top of lines, I developed these two functions: `FindNextLine`, which finds the first black pixel of the next collection extracted from the horizontal projection, and `FindBottomOfLine`, which looks for the first white pixel with a Y dimension bigger than the top of the line.

```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;
}
}
}

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;
}```

Because characters like '?' are identified as two lines, we merge those lines whose distance to the next line is a constant fraction of their height:

```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;
}```

And ultimately, we save the images of the lines in the output directory.

## Experimental results

I tested this algorithm for different fonts and sizes, including Mitra, TimesNewRoman, Arial, and Zar. For those without any noise, it works 96% percent, but for noisy samples, based on the noise ratio, we get different results which are not acceptable.

## History

I have spent two years of my life developing an Open Source Farsi /Arabic OCR, and now I want to share some of my experiences here. If you are interested in developing Farsi/Arabic OCR, you can join the following group: farsi_arabic_OCR@groups.yahoo.com.

## Share

 Team Leader PDP 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 .

## You may also be interested in...

 First Prev Next
 OCR متن انتخاب شده Member 1303133319-Aug-17 5:06 Member 13031333 19-Aug-17 5:06
 Re: OCR متن انتخاب شده mehran ghainian hasaruye19-Nov-17 2:09 mehran ghainian hasaruye 19-Nov-17 2:09
 I want java android Nguyễn Thức31-May-17 0:49 Nguyễn Thức 31-May-17 0:49
 OCR Member 129327473-Jan-17 5:44 Member 12932747 3-Jan-17 5:44
 Re: OCR mehran ghainian hasaruye15-Mar-17 9:32 mehran ghainian hasaruye 15-Mar-17 9:32
 see the link i think u can help me Member 1142050417-Mar-15 13:42 Member 11420504 17-Mar-15 13:42
 Re: see the link i think u can help me mehran ghainian hasaruye11-Feb-16 3:08 mehran ghainian hasaruye 11-Feb-16 3:08
 OCR English,Arabic Fathi Hossam14-Nov-14 13:21 Fathi Hossam 14-Nov-14 13:21
 Re: OCR English,Arabic mehran ghainian hasaruye14-Nov-14 22:23 mehran ghainian hasaruye 14-Nov-14 22:23
 Re: OCR English,Arabic mehran ghainian hasaruye19-Nov-14 22:04 mehran ghainian hasaruye 19-Nov-14 22:04
 Arabic segmentation Ysef21-Oct-13 23:44 Ysef 21-Oct-13 23:44
 Re: Arabic segmentation mehran ghainian hasaruye13-Dec-13 1:46 mehran ghainian hasaruye 13-Dec-13 1:46
 LineDetection OCR Omar Elouafi14-Jun-13 6:37 Omar Elouafi 14-Jun-13 6:37
 Re: LineDetection OCR mehran ghainian hasaruye14-Jun-13 23:01 mehran ghainian hasaruye 14-Jun-13 23:01
 Re: LineDetection OCR Omar Elouafi10-Jul-13 3:02 Omar Elouafi 10-Jul-13 3:02
 new project (other open source ocr project) reza161514-Oct-12 15:56 reza1615 14-Oct-12 15:56
 Re: new project (other open source ocr project) mehran ghainian hasaruye7-Apr-14 9:24 mehran ghainian hasaruye 7-Apr-14 9:24
 آی.دی شما؟ Hamid Reza Niroomand29-Sep-12 10:50 Hamid Reza Niroomand 29-Sep-12 10:50
 Re: آی.دی شما؟ mehran ghainian hasaruye3-Oct-12 0:48 mehran ghainian hasaruye 3-Oct-12 0:48
 OCR programing7-Aug-12 20:15 programing 7-Aug-12 20:15
 Re: OCR mehran ghainian hasaruye29-Aug-12 19:48 mehran ghainian hasaruye 29-Aug-12 19:48
 Ocr line detection Raph Jojo3-Jul-12 7:24 Raph Jojo 3-Jul-12 7:24
 Re: Ocr line detection mehran ghainian hasaruye7-Apr-14 9:16 mehran ghainian hasaruye 7-Apr-14 9:16
 My vote of 5 manoj kumar choubey11-Apr-12 3:52 manoj kumar choubey 11-Apr-12 3:52
 Re: My vote of 5 mehran ghainian hasaruye7-Apr-14 9:18 mehran ghainian hasaruye 7-Apr-14 9:18
 help me Member 826846610-Nov-11 23:57 Member 8268466 10-Nov-11 23:57
 i need to do segmentation character..which is vertically..how to do it? i try change from yours but can't tq
 Re: help me mehran ghainian hasaruye12-Dec-11 19:42 mehran ghainian hasaruye 12-Dec-11 19:42
 thankful amir 216-Jul-11 2:11 amir 2 16-Jul-11 2:11
 Can not open the simple Member 46751956-Aug-10 13:27 Member 4675195 6-Aug-10 13:27
 Re: Can not open the simple mehran ghainian hasaruye8-Aug-10 7:06 mehran ghainian hasaruye 8-Aug-10 7:06
 Re: Can not open the simple Member 46751958-Aug-10 10:58 Member 4675195 8-Aug-10 10:58
 Re: Can not open the simple mehran ghainian hasaruye30-Aug-10 5:34 mehran ghainian hasaruye 30-Aug-10 5:34
 Very interesting Yves12-Jul-10 15:03 Yves 12-Jul-10 15:03
 Re: Very interesting mehran ghainian hasaruye14-Jul-10 2:54 mehran ghainian hasaruye 14-Jul-10 2:54
 My vote of 5 babakzawari12-Jul-10 2:49 babakzawari 12-Jul-10 2:49
 Re: My vote of 5 [modified] mehran ghainian hasaruye12-Jul-10 5:42 mehran ghainian hasaruye 12-Jul-10 5:42
 My vote of 1 Frank Heimes10-Jul-10 6:02 Frank Heimes 10-Jul-10 6:02
 Not very useful Frank Heimes10-Jul-10 6:02 Frank Heimes 10-Jul-10 6:02
 Re: Not very useful mehran ghainian hasaruye10-Jul-10 10:47 mehran ghainian hasaruye 10-Jul-10 10:47
 A lotta code Dave Kreskowiak9-Jul-10 19:24 Dave Kreskowiak 9-Jul-10 19:24
 Last Visit: 31-Dec-99 19:00     Last Update: 24-Nov-17 3:44 Refresh 1