Click here to Skip to main content
16,015,218 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more: , +
Hi guys I'm very new to this image processing concept. I was trying to do a sample project how to recognize malayan characters in an image. Im stuck in line and character segmentation. If some one can help me this sample code would be greate.


Thanks again,
Ganesh Ramasamy
Posted

1 solution

I assume you doing an OCR related project. There are so many different ways to do the image segmentation. In image segmentation fist you need to identify the upper and lower boundary of the image. Here is the code for the Line segmentation. you can optimize this further.....

histogramCreation histo = new histogramCreation();
        getSpecificArea getSpecific = new getSpecificArea();

        private Bitmap inputImage = null;
        List<int> hHisto = new List<int>();
        List<int> vHisto = new List<int>();

        internal histogramCreation histogramCreation
        {
            get
            {
                throw new System.NotImplementedException();
            }
            set
            {
            }
        }

        public List<bitmap> lineDetection(Bitmap image)
        {
            
            Bitmap Image = (Bitmap)image.Clone ();

            setImage(Image);
            hHisto = histo.horizontalProjection(inputImage);
            vHisto = histo.verticalProjection (inputImage);

            removeVLines();
            removeHLines();

            hHisto = histo.horizontalProjection(inputImage);
            vHisto = histo.verticalProjection(inputImage);
            int y = 0;

            bool lineDetect = true;

            List<int> lineTop = new List <int>();
            List<int> lineBot = new List<int>();

            List<bitmap> lineCapture = new List<bitmap>();

            while (lineDetect)
            {
                y = findNextLine(hHisto,y);

                if (y == -1) break;

                if (y >= hHisto.Count)
                {
                    lineDetect = false;
                }
                if (lineDetect)
                {
                    if (lineTop.Count >= hHisto.Count)
                    {
                        break;
                    }
                    lineTop.Add(y);                  
                    y = findBottomOfLine(hHisto, y);
                    lineBot.Add(y);

                    bool flag = false;
                    for (int j = y; j < hHisto.Count; j++)
                    {

                        if (hHisto[j] > 0)
                        {
                            flag = true;
                        }
                    }
                    if (flag == false)
                    {
                        y = hHisto.Count;
                    }

                    if (y == hHisto.Count - 1)
                    {
                        break;
                    }                    
                }
            }

            for (int lineCount = 0; lineCount < lineTop.Count; lineCount++)
            {
                int height = lineBot[lineCount] - lineTop[lineCount];
                if (height >2 )
                {
                    Bitmap newLine = new Bitmap(inputImage.Width, height);
                    //getSpecific.FillImage(newLine, Brushes.Black);
                    newLine = getSpecific.GetSpecificAreaOfImage(new Rectangle(0, lineTop[lineCount], inputImage.Width, height), inputImage);
                    Bitmap cropLines = new Bitmap(newLine);
                    if (cropLines.Height > 12)
                    {
                        lineCapture.Add(cropLines);
                    }
                }                
            }
            if (lineCapture.Count == 0)
            {
                lineCapture.Add(image);
            }
            inputImage.Dispose();
            return lineCapture;
        }


        private void removeHLines()
        {
            Bitmap tempImage = (Bitmap)inputImage.Clone();
            for (int i = 0; i < hHisto.Count; i++)
            {
                if (hHisto[i] >= (tempImage.Width - 10))
                {
                    for (int j = 0; j < tempImage.Width; j++)
                    {
                        tempImage.SetPixel(j, i, Color.White);
                    }
                }
            }
            inputImage = tempImage;
        }
        private void removeVLines()
        {
            Bitmap tempImage = (Bitmap)inputImage.Clone();
            for (int i = 0; i < vHisto.Count; i++)
            {

                if (vHisto[i] >= (tempImage.Height - 10) || vHisto[i + 2] == 0)
                {
                    for (int j = 0; j < tempImage.Height; j++)
                    {
                        tempImage.SetPixel(i, j, Color.White);
                    }
                }
                if (i + 3 >= vHisto.Count)
                {
                    break;
                }
            }
            inputImage = tempImage;
        }

        private void setImage(Bitmap image)
        {
            this.inputImage = image;
        }

        private int findNextLine(List<int> histo, int start)
        {
            if (start > histo.Count)
            {
                return -1;
            }
            for (int i = start; i < histo.Count;i++)
            {
                if (histo[i] > 0)
                {
                    start = i;
                    break;
                }
            }
            return start < histo.Count ? start : -1;       
        }

        private int findBottomOfLine(List<int> histo, int end)
        {
            for (int i = end; i < histo.Count; i++)
            {
                if (histo[i] == 0)
                {
                    end = i;
                    break;
                }
                else if (i == hHisto.Count-1)
                {
                    end = i;
                }
            }
            return end < histo.Count ? end : -1;       
        }
    }


