"Contour Analysis for Image Recognition in C#"


Today's project is one that is both a "Wow, so that how something like that works" and an "ouch, the math is hurting my brain" kind of project. The depth this article goes into is pretty cool and if you stick with it, you'll come away with a much greater understanding... and some code too. :)

Contour Analysis for Image Recognition in C#

The theory of contour analysis and its practical application to image recognition and OCR

The article describes the theoretical bases of the contour analysis and aspects of its practical application for image recognition. The article also includes library for operation with the contour analysis, and a demo-example.

The first part of the article contains the main definitions and theorems of the contour analysis. I tried to select the principal moments which allow to understand quickly enough an essence of the contour analysis, and to begin its application in practice. Also, I added something from myself. In the core, it concerns some aspects of the theory, and also problems of optimization of algorithms of the contour analysis. The second part of the article is devoted to it. In the same place results of work of algorithms are brought, problems and deficiencies of the given method are described.

The third part describes C# library ContourAnalysis.


Part 1: Bases of the Contour Analysis

What is Necessary for the Contour Analysis (CA)

The CA allows to describe, store, compare and find the objects presented in the form of the exterior outlines - contours.

It is supposed that the contour contains the necessary information on the object shape. Interior points of the object are not accepted to attention. It restricts area of applicability of algorithms of a CA, but reviewing only contours allows to pass from two-dimensional space of the image - to space of contours and by that to lower computing and algorithmic complexity.

CA allows to effectively solve the main problems of a pattern recognition - transposition, turn and a rescaling of the image of object. CA methods are invariant to these transformations.

The Main Concepts

At first, we define such an object contour. The contour is a boundary of object, a population of points (pixels), separating object from a background.

In systems of computer vision, some formats of coding of a contour are used - the code of Freeman, two-dimensional coding, polygonal coding are most known. But all these formats of coding are not used in a CA.

Instead, in a CA the contour is encoded by the sequence consisting of complex numbers. On a contour, the point which is called as starting point is fixed. Then, the contour is scanned (is admissible - clockwise), and each vector of offset is noted by a complex number a+ib. Where a - point offset on x axis, and b - offset on y axis. Offset is noted concerning the previous point.


Part 2: Practical Application of the Contour Analysis

The General Algorithm of Recognition

So, we will solve the pattern recognition task on the image.

The general sequence of an operation at recognition looks so:

  1. Preliminary handling of the image - smoothing, a filtration of noise, a contrast raise
  2. Binarization of the image and selection of contours of objects
  3. Initial filtration of contours on perimeter, squares, to a crest factor, fractality and so on
  4. Coercion of contours to uniform length, smoothing
  5. Search of all discovered contours, searching of the template maximum similar to the given contour

We will not consider points 1 and 3, they are specific to application area, and have the small relation to a CA.

Further we consider an algorithm body - searching and comparing of contours with templates. And then - we stop on binarization, coercion to uniform length and smoothing of contours a little.


Part 3: ContourAnalysis Library

The library includes two projects. The first project ContourAnalysis - implements base functions of the contour analysis - creation of contours, a scalar product of contours, equalization, evaluation ICF and ACF, comparing and searching of templates.

The class Contour - creates and stores contours. It contains basic operations for contours - scalar product, scaling, equalization, normalization, a spectrum evaluation, evaluation ACF and ICF.

The class Template is used for creation of base of templates. This class stores a contour, it ACF, descriptors ACF, the linear parameters of an initial contour (area), norm of a contour. Also, the template has a name which is used as the recognized value.

Class TemplateFinder implements fast searching of a template for the given contour. Outcome of operation of this class is FoundTemplateDesc which contains an initial contour, and the template discovered for the given contour. Besides, FoundTemplateDesc contains similarity rate, angle of rotation and a scale of a contour, relative to a template.

The second project - ContourAnalysisProcessing - contains methods for preliminary handling of the image, selection of contours, their filtrations and a recognition. Also, it contains tools for automatic generation of templates for recognition of printing symbols.

Project ContourAnalysisProcessing uses library OpenCV (EmguCV .NET wrapper) for operation with the image.

The class ImageProcessor is used for image handling. It, also, stores base of templates.

Method ImageProcessor.ProcessImage() receives the image on an input. Outcome of operation are lists discovered contours (ImageProcessor.samples) and the list of the recognized contours (ImageProcessor.foundTemplates).

The class ImageProcessor contains also settings for searching of contours.


Here's a snap of the app running. Yeah, that's doing the image processing in real time, using my built-in web cam. How cool is that?

What I find amazing is how little, relatively, there is. You'd think there'd be tons of files, etc?

private void ProcessFrame()
         if (captureFromCam)
             frame = _capture.QueryFrame();
             ibMain.Image = processor.binarizedFrame;
             ibMain.Image = frame;
     catch (Exception ex)

public void ProcessImage(Image<Gray, byte> grayFrame)
     if (equalizeHist)
     Image<Gray, byte> smoothedGrayFrame = grayFrame.PyrDown();
     smoothedGrayFrame = smoothedGrayFrame.PyrUp();
     Image<Gray, byte> cannyFrame = null;
     if (noiseFilter)
         cannyFrame = smoothedGrayFrame.Canny(new Gray(cannyThreshold), new Gray(cannyThreshold));
     if (blur)
         grayFrame = smoothedGrayFrame;
     CvInvoke.cvAdaptiveThreshold(grayFrame, grayFrame, 255, Emgu.CV.CvEnum.ADAPTIVE_THRESHOLD_TYPE.CV_ADAPTIVE_THRESH_MEAN_C, Emgu.CV.CvEnum.THRESH.CV_THRESH_BINARY, adaptiveThresholdBlockSize + adaptiveThresholdBlockSize % 2 + 1, adaptiveThresholdParameter);
     if (addCanny)
     if (cannyFrame != null)
     this.binarizedFrame = grayFrame;

     //dilate canny contours for filtering
     if (cannyFrame != null)
         cannyFrame = cannyFrame.Dilate(3);

     //find contours
     var sourceContours = grayFrame.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_NONE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST);
     //filter contours
     contours = FilterContours(sourceContours, cannyFrame, grayFrame.Width, grayFrame.Height);
     //find templates
     lock (foundTemplates)

     lock (templates)
     Parallel.ForEach<Contour<Point>>(contours, (contour) =>
         var arr = contour.ToArray();
         Template sample = new Template(arr, contour.Area, samples.templateSize);
         lock (samples)

         if (!onlyFindContours)
             FoundTemplateDesc desc = finder.FindTemplate(templates, sample);

             if (desc != null)
                 lock (foundTemplates)
     FilterByIntersection(ref foundTemplates);

What excites me about this project is how it could be used with others... Think about a robot, with a Kinect, that could actually read signs as it traveled about? Or maybe using this in a WP7 app? Or... or... or...

The Discussion

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.