Saturday, November 16, 2024
Google search engine
HomeLanguagesChain Code for 2D Line

Chain Code for 2D Line

Chain code is a lossless compression technique used for representing an object in images. The co-ordinates of any continuous boundary of an object can be represented as a string of numbers where each number represents a particular direction in which the next point on the connected line is present. One point is taken as the reference/starting point and on plotting the points generated from the chain, the original figure can be re-drawn.

 
 

This article describes how to generate a 8-neighbourhood chain code of a 2-D straight line. In a rectangular grid, a point can have at most 8 surrounding points as shown below. The next point on the line has to be one of these 8 surrounding points. Each direction is assigned a code. Using this code we can find out which of the surrounding point should be plotted next.

 

8-Neighbourhood connected system

 

The chain codes could be generated by using conditional statements for each direction but it becomes very tedious to describe for systems having large number of directions(3-D grids can have up to 26 directions). Instead we use a hash function. The difference in X(dx           ) and Y(dy           ) co-ordinates of two successive points are calculated and hashed to generate the key for the chain code between the two points.

 

Chain code list: [5, 6, 7, 4, -1, 0, 3, 2, 1]

 

Hash function: C(dx, dy) = 3dy + dx + 4

 

Hash table:- 
 

 

dx dy C(dx, dy) chainCode[C]
1 0 5 0
1 1 8 1
0 1 7 2
-1 1 6 3
-1 0 3 4
-1 -1 0 5
0 -1 1 6
1 -1 2 7

The function does not generate the value 4 so a dummy value is stored there.

Examples: 
 

Input : (2, -3), (-4, 2)
Output : Chain code for the straight line from (2, -3) to (-4, 2) is 333433

Input : (-7, -4), (9, 3)
Output : Chain code for the straight line from (-7, -4) to (9, 3) is 0101010100101010

 

C++




// C++ code for generating 8-neighbourhood chain
// code for a 2-D line
#include <iostream>
#include <math.h>
#include <vector>
 
std::vector<int> codeList = { 5, 6, 7, 4, -1, 0, 3, 2, 1 };
 
// This function generates the chaincode
// for transition between two neighbour points
int getChainCode(int x1, int y1, int x2, int y2)
{
    int dx = x2 - x1;
    int dy = y2 - y1;
    int hashKey = 3 * dy + dx + 4;
    return codeList[hashKey];
}
 
// This function generates the list of
// chaincodes for given list of points
std::vector<int> generateChainCode(
    std::vector<std::vector<int> > ListOfPoints)
{
    std::vector<int> chainCode;
    for (int i = 0; i < ListOfPoints.size() - 1; i++) {
        std::vector<int> a = ListOfPoints[i];
        std::vector<int> b = ListOfPoints[i + 1];
        chainCode.push_back(
            getChainCode(a[0], a[1], b[0], b[1]));
    }
    return chainCode;
}
 
// This function generates the list of points for
// a straight line using Bresenham's Algorithm
std::vector<std::vector<int> > Bresenham2D(int x1, int y1,
                                           int x2, int y2)
{
    std::vector<std::vector<int> > ListOfPoints;
    ListOfPoints.push_back({ x1, y1 });
    int xdif = x2 - x1;
    int ydif = y2 - y1;
    int dx = abs(xdif);
    int dy = abs(ydif);
    int xs;
    if (xdif > 0) {
        xs = 1;
    }
    else {
        xs = -1;
    }
 
    int ys;
    if (ydif > 0) {
        ys = 1;
    }
    else {
        ys = -1;
    }
 
    if (dx > dy) {
        // Driving axis is the X-axis
        int p = 2 * dy - dx;
        while (x1 != x2) {
            x1 += xs;
            if (p >= 0) {
                y1 += ys;
                p -= 2 * dx;
            }
            p += 2 * dy;
            ListOfPoints.push_back({ x1, y1 });
        }
    }
    else {
        // Driving axis is the Y-axis
        int p = 2 * dx - dy;
        while (y1 != y2) {
            y1 += ys;
            if (p >= 0) {
                x1 += xs;
                p -= 2 * dy;
            }
            p += 2 * dx;
            ListOfPoints.push_back({ x1, y1 });
        }
    }
 
    return ListOfPoints;
}
 