In the above code snippet i used the histogram (projection profiling) to do the segmentation. Hope you know how to do the histogram creation, if not this is how to do histogram creation.

private pixelCheck pixelCheck = new pixelCheck();
        
        List<int> hHisto = new List<int>();
        List<int> vHisto = new List<int>();

        internal pixelCheck pixelCheck1
        {
            get
            {
                throw new System.NotImplementedException();
            }
            set
            {
            }
        }

        public List<int> horizontalProjection(Bitmap image)
        {
            hHisto.Clear();
            for (int i = 0; i < image.Height; i++)
            {
                int val = 0;
                for (int j = 0; j < image.Width; j++)
                {
                    Color color = image.GetPixel(j, i);
                    int pixelValue = (int)(color.R + color.G + color.B) / 3;
                    val += (pixelCheck.getpixelCheck(pixelValue));
                }
                hHisto.Add(val);
            }
            return hHisto;
        }

        public List<int> verticalProjection(Bitmap image)
        {
            vHisto.Clear();
            for (int i = 0; i < image.Width; i++)
            {
                int val = 0;
                for (int j = 0; j < image.Height; j++)
                {
                    Color color = image.GetPixel(i, j);
                    int pixelValue = (int)(color.R + color.G + color.B) / 3;
                    val += (pixelCheck.getpixelCheck(pixelValue));
                }
                vHisto.Add(val);
            }
            return vHisto;
        }


