Department of Computer Science and Technology

Raspberry Pi

Colour Key

0 Introduction

Now we have the basics, and have been introduced to the libraries functionality we can look at some image processing algorithms. The algorithm we will look at is this tutorial is a fairly basic one. The aim is apply a Colour Key to an image, picking out a specific colour or range of colours in the image and removing them, or replace them with a seperate background image. This is how green-screens are removed and replaced in film footage, although the algorithms used are likely more complicated than the one we will look at here.

1 The Algorithm

The algorithm we will use takes in a reference colour and a threshold. The threshold dictates how far away from the reference colour a pixel's colour can be and still pass.

To calculate which pixels pass, the difference between the 2 pixels colour channels is compared and the distance between them is calculated using the Pythagorean formula. The algorithm is outlined in pseudo-code below.


For each pixel:
1 Get the red green and blue values of the pixel
2 Subtract the red, green and blue values of the pixel from the respective
	channels of the comparison colour.  This is the colour difference in each
	colour axis.
3 Calculate the length of the line represented by the colour difference
	length = sqrt( sqr(red difference) + sqr(green difference) + sqr(blue difference) )
4 Compare this length to the threshold.  If it passes, mark it white, otherwise
	mark it black

2 The Implementation

This is all there is to the algorithm. Now we will implement it in Python. Take the code written for the basic tutorial and copy it into a new python file for this tutorial. Call it what you like.


import imgproc
from imgproc import *


# open a webcam to take pictures
camera = Camera(160, 120)

# Open a viewer window to display images
viewer = Viewer(160, 120, "Colour Key")

# take a picture from the camera
img = camera.grabImage()

# display the image in the viewer
viewer.displayImage(img)


# iterate over each pixel in the image
for x in range(0, img.width):
	for y in range(0, img.height):
		
		# our code will go here


# display the image again
viewer.displayImage(img)

# delay for 5000 milliseconds to give us time to see the changes, then exit
waitTime(5000)


# end of the script

The first change we need to make is we need to add import math. This will allow us to use the square root function needed.

Next we need to add a couple of variables, these will be constants that we use for the threshold and reference colour. Create these before the loop


ref_red = 192
ref_green = 80
ref_blue = 80
threshold = 96

You can set the reference colour to whatever you like, if you are using a webcam, you may have a coloured object you want to try and detect with the camera. Otherwise, there are some relevant images in the samples(NOTE) directory.

Now we extract each pixel value in turn, and subtract the pixel colour values from the reference.


for x in range(0, img.width):
	for y in range(0, img.height):
		red, green, blue = img[x, y]

		# subtract the pixel colour from the reference
		d_red = ref_red - red
		d_green = ref_green - green
		d_blue = ref_blue - blue

Next we find the length of the difference vector


		length = math.sqrt( (d_red * d_red) + (d_green * d_green) + (d_blue * d_blue) )

The final step is to compare this length against the reference threshold. For now if it passes we will just set the pixel completely white, and set it black otherwise.


		if length > threshold:
			img[x, y] = 0, 0, 0
		else:
			img[x, y] = 255, 255, 255

This is the entire basic algorithm, you can test it out now and try and pinpoint the colour of your object. This concludes the tutorial, I will leave it up to you to play with settings and come up with other ways of filtering colour. Something you may like to attempt is to remove the shade of colour from the equation, so that dark red and light red are both 'sensed' as being the same colour.

The code listings for Python are below, along with a faster C equivalent. The C example loops endlessly, grabbing frames from the Camera.

3 Code Listing

3.1 Python Code


import imgproc
from imgproc import *

# import maths module for the square root function
import math


# open a webcam to take pictures
camera = Camera(160, 120)

# Open a viewer window to display images
viewer = Viewer(160, 120, "Colour Key")

# take a picture from the camera
img = camera.grabImage()

# display the image in the viewer
viewer.displayImage(img)


# constant variables used in the algorithm
ref_red = 192
ref_green = 80
ref_blue = 80
threshold = 96


# take a picture from the camera
img = camera.grabImage()

# iterate over each pixel in the image
for x in range(0, img.width):
	for y in range(0, img.height):
		red, green, blue = img[x, y]

		# subtract the pixel colour from the reference
		d_red = ref_red - red
		d_green = ref_green - green
		d_blue = ref_blue - blue

		# length of the difference vector
		length = math.sqrt( (d_red * d_red) + (d_green * d_green) + (d_blue * d_blue) )

		if length > threshold:
			img[x, y] = 0, 0, 0
		else:
			img[x, y] = 255, 255, 255


# display the image again
viewer.displayImage(img)

# delay for 5000 milliseconds to give us time to see the changes, then exit
waitTime(5000)


# end of the script

3.2 C Code

To compile the C code type this command in the terminal.


sudo gcc -O2 -o colour colour.c -limgproc

Now here is the C source



#include <stdlib.h>
#include <stdio.h>
#include "imgproc.h"
#include <math.h>

int main(int argc, char * argv[])
{
	// initialise the library
	init_imgproc();


	// open the webcam, with a capture resolution of width 320 and height 240
	Camera * cam = camOpen(320, 240);

	// create a new viewer of the same resolution with a caption
	Viewer * view = viewOpen(320, 240, "Colour Key");


	while(1){
		// constant variables used in the algorithm
		unsigned int ref_red = 192;
		unsigned int ref_green = 80;
		unsigned int ref_blue = 80;
		unsigned int threshold = 96;

		// calculate the squared threshold to simplify calculations
		unsigned int threshold_sq = threshold * threshold;

		// capture an image from the webcam	
		Image * img = camGrabImage(cam);


		// iterators
		unsigned int x, y;
		for(x = 0; x < img->width; x++){
			for(y = 0; y < img->height; y++){
				char * pixel = imgGetPixel(img, x, y);
				unsigned int red = pixel[2];
				unsigned int green = pixel[1];
				unsigned int blue = pixel[0];

				// subtract the pixel colour from the reference
				unsigned int d_red = ref_red - red;
				unsigned int d_green = ref_green - green;
				unsigned int d_blue = ref_blue - blue;

				// calculate the squared length of the difference vector
				unsigned int length_sq = d_red * d_red +
										 d_green * d_green + 
										 d_blue * d_blue;

				if(length_sq > threshold_sq){
					imgSetPixel(img, x, y, 0, 0, 0);
				} else {
					imgSetPixel(img, x, y, 255, 255, 255);
				}
			}
		}

		// display the image
		viewDisplayImage(view, img);

		// destroy the image
		imgDestroy(img);
	}

	// finally quit
	viewClose(view);
	camClose(cam);

	// finally we uninitialise the library
	quit_imgproc();
	return 0;
}