3 <TITLE>Eyebot image processing primitives
</TITLE>
6 <H1>Eyebot image processing primitives
</H1>
8 <ADDRESS>Petter Reinholdtsen
<pere@td.org.uit.no
>,
2000-
01-
17</ADDRESS>
12 This document covers image processing functions available in Eyebot
13 RoBIOS version
2.3 internal patch level g. It tries to give the
14 reader a good start to use the available primitives as effective as
15 possible. It is based on the RoBIOS source code, to make sure the
16 function descriptions are as accurate as possible.
22 <P>Eyebot image functions handle
4-bit gray scale images and
24 bit color
23 images. There are two defined image types, available when including
27 #define imagecolumns
82
29 BYTE image[imagerows][imagecolumns]; /*
5084 bytes */
30 BYTE colimage[imagerows][imagecolumns][
3]; /*
15252 bytes */
33 <P>The image dimensions are
80 rows and
60 columns with one border row
34 on all sides. The color images are RGB images with red as byte
0,
35 green as byte
1 and blue as byte
2.
37 <P>The memory layout of the image types makes this the fastest way to
38 loop thru the image components:
43 for (row =
1; row < imagerows-
1; row++)
44 for (column =
1; column < imagecolumns-
1; column++)
45 process_pixel(img[row][column]);
48 <P>Note that pixels coordinates go from
1 to imagerows-
2 and
49 imagecolumns-
2 inclusive to skip the border pixels.
</P>
51 <P>This loop might sometimes be faster, but it process the left and
52 right border pixels as well.
58 for (pos = imagecolumns; pos < imagecolumns*(imagerows-
1); pos++)
59 process_pixel(img[
0][pos]);
62 <P>The RoBIOS kernel has a number of image processing functions
63 available. I will here group them into camera, color, grey-scale and
64 LCD display functions. They are part of the Camera (CAM), Image
65 Processing (IP) and LCD module
67 <P>In addition to the kernel functions, the libimprov library provides a
68 number of image operations.
70 <H2>Camera functions
</H2>
75 int CAMInit (int zoom);
77 int CAMGetColFrame (colimage * buf, int convert);
78 int CAMGetFrame (image * buf);
80 int CAMMode (int mode);
81 int CAMGet (int *bright, int *off, int *cont);
82 int CAMSet (int bright, int off, int cont);
85 <P>Eyebot/RoBIOS currently supports three different cameras; Greyscale
86 QuickCam, Color QuickCam and EyeCam (color). The first Eyebots used
87 Greyscale QuickCams, while later models used Color QuickCams. The
88 latest model uses a locally designed EyeCam, as the older QuickCams
89 are no longer produced, and the specifications for the newer QuickCams
90 are impossible to get from Logitec.
92 <P>Both QuickCam and EyeCam use the same lenses, and these lenses can
93 be replaced to change viewing-angle. Currently we have
33,
41,
43 and
94 47 degree lenses. When changing lens on the camera, make sure to get
95 the camera back to focus. Focusing is done by moving the lens back or
96 forward by turning it in the socket. The width of the EyeCam base is
99 <P>The following code will grab one image from the camera:
104 int camversion, resval, resval2;
108 while (INITERROR == (camversion = CAMInit(NORMAL)))
111 if (NOCAM == camversion)
112 LCDPutString("No camera");
113 else if (BWCAM <= camversion && camversion < COLCAM)
114 resval = CAMGetFrame(&img);
115 else if (COLCAM <= camversion && camversion <
0x20)
116 resval = CAMGetColFrame(&colimg,
0); /* color image */
117 resval2 = CAMGetColFrame((colimage*)&img,
1); /* grey image */
120 LCDPutString("CAMGet{Col}Frame() failed");
123 <P>CAMInit() accepts parameter WIDE, NORMAL or TELE, to change the
124 zoom of the camera. This parameter is used by grey-scale QuickCam
125 only. CAMInit() might fail the first times, and the while loop make
126 sure the camera is initialized anyway. The version numbers returned
127 from CAMInit() are:
</P>
129 <TABLE ALIGN=
"center">
130 <TR><TD>0</TD><TD>Greyscale QuickCam
</TD></TR>
131 <TR><TD>16</TD><TD>Color QuickCam
</TD></TR>
132 <TR><TD>17</TD><TD>Eyebot
</TD></TR>
135 <P>CAMGetFrame() returns a
80x60
4-bit grey-scale image. The bits
136 occupy the lower
4 bit of an
8-bit BYTE.
138 <P>CAMGetColFrame() returns a
24-bit color image if the second
139 parameter is
0, and a
4-bit grey-scale image if the second parameter
142 Each grab function returns as soon as the next complete image is
143 ready. The QuickCam grey scale delivers
20 frames per second. The
144 QuickCam color frame rate is normally
6.5 frames per second. The
145 EyeCam is stable on
3.7 frames per second, using ~
270000 microseconds
146 to grab one frame.
</P>
148 <TABLE ALIGN=
"center">
149 <TR><TD><IMG SRC=
"image0-color.png" ALIGN=
"left"></TD>
150 <TD><IMG SRC=
"image1-color.png" ALIGN=
"right"></TD><TR>
152 <TR><TD COLSPAN=
"2" ALIGN=
"center">Two sample
24bit color images taken
153 from the same position. Left is from QuickCam with
<BR>wide lens,
154 Right is from EyeCam with narrow lens. Images are
3x the original
159 <P>CAMGet(), CAMSet() and CAMMode() can be used to change the current
160 camera settings. CAMMode() is used to enable or disable
161 autobrightness in the camera. Disabling autobrightness currently only
162 works with QuickCam. CAMGet() and CAMSet() is used to change the
163 brightness and color/grey adjustment parameters. They can
164 currently only be used with the QuickCam. The CAMInit() parameter is
165 only used on grey scale QuickCam.
167 <H2>Color image functions
</H2>
169 <P>Color images are
82x62 including pixel border. The pixels are
24-bit
170 RGB (
3 x
8 bit), as fetched from the color camera.
172 <H3>IPColor2Grey
</H3>
177 int IPColor2Grey (colimage *src, image *dst);
180 <P>This function converts a color image to
4-bit grey-scale images.
181 Pixels are converted using the following approximation (division by
4
182 is faster then division by
3): grey level = (R+
2*G+B)/
4.
</P>
184 <TABLE ALIGN=
"center">
185 <TR><TD><IMG SRC=
"image0-grey.png" ALIGN=
"left"></TD>
186 <TD><IMG SRC=
"image1-grey.png" ALIGN=
"right"></TD><TR>
187 <TR><TD COLSPAN=
"2" ALIGN=
"center">Converted from color to grey-scale.
</TD></TR>
190 <P>There is currently no way this function might fail, so it should
191 always return
0. The function uses ~
9200 microseconds on the Eyebot
192 and ~
350 microseconds in the simulator.
194 <H2>Grey-scale image functions
</H2>
196 <P>Grey-scale images are
82x62 including pixel border and
4-bit grey level
197 values. The lower
4 bit of the pixel BYTE are used.
201 <TABLE ALIGN=
"right" BORDER=
"1">
202 <TR><TH>Grey level
</TH><TH>Pattern
</TH><TH>Grey level
</TH><TH>Pattern
</TH></TR>
203 <TR><TD>0-
3</TD><TD ALIGN=
"center">00<BR>00</TD>
204 <TD>10-
12</TD><TD ALIGN=
"center">01<BR>11</TD></TR>
205 <TR><TD>4-
6</TD><TD ALIGN=
"center">00<BR>10</TD>
206 <TD>13-
15</TD><TD ALIGN=
"center">11<BR>11</TD></TR>
207 <TR><TD>7-
9</TD><TD ALIGN=
"center">01<BR>10</TD></TR>
213 int IPDither (image *src, image *dst);
216 <P>Converts every second grey-scale pixel and every second row to a
217 2x2 black and white pattern. It starts in upper left corner
218 (*src)[
1][
1] and writes the corresponding pattern to
219 (*dst)[
1-
2][
1-
2]. The patterns are given in the table to the
220 right. The border pixels are not touched.
</P>
223 <TABLE ALIGN=
"center">
224 <TR><TD><IMG SRC=
"image0-dither.png" ALIGN=
"left"></TD>
225 <TD><IMG SRC=
"image1-dither.png" ALIGN=
"right"></TD><TR>
226 <TR><TD COLSPAN=
"2" ALIGN=
"center">Converted from grey-scale to
2x2 dithered.
</TD></TR>
229 <P>There is currently no way this function might fail, so it should
230 always return
0. The function uses ~
4400 microseconds on the Eyebot
231 and ~
0.31 microsecond in the simulator.
238 int IPLaplace (image *src, image *dst);
241 <P>Edge detection using the Laplace operator on each pixel using a
3x3
246 result = abs ( -
1 4 -
1 )
250 <TABLE ALIGN=
"center">
251 <TR><TD><IMG SRC=
"image0-laplace.png" ALIGN=
"left"></TD>
252 <TD><IMG SRC=
"image1-laplace.png" ALIGN=
"right"></TD><TR>
253 <TR><TD COLSPAN=
"2" ALIGN=
"center">Result of Laplace operator.
</TD></TR>
256 <P>There is currently no way this function might fail, so it should
257 always return
0. This function uses ~
21000 microseconds on the Eyebot
258 and ~
0.11 microsecond in the simulator.
266 int IPSobel (image *src, image *dst);
269 <P>Edge detection using the Sobel operator on each pixel using a
3x3
274 result = [ abs ( -
2 0 2 ) + abs (
0 0 0 ) ] /
3
278 <TABLE ALIGN=
"center">
279 <TR><TD><IMG SRC=
"image0-sobel.png" ALIGN=
"left"></TD>
280 <TD><IMG SRC=
"image1-sobel.png" ALIGN=
"right"></TD><TR>
281 <TR><TD COLSPAN=
"2" ALIGN=
"center">Result of Sobel operator.
</TD></TR>
284 <P>There is currently no way this function might fail, so it should
285 always return
0. This function uses ~
35000 microseconds on the Eyebot
286 and ~
0.42 microsecond in the simulator.
293 int IPDiffer (image *source1, image *source2, image *destination);
296 <P>Calculate the grey level difference and store result in
297 destination. The following formula is used for each pixel:
</P>
300 destination = source1 - source2;
302 destination = -destination;
305 <TABLE ALIGN=
"center">
306 <TR><TD><IMG SRC=
"image0-differ.png" ALIGN=
"left"></TD>
307 <TD><IMG SRC=
"image1-differ.png" ALIGN=
"right"></TD><TR>
308 <TR><TD COLSPAN=
"2" ALIGN=
"center">The result of 'Sobel' minus 'Laplace' operator.
</TD></TR>
311 <P>There is currently no way this function might fail, so it should
312 always return
0. This function uses ~
8200 microseconds on the Eyebot
313 and ~
0.11 microsecond in the simulator.
315 <H2>LCD image display functions
</H2>
317 <P>The LCD can display a black and white image with geometry
128x64 or
318 convert a
82x62 grey-scale image (excluding the border pixels) to
319 black and white before displaying it in the upper left corner of the
327 int LCDPutImage (BYTE bwimg[(
128/
8)*
64]);
330 <P>Write a
128x64 black/white image on the LCD display. Each byte is
331 8 pixel values. The bytes are printed left to right, top to
332 botton. The bits in each byte are printed in right to left order. I.e
333 the bits of the first two bytes in the array are printed in this
334 order: |
76543210|
76543210|
336 <P>There is currently no way this function might fail, so it should
337 always return
0. This function uses ~
5500 microseconds on the Eyebot
338 and ~
20000 microsecond in the simulator.
340 <H3>LCDPutGraphic
</H3>
345 int LCDPutGraphic (image *img);
348 <P>Converts and writes a
4-bit gray scale image in the upper left
349 corner of the black and white LCD display. The border pixels are not
350 written. If the grey level is
0-
7, the LCD pixel is inverted. If it
351 is
8-
15, the pixel is left as it is. If the LCD is cleared before the
352 image is displayed, this will give a simple printout of the image.
354 <P>There is currently no way this function might fail, so it should
355 always return
0. This function uses ~
13000 microseconds on the Eyebot
356 and ~
20000 microsecond in the simulator.
358 <H2>Image processing speed
</H2>
360 <P>Timings are done on
35 MHz Eyebot Mk3 using RoBIOS v2.3g. The
361 simulator ran on Pentium
133 MHz MMX. ms is time in microseconds, ips
362 is iterations per second when run in a loop.
</P>
364 <TABLE ALIGN=
"center">
365 <TR><TH></TH><TH COLSPAN=
"2">Simulator
</TH><TH COLSPAN=
"2">Eyebot
</TH></TR>
366 <TR><TH>Function name
</TH><TH>ms
</TH><TH>ips
</TH><TH>ms
</TH><TH>ips
</TH></TR>
367 <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>
368 <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>
369 <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>
370 <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>
371 <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>
372 <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>
373 <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>
374 <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>
380 <DT><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.
381 <DD>http://www.ee.uwa.edu.au/~braunl/eyebot/ftp/ROBIOS/library.html
383 <DT><A HREF=
"http://www.ee.uwa.edu.au/~braunl/eyebot/sim/sim.html">Eyesim -
384 Eyebot simulator
</A></DT>, N. Tay, E. Nichols, G. Ong
1999.
385 <DD>http://www.ee.uwa.edu.au/~braunl/eyebot/sim/sim.html
387 <DT>Digital Image Processing, R. C. Gonzales and R. E. Woods,
388 Addison-Wesley
1992</DT>
393 <P>2000-
01-
17 Removed some spelling errors and corrected the size of
395 <P>2000-
01-
10 First version released to the public.
398 <!-- LocalWords: Eyebot RoBIOS QuickCam EyeCam