Freeman chain codes
OCR
digital image processing
shape representation
computer vision

Understanding Freeman chain codes for OCR

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Freeman chain codes are a compact way to describe the outline of a binary shape by storing the direction taken at each boundary step. In OCR, that matters because a character's contour carries useful structural information even before you apply more advanced classification methods.

What a Freeman Chain Code Describes

Imagine tracing the edge of a character one boundary pixel at a time. Instead of storing every coordinate, you store only the movement direction from one contour point to the next.

In the common 8-direction version, the code values are:

  • '0 for right'
  • '1 for up-right'
  • '2 for up'
  • '3 for up-left'
  • '4 for left'
  • '5 for down-left'
  • '6 for down'
  • '7 for down-right'

So a boundary walk can be represented as a short sequence such as 0, 0, 2, 2, 4, 6 instead of a long list of pixel coordinates.

Why OCR Pipelines Use Chain Codes

Classic OCR systems often need features that capture shape, not just raw pixel intensity. A chain code helps because it records how the contour turns and how strokes move around the boundary.

That can help distinguish characters that occupy similar bounding boxes but have different outlines. For example:

  • 'C and O are both rounded, but one contour stays open and the other closes'
  • 'L and T have very different direction-change patterns'
  • '6 and 8 may share overall size but differ in contour loops and turning behavior'

Chain codes are not a complete OCR system by themselves, but they are a useful contour feature in classical vision pipelines.

Build a Chain Code From Ordered Boundary Points

Suppose contour extraction has already given you the boundary points in order. The following Python example converts those points into an 8-direction Freeman chain code.

python
1DIRECTION_MAP = {
2    (1, 0): 0,
3    (1, -1): 1,
4    (0, -1): 2,
5    (-1, -1): 3,
6    (-1, 0): 4,
7    (-1, 1): 5,
8    (0, 1): 6,
9    (1, 1): 7,
10}
11
12def freeman_chain_code(points):
13    code = []
14
15    for i in range(1, len(points)):
16        x1, y1 = points[i - 1]
17        x2, y2 = points[i]
18        step = (x2 - x1, y2 - y1)
19        code.append(DIRECTION_MAP[step])
20
21    return code
22
23contour = [(1, 1), (2, 1), (3, 1), (3, 0), (3, -1)]
24print(freeman_chain_code(contour))

This produces the directional sequence that describes the contour path.

Raw Codes Need Normalization

A raw chain code depends on where the contour walk starts and on the image orientation. That means the same character can produce different raw sequences if tracing begins at a different point.

One common improvement is a differential chain code. Instead of storing absolute directions, you store the change in direction between successive steps. That makes the feature less sensitive to the arbitrary starting point of the contour traversal.

Another important step is preprocessing:

  • binarization
  • noise removal
  • connected-component extraction
  • boundary ordering

If the contour is noisy or unordered, the chain code becomes unstable and much less useful for OCR.

4-Direction Versus 8-Direction Coding

Some systems use 4-connectivity, where only up, down, left, and right are allowed. Others use 8-connectivity, which also includes diagonal moves.

The 8-direction version is more expressive for handwritten and curved shapes because it captures diagonal contour motion directly. The 4-direction version is simpler, but it may produce a less natural representation for slanted strokes.

Choosing between them depends on:

  • the contour extraction method
  • the character style
  • the rest of the feature pipeline

Common Pitfalls

  • Generating contour points out of order, which makes the resulting code meaningless.
  • Using raw chain codes without accounting for different starting points.
  • Forgetting whether the implementation assumes 4-connectivity or 8-connectivity.
  • Feeding noisy boundaries into the feature extractor and expecting stable codes.
  • Treating chain codes as a full OCR solution instead of one feature among several.

Summary

  • Freeman chain codes represent a contour as a sequence of directional steps.
  • In OCR, they help describe boundary shape in a compact form.
  • The code is useful only if the contour points are ordered and reasonably clean.
  • Differential coding and normalization make chain-code features more robust.
  • Chain codes work best as part of a larger OCR pipeline, not as the entire recognizer.

Course illustration
Course illustration

All Rights Reserved.