you can archive character segmentation if following manner...
private histogramCreation histo = new histogramCreation();
        private getSpecificArea getSpecific = new getSpecificArea();
        private NoiceRemoval2 noise = new NoiceRemoval2();

        private Bitmap inputImage = null;

        private recognize recognize1 = new recognize();

        private List<int> vHisto = new List<int>();
        private List<int> hHisto = new List<int>();
        private string value = "";

        internal histogramCreation histogramCreation
        {
            get
            {
                throw new System.NotImplementedException();
            }
            set
            {
            }
        }

        public List<bitmap> charactorSegmentImage(Bitmap image)
        {
            vHisto.Clear();
            hHisto.Clear();
            string value = null;

            setImage(image);

            vHisto = histo.verticalProjection(inputImage);
            hHisto = histo.horizontalProjection(inputImage);

            int x = 0;

            bool charactorDetect = true;

            List<int> start = new List<int>();
            List<int> end = new List<int>();

            List<bitmap> charactorCapture = new List<bitmap>();
            List<bitmap> finalCharacters = new List<bitmap>();

            List<string> wordsDetected = new List<string>();
            List<string> sectionDetected = new List<string>();

            int charactorCount = 0;

            while (charactorDetect)
            {
                if (x >= vHisto.Count)
                {
                    break;
                }
                x = findNextCharactor(vHisto, x);

                if (x >= vHisto.Count)
                {
                    charactorDetect = false;
                }

                if (charactorDetect)
                {
                    if (start.Count >= vHisto.Count)
                    {
                        break;
                    }
                    start.Add(x);
                    x = findnextWord(vHisto, x);
                    end.Add(x);

                    if (start[start.Count - 1] == end[end.Count - 1])
                    {
                        charactorDetect = false;
                    }

                    if (start.Count > 2)
                    {
                        if (start[start.Count - 1] == start[start.Count - 2])
                        {
                            start.Remove(start.Count - 1);
                        }
                    }

                    if (end.Count > 2)
                    {
                        if (end[end.Count - 1] == end[end.Count - 2])
                        {
                            end.Remove(end.Count - 1);
                        }
                    }
                }
            }

            for (charactorCount = 0; charactorCount < start.Count; charactorCount++)
            {
                int width = end[charactorCount] - start[charactorCount];
                if (width >= 2 && inputImage.Height > 10)
                {
                    Bitmap newCharactor = new Bitmap(width, inputImage.Height);
                   // getSpecific.FillImage(newCharactor, Brushes.Black);
                    newCharactor = getSpecific.GetSpecificAreaOfImage(new Rectangle(start[charactorCount], 0, width, inputImage.Height), inputImage);
                    Bitmap cropCharactors = new Bitmap(newCharactor);
                    cropCharactors = removeInvalidChar(cropCharactors);
                    if (cropCharactors != null)
                    {
                        charactorCapture.Add(cropCharactors);
                    }
                    for (int i = 0; i < charactorCapture.Count; i++)
                    {
                        string val = recognize1.characterRecognition(charactorCapture[i]);
                        value += (val);
                    }
                }
                if (end.Count - 1 == charactorCount && charactorCapture != null)
                {
                    for (int i = 0; i < charactorCapture.Count; i++)
                    {
                        {
                            string val = recognize1.characterRecognition(charactorCapture[i]);
                            value += (val);
                        }
                        wordsDetected.Add(value);
                    }
                }
            }
            return charactorCapture;
        }

        private void setImage(Bitmap image)
        {
            this.inputImage = image;
        }

        private int findNextCharactor(List<int> vHisto, int x)
        {

            if (x > vHisto.Count)
            {
                return -1;
            }
            for (int i = x; i < vHisto.Count; i++)
            {
                if (vHisto[i] > 0 && vHisto[i + 1] > 0)
                {
                    x = i + 1;
                    break;
                }
            }
            return x < vHisto.Count ? x : -1;
        }

        private int findnextWord(List<int> vHisto, int x)
        {
            for (int i = x; i < vHisto.Count; i++)
            {
                
                if (vHisto[i] == 0 && vHisto [i+1]==0)
                {
                    x = i;
                    break;
                }
                else
                {
                    if (vHisto[(vHisto.Count) - 1] != 0)
                    {
                        x = vHisto.Count;
                    }
                }
                if (i + 2 == vHisto.Count)
                {
                    break;
                }
            }
            return x <= vHisto.Count ? x : -1;
        }

        private Bitmap removeWhiteSpaces(Bitmap img)
        {
            Bitmap tempImg = img;
            Bitmap recImg = (Bitmap)tempImg.Clone();
            List<int> tempHiso = histo.horizontalProjection(img);

            List<int> start = new List<int>();
            for (int i = 0; i < tempHiso.Count; i++)
            {
                if (tempHiso[i] > 0)
                {
                    start.Add(i);
                }
            }
            int height = start[start.Count - 1] - start[0];
            int width = img.Width;

            if (start[0] + height > img.Height)
                height = img.Height - start[0];

            Rectangle rect = new Rectangle(0, start[0], img.Width, height + 1);
            return img = (Bitmap)recImg.Clone(rect, recImg.PixelFormat);
        }

        private Bitmap removeInvalidChar(Bitmap image)
        {
            int count = 0;
            List<int> charHist = new List<int>();
            Bitmap img = null;
            if (image.Height <= 15 || image.Width < 3)
            {
                charHist = histo.horizontalProjection(image);
                for (int d = 0; d < charHist.Count; d++)
                {
                    if (charHist[d] > 0)
                    {
                        count++;
                    }
                }
                if (count >= 12)
                {
                    img = removeWhiteSpaces(image);
                }
            }
            else
            {
                img = removeWhiteSpaces(image);
            }

            return img;
        }


This is the GetSpecificArea code snipet

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

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

            grPhoto.DrawImage(duplicate, new Rectangle(0, 0, areaFromSourceImage.Width,
            areaFromSourceImage.Height), areaFromSourceImage, GraphicsUnit.Pixel);
            grPhoto.Dispose();
            return Picture;
        }


As you can see in the above code snippet i have used a method call GetSpecificAreaOfImage. This method does is giving you an area in an image as a Bitmap.

Hope this help you in your future work....
if you have any question feel free to ask.

Steve Roziro
 
Share this answer
 
v4
Comments
alsaidi52 16-Jul-12 22:42pm    
Can I find this code in Matlab to make character segmentation?
Member 10407815 8-Dec-13 14:33pm    
i have try this in vb, but its seem doesn't work correctly....

it can't cropped a single character i have input, may i do wrong??
[no name] 21-Sep-12 0:41am    
@steve Roziro - Can u please upload a sample project of above code?
Member 10407815 8-Dec-13 14:39pm    
there i need to know what inside of function PixelCheck(), Recognize(), and function InlineAssignHelper()....tank you, i need the solution...
Member 3789365 17-Jul-14 10:04am    
Hi, can you please let me know how these objects are being declared ???
histogramCreation histo = new histogramCreation();
getSpecificArea getSpecific = new getSpecificArea();

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900