void DriverFunction()
{
    int x1 = -9;
    int y1 = -3;
    int x2 = 10;
    int y2 = 1;
    std::vector<std::vector<int> > ListOfPoints
        = Bresenham2D(x1, y1, x2, y2);
    std::vector<int> chainCode
        = generateChainCode(ListOfPoints);
 
    std::string chainCodeString = "";
    for (int i = 0; i < chainCode.size(); i++) {
        chainCodeString += std::to_string(chainCode[i]);
    }
 
    std::cout << "Chain code for the straight line from ("
              << x1 << "," << y1 << ") to (" << x2 << ","
              << y2 << ") is " << chainCodeString
              << std::endl;
}
 
int main()
{
    DriverFunction();
    return 0;
}
 
// This code is contributed by ishankhndelwals.


Java




import java.util.ArrayList;
import java.util.List;
 
public class Main {
  static List<Integer> codeList
    = new ArrayList<Integer>();
  static
  {
    codeList.add(5);
    codeList.add(6);
    codeList.add(7);
    codeList.add(4);
    codeList.add(-1);
    codeList.add(0);
    codeList.add(3);
    codeList.add(2);
    codeList.add(1);
  }
 
  // This function generates the chaincode
  // for transition between two neighbour points
  static int getChainCode(int x1, int y1, int x2, int y2)
  {
    int dx = x2 - x1;
    int dy = y2 - y1;
    int hashKey = 3 * dy + dx + 4;
    return codeList.get(hashKey);
  }
 
  // This function generates the list of
  // chaincodes for given list of points
  static List<Integer>
    generateChainCode(List<List<Integer> > ListOfPoints)
  {
    List<Integer> chainCode = new ArrayList<Integer>();
    for (int i = 0; i < ListOfPoints.size() - 1; i++) {
      List<Integer> a = ListOfPoints.get(i);
      List<Integer> b = ListOfPoints.get(i + 1);
      chainCode.add(getChainCode(a.get(0), a.get(1),
                                 b.get(0), b.get(1)));
    }
    return chainCode;
  }
 
  // This function generates the list of points for
  // a straight line using Bresenham's Algorithm
  static List<List<Integer> > Bresenham2D(int x1, int y1,
                                          int x2, int y2)
  {
    List<List<Integer> > ListOfPoints
      = new ArrayList<List<Integer> >();
    ListOfPoints.add(List.of(x1, y1));
    int xdif = x2 - x1;
    int ydif = y2 - y1;
    int dx = Math.abs(xdif);
    int dy = Math.abs(ydif);
    int xs;
    if (xdif > 0) {
      xs = 1;
    }
    else {
      xs = -1;
    }
 
    int ys;
    if (ydif > 0) {
      ys = 1;
    }
    else {
      ys = -1;
    }
 
    if (dx > dy) {
      // Driving axis is the X-axis
      int p = 2 * dy - dx;
      while (x1 != x2) {
        x1 += xs;
        if (p >= 0) {
          y1 += ys;
          p -= 2 * dx;
        }
        p += 2 * dy;
        ListOfPoints.add(List.of(x1, y1));
      }
    }
    else {
      // Driving axis is the Y-axis
      int p = 2 * dx - dy;
      while (y1 != y2) {
        y1 += ys;
        if (p >= 0) {
          x1 += xs;
          p -= 2 * dy;
        }
        p += 2 * dx;
        ListOfPoints.add(List.of(x1, y1));
      }
    }
 
    return ListOfPoints;
  }
 
  static void DriverFunction()
  {
    int x1 = -9;
    int y1 = -3;
    int x2 = 10;
    int y2 = 1;
    List<List<Integer> > ListOfPoints
      = Bresenham2D(x1, y1, x2, y2);
    List<Integer> chainCode
      = generateChainCode(ListOfPoints);
 
    StringBuilder chainCodeString = new StringBuilder();
    for (int i = 0; i < chainCode.size(); i++) {
      chainCodeString.append(
        Integer.toString(chainCode.get(i)));
    }
 
    System.out.println(
      "Chain code for the straight line from (" + x1
      + "," + y1 + ") to (" + x2 + "," + y2 + ") is "
      + chainCodeString);
  }
 
  public static void main(String[] args)
  {
    DriverFunction();
  }
}
 
