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;
}