1 <!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN"
2 "http://www.w3.org/TR/REC-html40/loose.dtd">
4 <META NAME=
"GENERATOR" CONTENT=
"TtH 2.67">
8 <title> Eyebot image processing primitives
</title>
10 <H1 align=
"center">Eyebot image processing primitives
</H1>
12 <H3 align=center
>Petter Reinholdtsen
< pere@td.org.uit.no
> </H3>
14 <H3 align=center
>2000-
04-
21 </H3>
19 This document covers image processing functions available in Eyebot
20 RoBIOS version
2.3 internal patch level g. It tries to give the
21 reader a good start to use the available primitives as effective as
22 possible. It is based on the RoBIOS source code, to make sure the
23 function descriptions are as accurate as possible.
27 <H2><A NAME=
"tth_sEc1">
28 1</A> Introduction
</H2>
31 Eyebot image functions handle
4-bit gray scale images and
24 bit color
32 images. There are two defined image types, available when including
38 #define imagecolumns
82
40 BYTE image[imagerows][imagecolumns]; /*
5084 bytes */
41 BYTE colimage[imagerows][imagecolumns][
3]; /*
15252 bytes */
45 The image dimensions are
80 rows and
60 columns with one border row
46 on all sides. The color images are RGB images with red as byte
0,
47 green as byte
1 and blue as byte
2.
50 The memory layout of the image types makes this the fastest way to
51 loop thru the image components:
58 for (row =
1; row
< imagerows-
1; row++)
59 for (column =
1; column
< imagecolumns-
1; column++)
60 process_pixel(img[row][column]);
64 Note that pixels coordinates go from
1 to imagerows-
2 and
65 imagecolumns-
2 inclusive to skip the border pixels.
68 This loop might sometimes be faster, but it process the left and
69 right border pixels as well.
76 for (pos = imagecolumns; pos
< imagecolumns*(imagerows-
1); pos++)
77 process_pixel(img[
0][pos]);
81 The RoBIOS kernel has a number of image processing functions
82 available. I will here group them into camera, color, grey-scale and
83 LCD display functions. They are part of the Camera (CAM), Image
84 Processing (IP) and LCD module
87 In addition to the kernel functions, the libimprov library provides a
88 number of image operations.
91 <H2><A NAME=
"tth_sEc2">
92 2</A> Camera functions
</H2>
98 int CAMInit (int zoom);
99 int CAMGetColFrame (colimage * buf, int convert);
100 int CAMGetFrame (image * buf);
101 int CAMMode (int mode);
102 int CAMGet (int *bright, int *off, int *cont);
103 int CAMSet (int bright, int off, int cont);
107 Eyebot/RoBIOS currently supports three different cameras; Greyscale
108 QuickCam, Color QuickCam and EyeCam (color). The first Eyebots used
109 Greyscale QuickCams, while later models used Color QuickCams. The
110 latest model uses a locally designed EyeCam, as the older QuickCams
111 are no longer produced, and the specifications for the newer QuickCams
112 are impossible to get from Logitec.
115 Both QuickCam and EyeCam use the same lenses, and these lenses can
116 be replaced to change viewing-angle. Currently we have
33,
41,
43 and
117 47 degree lenses. When changing lens on the camera, make sure to get
118 the camera back to focus. Focusing is done by moving the lens back or
119 forward by turning it in the socket. The width of the EyeCam base is
123 The following code will grab one image from the camera:
129 int camversion, resval, resval2;
133 while (INITERROR == (camversion = CAMInit(NORMAL)))
136 if (NOCAM == camversion)
137 LCDPutString("No camera");
138 else if (BWCAM
<= camversion
&& camversion
< COLCAM)
139 resval = CAMGetFrame(
&img);
140 else if (COLCAM
<= camversion
&& camversion
< 0x20)
141 resval = CAMGetColFrame(
&colimg,
0); /* color image */
142 resval2 = CAMGetColFrame((colimage*)
&img,
1); /* grey image */
145 LCDPutString("CAMGet{Col}Frame() failed");
149 CAMInit() accepts parameter WIDE, NORMAL or TELE, to change the
150 zoom of the camera. This parameter is used by grey-scale QuickCam
151 only. CAMInit() might fail the first times, and the while loop make
152 sure the camera is initialized anyway. The version numbers returned
159 <tr><td align=
"right">0 </td><td>Greyscale QuickCam
</td></tr>
160 <tr><td align=
"right">16 </td><td>Color QuickCam
</td></tr>
161 <tr><td align=
"right">17 </td><td>EyeCam
</td></tr></TaBle>
166 CAMGetFrame() returns a
80x60
4-bit grey-scale image. The bits
167 occupy the lower
4 bit of an
8-bit BYTE.
170 CAMGetColFrame() returns a
24-bit color image if the second
171 parameter is
0, and a
4-bit grey-scale image if the second parameter
175 Each grab function returns as soon as the next complete image is
176 ready. The QuickCam grey scale delivers
20 frames per second. The
177 QuickCam color frame rate is normally
6.5 frames per second. The
178 EyeCam is stable on
3.7 frames per second, using
270000 microseconds
183 <p><A NAME=
"tth_fIg1">
185 <center> <img src=
"image0-color.png" alt=
"image0-color.png"><br>
187 <center> <img src=
"image1-color.png" alt=
"image1-color.png"><br>
190 <center>Figure
1: Two sample
24bit color images taken
191 from the same position. Left is from QuickCam with wide lens,
192 Right is from EyeCam with narrow lens. Images are
3x the original
196 CAMGet(), CAMSet() and CAMMode() can be used to change the current
197 camera settings. CAMMode() is used to enable or disable
198 autobrightness in the camera. Disabling autobrightness currently only
199 works with QuickCam. CAMGet() and CAMSet() is used to change the
200 brightness and color/grey adjustment parameters. They can
201 currently only be used with the QuickCam. The CAMInit() parameter is
202 only used on grey scale QuickCam.
205 <H2><A NAME=
"tth_sEc3">
206 3</A> Color image functions
</H2>
209 Color images are
82x62 including pixel border. The pixels are
24-bit
210 RGB (
3 x
8 bit), as fetched from the color camera.
213 <H3><A NAME=
"tth_sEc3.1">
214 3.1</A> IPColor2Grey
</H3>
220 int IPColor2Grey (colimage *src, image *dst);
224 This function converts a color image to
4-bit grey-scale images.
225 Pixels are converted using the following approximation (division by
4
226 is faster then division by
3): grey level = (R+
2*G+B)/
4.
230 <p><A NAME=
"tth_fIg2">
232 <center> <img src=
"image0-grey.png" alt=
"image0-grey.png"><br>
234 <center> <img src=
"image1-grey.png" alt=
"image1-grey.png"><br>
237 <center>Figure
2: Converted from color to grey-scale.
</center>
240 There is currently no way this function might fail, so it should
241 always return
0. The function uses
9200 microseconds on the Eyebot
242 and
350 microseconds in the simulator.
245 <H2><A NAME=
"tth_sEc4">
246 4</A> Grey-scale image functions
</H2>
249 Grey-scale images are
82x62 including pixel border and
4-bit grey level
250 values. The lower
4 bit of the pixel BYTE are used.
253 <H3><A NAME=
"tth_sEc4.1">
254 4.1</A> IPDither
</H3>
260 <tr><td align=
"right">Grey level
</td><td>0-
3 </td><td>4-
6 </td><td>7-
9 </td><td>10-
12 </td><td>13-
15 </td></tr>
261 <tr><td align=
"right">Pattern
</td><td>
263 <tr><td align=
"center"><TablE border=
0><tr><td nowrap align=center
>
264 00 </td></TABle></td></tr>
265 <tr><td align=
"center"><TablE border=
0><tr><td nowrap align=center
>
266 00 </td></TABle></td></tr></TaBle>
269 <tr><td align=
"center"><TablE border=
0><tr><td nowrap align=center
>
270 00 </td></TABle></td></tr>
271 <tr><td align=
"center"><TablE border=
0><tr><td nowrap align=center
>
272 10 </td></TABle></td></tr></TaBle>
275 <tr><td align=
"center"><TablE border=
0><tr><td nowrap align=center
>
276 01 </td></TABle></td></tr>
277 <tr><td align=
"center"><TablE border=
0><tr><td nowrap align=center
>
278 10 </td></TABle></td></tr></TaBle>
281 <tr><td align=
"center"><TablE border=
0><tr><td nowrap align=center
>
282 01 </td></TABle></td></tr>
283 <tr><td align=
"center"><TablE border=
0><tr><td nowrap align=center
>
284 11 </td></TABle></td></tr></TaBle>
287 <tr><td align=
"center"><TablE border=
0><tr><td nowrap align=center
>
288 11 </td></TABle></td></tr>
289 <tr><td align=
"center"><TablE border=
0><tr><td nowrap align=center
>
290 11 </td></TABle></td></tr></TaBle>
299 int IPDither (image *src, image *dst);
303 Converts every second grey-scale pixel and every second row to a
304 2x2 black and white pattern. It starts in upper left corner
305 (*src)[
1][
1] and writes the corresponding pattern to
306 (*dst)[
1-
2][
1-
2]. The patterns are given in the table to the
307 right. The border pixels are not touched.
311 <p><A NAME=
"tth_fIg3">
313 <center> <img src=
"image0-dither.png" alt=
"image0-dither.png"><br>
315 <center> <img src=
"image1-dither.png" alt=
"image1-dither.png"><br>
318 <center>Figure
3: Converted from grey-scale to
2x2 dithered.
</center>
321 There is currently no way this function might fail, so it should
322 always return
0. The function uses
4400 microseconds on the Eyebot
323 and
0.31 microsecond in the simulator.
326 <H3><A NAME=
"tth_sEc4.2">
327 4.2</A> IPLaplace
</H3>
333 int IPLaplace (image *src, image *dst);
337 Edge detection using the Laplace operator on each pixel using a
3x3
342 <br clear=
"all"><table border=
"0" width=
"100%"><tr><td>
343 <Table align=
"center"><tr><td nowrap
align=
"center">
344 result = abs (
</td><td nowrap align=center
>
346 <tr><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
347 0 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
348 <font face=symbol
>-
</font
349 >1 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
350 0 </td></TABle></td></tr>
351 <tr><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
352 <font face=symbol
>-
</font
353 >1 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
354 4 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
355 <font face=symbol
>-
</font
356 >1 </td></TABle></td></tr>
357 <tr><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
358 0 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
359 <font face=symbol
>-
</font
360 >1 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
361 0</td></TABle></td></tr></TaBle>
362 </td><td nowrap align=center
>
364 </td><td width=
"1%">(
1)
</td></table>
370 <p><A NAME=
"tth_fIg4">
372 <center> <img src=
"image0-laplace.png" alt=
"image0-laplace.png"><br>
374 <center> <img src=
"image1-laplace.png" alt=
"image1-laplace.png"><br>
377 <center>Figure
4: Result of Laplace operator.
</center>
380 There is currently no way this function might fail, so it should
381 always return
0. This function uses
21000 microseconds on the Eyebot
382 and
0.11 microsecond in the simulator.
385 <H3><A NAME=
"tth_sEc4.3">
386 4.3</A> IPSobel
</H3>
392 int IPSobel (image *src, image *dst);
396 Edge detection using the Sobel operator on each pixel using a
3x3
401 <br clear=
"all"><table border=
"0" width=
"100%"><tr><td>
402 <Table align=
"center"><tr><td nowrap
align=
"center">
403 result =
</td><td nowrap align=center
>
404 <tabLe border=
0><tr><td nowrap align=center
>
405 abs (
</td><td nowrap align=center
>
407 <tr><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
408 <font face=symbol
>-
</font
409 >1 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
410 0 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
411 1 </td></TABle></td></tr>
412 <tr><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
413 <font face=symbol
>-
</font
414 >2 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
415 0 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
416 2 </td></TABle></td></tr>
417 <tr><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
418 <font face=symbol
>-
</font
419 >1 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
420 0 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
421 1</td></TABle></td></tr></TaBle>
422 </td><td nowrap align=center
>
423 ) + abs (
</td><td nowrap align=center
>
425 <tr><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
426 <font face=symbol
>-
</font
427 >1 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
428 <font face=symbol
>-
</font
429 >2 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
430 <font face=symbol
>-
</font
431 >1 </td></TABle></td></tr>
432 <tr><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
433 0 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
434 0 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
435 0 </td></TABle></td></tr>
436 <tr><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
437 1 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
438 2 </td></TABle></td><td align=
"right"><TablE border=
0><tr><td nowrap align=center
>
439 1</td></TABle></td></tr></TaBle>
440 </td><td nowrap align=center
>
441 )
</td></tabLe><hr NOSHADE
>3<Br></td><td nowrap align=center
>
443 </td><td width=
"1%">(
2)
</td></table>
449 <p><A NAME=
"tth_fIg5">
451 <center> <img src=
"image0-sobel.png" alt=
"image0-sobel.png"><br>
453 <center> <img src=
"image1-sobel.png" alt=
"image1-sobel.png"><br>
456 <center>Figure
5: Result of Sobel operator.
</center>
459 There is currently no way this function might fail, so it should
460 always return
0. This function uses
35000 microseconds on the Eyebot
461 and
0.42 microsecond in the simulator.
464 <H3><A NAME=
"tth_sEc4.4">
465 4.4</A> IPDiffer
</H3>
471 int IPDiffer (image *source1, image *source2, image *destination);
475 Calculate the grey level difference and store result in
476 destination. The following formula is used for each pixel:
480 <br clear=
"all"><table border=
"0" width=
"100%"><tr><td>
481 <Table align=
"center"><tr><td nowrap
align=
"center">
482 destination = abs ( source1
<font face=symbol
>-
</font
483 > source2 )
</td></Table>
484 </td><td width=
"1%">(
3)
</td></table>
490 <p><A NAME=
"tth_fIg6">
492 <center> <img src=
"image0-differ.png" alt=
"image0-differ.png"><br>
494 <center> <img src=
"image1-differ.png" alt=
"image1-differ.png"><br>
497 <center>Figure
6: The result of 'Sobel' minus 'Laplace' operator.
</center>
500 There is currently no way this function might fail, so it should
501 always return
0. This function uses
8200 microseconds on the Eyebot
502 and
0.11 microsecond in the simulator.
505 <H2><A NAME=
"tth_sEc5">
506 5</A> LCD image display functions
</H2>
509 The LCD can display a black and white image with geometry
128x64 or
510 convert a
82x62 grey-scale image (excluding the border pixels) to
511 black and white before displaying it in the upper left corner of the
515 <H3><A NAME=
"tth_sEc5.1">
516 5.1</A> LCDPutImage
</H3>
522 int LCDPutImage (BYTE bwimg[(
128/
8)*
64]);
526 Write a
128x64 black/white image on the LCD display. Each byte is
527 8 pixel values. The bytes are printed left to right, top to
528 botton. The bits in each byte are printed in right to left order. I.e
529 the bits of the first two bytes in the array are printed in this
530 order:
76543210 76543210.
533 There is currently no way this function might fail, so it should
534 always return
0. This function uses
5500 microseconds on the Eyebot
535 and
20000 microsecond in the simulator.
538 <H3><A NAME=
"tth_sEc5.2">
539 5.2</A> LCDPutGraphic
</H3>
545 int LCDPutGraphic (image *img);
549 Converts and writes a
4-bit gray scale image in the upper left
550 corner of the black and white LCD display. The border pixels are not
551 written. If the grey level is
0-
7, the LCD pixel is inverted. If it
552 is
8-
15, the pixel is left as it is. If the LCD is cleared before the
553 image is displayed, this will give a simple printout of the image.
556 There is currently no way this function might fail, so it should
557 always return
0. This function uses
13000 microseconds on the Eyebot
558 and
20000 microsecond in the simulator.
561 <H2><A NAME=
"tth_sEc6">
562 6</A> Image processing speed
</H2>
565 Timings are done on
35 MHz Eyebot Mk3 using RoBIOS v2.3g. The
566 simulator ran on Pentium
133 MHz MMX. ms is time in microseconds, ips
567 is iterations per second when run in a loop.
573 <tr><td></td><td align=
"right">Simulator
</td><td align=
"right"></td><td align=
"right">Eyebot
</td></tr>
574 <tr><td>Function name
</td><td align=
"right">ms
</td><td align=
"right">ips
</td><td align=
"right">ms
</td><td align=
"right">ips
</td></tr>
575 <tr><td>CAMGetColFrame()
</td><td align=
"right">n/a
</td><td align=
"right">n/a
</td><td align=
"right">270000 </td><td align=
"right">3.7 </td></tr>
576 <tr><td>IPColor2Grey()
</td><td align=
"right">350 </td><td align=
"right">2900 </td><td align=
"right">9200 </td><td align=
"right">110 </td></tr>
577 <tr><td>IPDither()
</td><td align=
"right">0.31 </td><td align=
"right">3200000 </td><td align=
"right">4400 </td><td align=
"right">230 </td></tr>
578 <tr><td>IPLaplace()
</td><td align=
"right">0.11 </td><td align=
"right">9100000 </td><td align=
"right">21000 </td><td align=
"right">49 </td></tr>
579 <tr><td>IPSobel()
</td><td align=
"right">0.42 </td><td align=
"right">2400000 </td><td align=
"right">35000 </td><td align=
"right">28 </td></tr>
580 <tr><td>IPDiffer()
</td><td align=
"right">0.11 </td><td align=
"right">9100000 </td><td align=
"right">8200 </td><td align=
"right">120 </td></tr>
581 <tr><td>LCDPutImage()
</td><td align=
"right">20000 </td><td align=
"right">50 </td><td align=
"right">5500 </td><td align=
"right">180 </td></tr>
582 <tr><td>LCDPutGraphic()
</td><td align=
"right">35000 </td><td align=
"right">29 </td><td align=
"right">13000 </td><td align=
"right">76 </td></tr></TaBle>
587 <H2><A NAME=
"tth_sEc7">
588 7</A> References
</H2>
594 <dd><a href=
"http://www.ee.uwa.edu.au/~braunl/eyebot/ftp/ROBIOS/library.html">Eyebot RoBIOS library documentation
</a>, T. Bräunl, K. Schmitt, T Lampart
1998.
<br>
595 http://www.ee.uwa.edu.au/
braunl/eyebot/ftp/ROBIOS/library.html
599 <dd><a href=
"http://www.ee.uwa.edu.au/~braunl/eyebot/sim/sim.html">Eyesim -
600 Eyebot simulator
</a>, N. Tay, E. Nichols, G. Ong
1999.
<br>
601 http://www.ee.uwa.edu.au/
braunl/eyebot/sim/sim.html
605 <dd>Digital Image Processing, R. C. Gonzales and R. E. Woods,
609 </DL> <H2><A NAME=
"tth_sEc8">
610 8</A> Changelog
</H2>
614 <DL compact
><dt><b></b></dt>
615 <dd>2000-
04-
21 Converted base document from HTML to TeX. Correct
616 name of EyeCam from Eyebot.
620 <dd>2000-
01-
17 Removed some spelling errors and corrected the size
625 <dd>2000-
01-
10 First version released to the public.
629 <p><hr><small>File translated from
630 T
<sub><font size=
"-1">E
</font></sub>X
631 by
<a href=
"http://hutchinson.belmont.ma.us/tth/">
632 T
<sub><font size=
"-1">T
</font></sub>H
</a>,
633 version
2.67.
<br>On
24 Apr
2000,
11:
10.
</small>