// This code is contributed by ishankhandelwals.


Python3




# Python3 code for generating 8-neighbourhood chain
# code for a 2-D line
 
codeList = [5, 6, 7, 4, -1, 0, 3, 2, 1]
 
# This function generates the chaincode
# for transition between two neighbour points
def getChainCode(x1, y1, x2, y2):
    dx = x2 - x1
    dy = y2 - y1
    hashKey = 3 * dy + dx + 4
    return codeList[hashKey]
 
'''This function generates the list of
chaincodes for given list of points'''
def generateChainCode(ListOfPoints):
    chainCode = []
    for i in range(len(ListOfPoints) - 1):
        a = ListOfPoints[i]
        b = ListOfPoints[i + 1]
        chainCode.append(getChainCode(a[0], a[1], b[0], b[1]))
    return chainCode
 
 
'''This function generates the list of points for
a straight line using Bresenham's Algorithm'''
def Bresenham2D(x1, y1, x2, y2):
    ListOfPoints = []
    ListOfPoints.append([x1, y1])
    xdif = x2 - x1
    ydif = y2 - y1
    dx = abs(xdif)
    dy = abs(ydif)
    if(xdif > 0):
        xs = 1
    else:
        xs = -1
    if (ydif > 0):
        ys = 1
    else:
        ys = -1
    if (dx > dy):
 
        # Driving axis is the X-axis
        p = 2 * dy - dx
        while (x1 != x2):
            x1 += xs
            if (p >= 0):
                y1 += ys
                p -= 2 * dx
            p += 2 * dy
            ListOfPoints.append([x1, y1])
    else:
 
        # Driving axis is the Y-axis
        p = 2 * dx-dy
        while(y1 != y2):
            y1 += ys
            if (p >= 0):
                x1 += xs
                p -= 2 * dy
            p += 2 * dx
            ListOfPoints.append([x1, y1])
    return ListOfPoints
 
def DriverFunction():
    (x1, y1) = (-9, -3)
    (x2, y2) = (10, 1)
    ListOfPoints = Bresenham2D(x1, y1, x2, y2)
    chainCode = generateChainCode(ListOfPoints)
    chainCodeString = "".join(str(e) for e in chainCode)
    print ('Chain code for the straight line from', (x1, y1),
            'to', (x2, y2), 'is', chainCodeString)
 
DriverFunction()


C#




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace CPP_to_C_Sharp
{
  class Program
  {
    static List<int> codeList = new List<int> { 5, 6, 7, 4, -1, 0, 3, 2, 1 };
 
    // This function generates the chaincode
    // for transition between two neighbour points
    static int getChainCode(int x1, int y1, int x2, int y2)
    {
      int dx = x2 - x1;
      int dy = y2 - y1;
      int hashKey = 3 * dy + dx + 4;
      return codeList[hashKey];
    }
 
    // This function generates the list of
    // chaincodes for given list of points
    static List<int> generateChainCode(
      List<List<int>> ListOfPoints)
    {
      List<int> chainCode = new List<int>();
      for (int i = 0; i < ListOfPoints.Count - 1; i++)
      {
        List<int> a = ListOfPoints[i];
        List<int> b = ListOfPoints[i + 1];
        chainCode.Add(getChainCode(a[0], a[1], b[0], b[1]));
      }
      return chainCode;
    }
 
    // This function generates the list of points for
    // a straight line using Bresenham's Algorithm
    static List<List<int>> Bresenham2D(int x1, int y1,
                                       int x2, int y2)
    {
      List<List<int>> ListOfPoints = new List<List<int>>();
      ListOfPoints.Add(new List<int> { x1, y1 });
      int xdif = x2 - x1;
      int ydif = y2 - y1;
      int dx = Math.Abs(xdif);
      int dy = Math.Abs(ydif);
      int xs;
      if (xdif > 0)
      {
        xs = 1;
      }
      else
      {
        xs = -1;
      }
 
      int ys;
      if (ydif > 0)
      {
        ys = 1;
      }
      else
      {
        ys = -1;
      }
 
      if (dx > dy)
      {
        // Driving axis is the X-axis
        int p = 2 * dy - dx;
        while (x1 != x2)
        {
          x1 += xs;
          if (p >= 0)
          {
            y1 += ys;
            p -= 2 * dx;
          }
          p += 2 * dy;
          ListOfPoints.Add(new List<int> { x1, y1 });
        }
      }
      else
      {
        // Driving axis is the Y-axis
        int p = 2 * dx - dy;
        while (y1 != y2)
        {
          y1 += ys;
          if (p >= 0)
          {
            x1 += xs;
            p -= 2 * dy;
          }
          p += 2 * dx;
          ListOfPoints.Add(new List<int> { x1, y1 });
        }
      }
 
      return ListOfPoints;
    }
 
    static void DriverFunction()
    {
      int x1 = -9;
      int y1 = -3;
      int x2 = 10;
      int y2 = 1;
      List<List<int>> ListOfPoints
        = Bresenham2D(x1, y1, x2, y2);
      List<int> chainCode
        = generateChainCode(ListOfPoints);
 
      string chainCodeString = "";
      for (int i = 0; i < chainCode.Count; i++)
      {
        chainCodeString += chainCode[i].ToString();
      }
 
      Console.WriteLine("Chain code for the straight line from ("
                        + x1 + "," + y1 + ") to (" + x2 + ","
                        + y2 + ") is " + chainCodeString);
    }
 
    static void Main(string[] args)
    {
      DriverFunction();
    }
  }
}
 
