Computer Laboratory

Raspberry Pi

The First Step

0 The First Step

For this first step, we will introduce the basic functionality provided by the library, and then we will read and write pixel values. For these tutorials I will use 'nano' as a text editor, though you may use whichever text editor you are most comfortable with. These examples can be run from the terminal, and from the desktop.

First navigate to your home directory and create and edit a new file called basics.py, this will be our template for the remaining tutorial.

cd ~
sudo nano basics.py

Next we need to import the custom tutorial python module. So at the top of the file:

import imgproc
from imgproc import *

Now, we will load the webcam, and create a viewer window to display images. If you do not have a webcam, skip that line.

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

# Open a viewer window to display images
viewer = Viewer(160, 120, "The first step")

Next we will take a picture and display it in the viewer window, if you are not using a webcam, you can load bitmap (.bmp) images by suppling the path to the constructor img = Image("./path/bitmapfile.bmp") or in C, you can use the function imgFromBitmap("./path/bitmapfile.bmp") to create a new Image from the source file.

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

# for those without a webcam
img = Image("/path/to/image.bmp")

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

Now we have taken an image and displayed it in the viewer, we want to do something with it. The format of the image we take from the camera uses the colour model RGB, with 8 bits per colour channel. This gives us a range of values between 0 and 255 (inclusive) for each channel of each pixel. What we are going to do is iterate over every pixel in turn and set their colour to the pixels dominant channel. Here is the operation in psuedo-code:

ITERATE over every column in the image
	ITERATE over every row in every column

		GET the pixel at this row and column

		SET Red to the pixel's red intensity
		SET Green to the pixel's green intensity
		SET Blue to the pixel's blue intensity

		IF Red > Green AND Red > Blue THEN
			SET pixel's red to 255
			SET pixel's green to 0
			SET pixel's blue to 0
		ELSE IF Green > Red AND Green > Blue THEN
			SET pixel's green to 255
			SET pixel's red to 0
			SET pixel's blue to 0
		ELSE
			SET pixel's blue to 255
			SET pixel's red to 0
			SET pixel's green to 0
		END
	END
END

This code translates quite well into Python, for the iteration we can use a for loop. We need to iterate over the width and height of the image, which we can access as an element of our Image object with img.width and img.height

for x in range(0, img.width):
	for y in range(0, img.height):

Now we need to get the value of the pixel at the given position. To do this we treat the Image as a Python array, and we index it with a tuple of the x and y position of the pixel. The returned value is a tuple itself, made up of the red, green and blue intensities

		# Get the value at the xth column and yth row, place the intensities into variables
		red, green, blue = img[x, y]

Now we can test the red, green and blue values against each other as they are simply integers. To set the value of the pixel, we against index img as an array, and provide a tuple of the new red, green and blue values.

		if red > green and red > blue:
			# Set the value of a pixel
			img[x, y] = 255, 0, 0
		elif green > red and green > blue:
			img[x, y] = 0, 255, 0
		else:
			img[x, y] = 0, 0, 255

To finish up, we need to display the image again so that we can see the changes, call displayImage() again, and then use delay() to delay for a number of milliseconds before exiting.

# display the image again
viewer.displayImage(img)

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

Now we have reached the end of the script. To run the script exit nano, or your text editor, open a terminal and type.

sudo python basics.py

The script should open an image from the webcam, and then a few seconds later change to a primary coloured image, marking the dominant colour at each pixel. This script has the basic operations used to operate on each pixel in an image. You will find on the Raspberry Pi that the per pixel operations takes a few seconds to complete. This is mainly due to overhead from the Python interpreter, which causes the large number of pixel accesses to be quite slow.

Below is a full Python listing of this tutorials code, as well as a faster commented C implementation.

1 Code Listing

1.1 Python Code

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, "The first step")

# 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):
		# Get the value at the xth column and yth row, place the intensities into variables
		red, green, blue = img[x, y]

		# test to find which colour is dominant
		if red > green and red > blue:
			# Red is dominant, so set the pixel to completely red
			img[x, y] = 255, 0, 0
		elif green > red and green > blue:
			img[x, y] = 0, 255, 0
		else:
			# if red or green isn't dominant, blue must be
			img[x, y] = 0, 0, 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

1.2 C Code

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

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

Now here is the C source


#include <stdlib.h>
#include <stdio.h>
#include "imgproc.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(160, 120);

	// create a new viewer of the same resolution with a caption
	Viewer * view = viewOpen(160, 120, "First");

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

	// or for those without a webcam (uncomment and comment above)
	//Image * img = imgFromBitmap("/path/to/image.bmp");

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


	// iterators
	unsigned int x, y;
	for(x = 0; x < img->width; x++){
		for(y = 0; y < img->height; y++){
			// Get a pointer to the current pixel
			char * pixel = imgGetPixel(img, x, y);

			// extract the red, green and blue intensities
			// index 0 is blue and 2 is red
			char red = pixel[2];
			char green = pixel[1];
			char blue = pixel[0];

			// test for predominantly red
			if(red > green && red > blue){
				// set the pixel to the colour 255, 0, 0 (completely red)
				imgSetPixel(img, x, y, 255, 0, 0);
			}
			// green
			else if(green > red && green > blue){
				imgSetPixel(img, x, y, 0, 255, 0);
			}
			// assume blue otherwise
			else {
				imgSetPixel(img, x, y, 0, 0, 255);
			}
		}
	}

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

	// wait for 5 seconds to give us a chance to see the changes
	waitTime(5000);

	// now we will free the memory for the various objects
	imgDestroy(img);
	viewClose(view);
	camClose(cam);

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