// This code is contributed by ishankhandelwals.


Javascript




// JavaScript code for generating 8-neighbourhood chain
// code for a 2-D line
 
let codeList = [5, 6, 7, 4, -1, 0, 3, 2, 1];
 
// This function generates the chaincode
// for transition between two neighbour points
function getChainCode(x1, y1, x2, y2){
    let dx = x2 - x1;
    let dy = y2 - y1;
    let hashKey = 3 * dy + dx + 4;
    return codeList[hashKey];  
}
 
 
// This function generates the list of
// chaincodes for given list of points
function generateChainCode(ListOfPoints){
    let chainCode = [];
    for(let i = 0; i < ListOfPoints.length-1; i++){
        let a = ListOfPoints[i];
        let b = ListOfPoints[i + 1];
        chainCode.push(getChainCode(a[0], a[1], b[0], b[1]));
             
    }
    return chainCode;   
}
 
// This function generates the list of points for
// a straight line using Bresenham's Algorithm
function Bresenham2D(x1, y1, x2, y2){
    let ListOfPoints = [];
    ListOfPoints.push([x1, y1]);
    let xdif = x2 - x1;
    let ydif = y2 - y1;
    let dx = Math.abs(xdif);
    let dy = Math.abs(ydif);
    if(xdif > 0){
        xs = 1;
    }      
    else{
        xs = -1;
    }
         
    if (ydif > 0){
        ys = 1;
    }
    else{
        ys = -1;
    }
         
    if (dx > dy){
        // Driving axis is the X-axis
        let p = 2 * dy - dx;
        while (x1 != x2){
            x1 += xs
            if (p >= 0){
                y1 += ys;
                p -= 2 * dx;        
            }
            p += 2 * dy;
            ListOfPoints.push([x1, y1]);        
        }
        
    }
    else{
        // Driving axis is the Y-axis
        let p = 2 * dx-dy;
        while(y1 != y2){
             y1 += ys;
            if (p >= 0){
                x1 += xs;
                p -= 2 * dy;             
            }
            p += 2 * dx;
            ListOfPoints.push([x1, y1]);       
        }
    }
     
    return ListOfPoints  
}
 
 
function DriverFunction(){
    let x1 = -9;
    let y1 = -3;
    let x2 = 10;
    let y2 = 1;
    let ListOfPoints = Bresenham2D(x1, y1, x2, y2);
    let chainCode = generateChainCode(ListOfPoints);
     
    let chainCodeString = "";
    for(let i = 0; i < chainCode.length; i++){
            chainCodeString += chainCode[i].toString();   
    }
 
    console.log("Chain code for the straight line from (", x1,",", y1,")","to","(", x2,",", y2,")", "is", chainCodeString);
}
 
DriverFunction();
// The code is contributed by Nidhi goel


Output: 

Chain code for the straight line from (-9, -3) to (10, 1) is 0010000100010000100

 

RELATED ARTICLES

Most Popular

Recent Comments