1 \documentclass[a4paper,
10pt
]{article
}
5 \title{Eyebot image processing primitives
}
6 \author{Petter Reinholdtsen $<$pere@td.org.uit.no$>$
}
9 % Make sure \href works in play LaTeX as well.
10 \def\hyperlink#1#2{\special{html:<a href="\#
#1">
}#2\special{html:</a>
}}
11 % Incorrect link name in \TeX\ because # can't be passed properly to a special.
12 \def\hypertarget#1#2{\special{html:<a name="
#1">
}#2\special{html:</a>
}}
13 \long\def\tthdump#1{#1} % Do nothing. The following are not done for TtH.
15 \def\title#1{\bgroup\leftskip 0 pt plus1fill
\rightskip 0 pt plus1fill
16 \pretolerance=
100000 \lefthyphenmin=
20 \righthyphenmin=
20
17 \noindent #1 \par\egroup}% Centers a possibly multi-line title.
18 \let\author=
\title % Actually smaller font than title in \LaTeX.
19 \input epsf
% PD package defines \epsfbox for figure inclusion
20 % Macro for http reference inclusion, per hypertex.
21 \def\href#1#2{\special{html:<a href="
#1">
}#2\special{html:</a>
}}
22 \def\urlend#1{#1\endgroup}
23 \def\url{\begingroup \tt
24 \catcode`
\_=
13 % Don't know why this works.
25 \catcode`\~=
11 \catcode`\#=
11 \catcode`\^=
11
26 \catcode`\$=
11 \catcode`\&=
11 \catcode`\%=
11
27 \urlend}% \url for plain \TeX.
35 This
document covers image processing functions available in Eyebot
36 RoBIOS version
2.3 internal patch level g. It tries to give the
37 reader a good start to use the available primitives as effective as
38 possible. It is based on the RoBIOS source code, to make sure the
39 function descriptions are as accurate as possible.
42 \section{Introduction
}
44 Eyebot image functions handle
4-bit gray scale images and
24 bit
color
45 images. There are two defined image types, available when including
49 #define imagecolumns
82
51 BYTE image
[imagerows
][imagecolumns
]; /*
5084 bytes */
52 BYTE colimage
[imagerows
][imagecolumns
][3]; /*
15252 bytes */
55 The image dimensions are
80 rows and
60 columns with one border row
56 on all sides. The
color images are RGB images with red as byte
0,
57 green as byte
1 and blue as byte
2.
59 The memory layout of the image types makes this the fastest way to
60 loop thru the image components:
65 for (row =
1; row < imagerows-
1; row++)
66 for (column =
1; column < imagecolumns-
1; column++)
67 process_pixel(img
[row
][column
]);
70 Note that pixels coordinates go from
1 to imagerows-
2 and
71 imagecolumns-
2 inclusive to skip the border pixels.
73 This loop might sometimes be faster, but it process the left and
74 right border pixels as well.
79 for (pos = imagecolumns; pos < imagecolumns*(imagerows-
1); pos++)
80 process_pixel(img
[0][pos
]);
83 The RoBIOS kernel has a number of image processing functions
84 available. I will here group them into camera,
color, grey-scale and
85 LCD display functions. They are part of the Camera (CAM), Image
86 Processing (IP) and LCD module
88 In addition to the kernel functions, the libimprov library provides a
89 number of image operations.
91 \section{Camera functions
}
95 int CAMInit (int zoom);
96 int CAMGetColFrame (colimage * buf, int convert);
97 int CAMGetFrame (image * buf);
98 int CAMMode (int mode);
99 int CAMGet (int *bright, int *off, int *cont);
100 int CAMSet (int bright, int off, int cont);
103 Eyebot/RoBIOS currently supports three different cameras; Greyscale
104 QuickCam, Color QuickCam and EyeCam (
color). The first Eyebots used
105 Greyscale QuickCams, while later models used Color QuickCams. The
106 latest model uses a locally designed EyeCam, as the older QuickCams
107 are no longer produced, and the specifications for the newer QuickCams
108 are impossible to get from Logitec.
110 Both QuickCam and EyeCam use the same lenses, and these lenses can
111 be replaced to change viewing-angle. Currently we have
33,
41,
43 and
112 47 degree lenses. When changing lens on the camera, make sure to get
113 the camera back to focus. Focusing is done by moving the lens back or
114 forward by turning it in the socket. The width of the EyeCam base is
117 The following code will grab one image from the camera:
121 int camversion, resval, resval2;
125 while (INITERROR == (camversion = CAMInit(NORMAL)))
128 if (NOCAM == camversion)
129 LCDPutString("No camera");
130 else if (BWCAM <= camversion && camversion < COLCAM)
131 resval = CAMGetFrame(&img);
132 else if (COLCAM <= camversion && camversion <
0x20)
133 resval = CAMGetColFrame(&colimg,
0); /*
color image */
134 resval2 = CAMGetColFrame((colimage*)&img,
1); /* grey image */
137 LCDPutString("CAMGet
{Col
}Frame() failed");
140 CAMInit() accepts parameter WIDE, NORMAL or TELE, to change the
141 zoom of the camera. This parameter is used by grey-scale QuickCam
142 only. CAMInit() might fail the first times, and the while loop make
143 sure the camera is initialized anyway. The version numbers returned
147 \begin{tabular
}{|r|l|
}
149 0 & Greyscale QuickCam \\
150 16 & Color QuickCam \\
156 CAMGetFrame() returns a
80x60
4-bit grey-scale image. The bits
157 occupy the lower
4 bit of an
8-bit BYTE.
159 CAMGetColFrame() returns a
24-bit
color image if the second
160 parameter is
0, and a
4-bit grey-scale image if the second parameter
163 Each grab function returns as soon as the next complete image is
164 ready. The QuickCam grey scale delivers
20 frames per second. The
165 QuickCam
color frame rate is normally
6.5 frames per second. The
166 EyeCam is stable on
3.7 frames per second, using ~
270000 microseconds
171 \begin{minipage
}[c
]{0.5\textwidth}
172 \centering \includegraphics[width=
1in
]{image0-
color}
174 \begin{minipage
}[c
]{0.5\textwidth}
175 \centering \includegraphics[width=
1in
]{image1-
color}
177 \caption{Two sample
24bit
color images taken
178 from the same position. Left is from QuickCam with wide lens,
179 Right is from EyeCam with narrow lens. Images are
3x the original
183 CAMGet(), CAMSet() and CAMMode() can be used to change the current
184 camera settings. CAMMode() is used to enable or disable
185 autobrightness in the camera. Disabling autobrightness currently only
186 works with QuickCam. CAMGet() and CAMSet() is used to change the
187 brightness and
color/grey adjustment parameters. They can
188 currently only be used with the QuickCam. The CAMInit() parameter is
189 only used on grey scale QuickCam.
191 \section{Color image functions
}
193 Color images are
82x62 including pixel border. The pixels are
24-bit
194 RGB (
3 x
8 bit), as fetched from the
color camera.
196 \subsection{IPColor2Grey
}
200 int IPColor2Grey (colimage *src, image *dst);
203 This function converts a
color image to
4-bit grey-scale images.
204 Pixels are converted using the following approximation (division by
4
205 is faster then division by
3): grey level = (R+
2*G+B)/
4.
209 \begin{minipage
}[c
]{0.5\textwidth}
210 \centering \includegraphics[width=
1in
]{image0-grey
}
212 \begin{minipage
}[c
]{0.5\textwidth}
213 \centering \includegraphics[width=
1in
]{image1-grey
}
215 \caption{Converted from
color to grey-scale.
}
218 There is currently no way this function might fail, so it should
219 always return
0. The function uses ~
9200 microseconds on the Eyebot
220 and ~
350 microseconds in the simulator.
222 \section{Grey-scale image functions
}
224 Grey-scale images are
82x62 including pixel border and
4-bit grey level
225 values. The lower
4 bit of the pixel BYTE are used.
227 \subsection{IPDither
}
230 \begin{tabular
}{|r|l|l|l|l|l|
}
232 Grey level &
0-
3 &
4-
6 &
7-
9 &
10-
12 &
13-
15 \\
235 $
\begin{array
}{cc
} 00 \\
00 \end{array
} $ &
236 $
\begin{array
}{cc
} 00 \\
10 \end{array
} $ &
237 $
\begin{array
}{cc
} 01 \\
10 \end{array
} $ &
238 $
\begin{array
}{cc
} 01 \\
11 \end{array
} $ &
239 $
\begin{array
}{cc
} 11 \\
11 \end{array
} $ \\
246 int IPDither (image *src, image *dst);
249 Converts every second grey-scale pixel and every second row to a
250 2x2 black and white pattern. It starts in upper left corner
251 (*src)[1][1] and writes the corresponding pattern to
252 (*dst)[1-2][1-2]. The patterns are given in the table to the
253 right. The border pixels are not touched.
257 \begin{minipage}[c]{0.5\textwidth}
258 \centering \includegraphics[width=1in]{image0-dither}
260 \begin{minipage}[c]{0.5\textwidth}
261 \centering \includegraphics[width=1in]{image1-dither}
263 \caption{Converted from grey-scale to 2x2 dithered.}
266 There is currently no way this function might fail, so it should
267 always return 0. The function uses ~4400 microseconds on the Eyebot
268 and ~0.31 microsecond in the simulator.
270 \subsection{IPLaplace}
274 int IPLaplace (image *src, image *dst);
277 Edge detection using the Laplace operator on each pixel using a 3x3
281 result = \mathrm{abs} (
292 \begin{minipage}[c]{0.5\textwidth}
293 \centering \includegraphics[width=1in]{image0-laplace}
295 \begin{minipage}[c]{0.5\textwidth}
296 \centering \includegraphics[width=1in]{image1-laplace}
298 \caption{Result of Laplace operator.}
301 There is currently no way this function might fail, so it should
302 always return 0. This function uses ~21000 microseconds on the Eyebot
303 and ~0.11 microsecond in the simulator.
310 int IPSobel (image *src, image *dst);
313 Edge detection using the Sobel operator on each pixel using a 3x3
317 result = {\mathrm{abs} (
334 \begin{minipage}[c]{0.5\textwidth}
335 \centering \includegraphics[width=1in]{image0-sobel}
337 \begin{minipage}[c]{0.5\textwidth}
338 \centering \includegraphics[width=1in]{image1-sobel}
340 \caption{Result of Sobel operator.}
343 There is currently no way this function might fail, so it should
344 always return 0. This function uses ~35000 microseconds on the Eyebot
345 and ~0.42 microsecond in the simulator.
347 \subsection{IPDiffer}
351 int IPDiffer (image *source1, image *source2, image *destination);
354 Calculate the grey level difference and store result in
355 destination. The following formula is used for each pixel:
358 destination = \mathrm{abs} ( source1 - source2 )
363 \begin{minipage}[c]{0.5\textwidth}
364 \centering \includegraphics[width=1in]{image0-differ}
366 \begin{minipage}[c]{0.5\textwidth}
367 \centering \includegraphics[width=1in]{image1-differ}
369 \caption{The result of 'Sobel' minus 'Laplace' operator.}
372 There is currently no way this function might fail, so it should
373 always return 0. This function uses ~8200 microseconds on the Eyebot
374 and ~0.11 microsecond in the simulator.
376 \section{LCD image display functions}
378 The LCD can display a black and white image with geometry 128x64 or
379 convert a 82x62 grey-scale image (excluding the border pixels) to
380 black and white before displaying it in the upper left corner of the
383 \subsection{LCDPutImage}
387 int LCDPutImage (BYTE bwimg[(128/8)*64]);
390 Write a 128x64 black/white image on the LCD display. Each byte is
391 8 pixel values. The bytes are printed left to right, top to
392 botton. The bits in each byte are printed in right to left order. I.e
393 the bits of the first two bytes in the array are printed in this
394 order: 76543210 76543210.
396 There is currently no way this function might fail, so it should
397 always return 0. This function uses ~5500 microseconds on the Eyebot
398 and ~20000 microsecond in the simulator.
400 \subsection{LCDPutGraphic}
404 int LCDPutGraphic (image *img);
407 Converts and writes a 4-bit gray scale image in the upper left
408 corner of the black and white LCD display. The border pixels are not
409 written. If the grey level is 0-7, the LCD pixel is inverted. If it
410 is 8-15, the pixel is left as it is. If the LCD is cleared before the
411 image is displayed, this will give a simple printout of the image.
413 There is currently no way this function might fail, so it should
414 always return 0. This function uses ~13000 microseconds on the Eyebot
415 and ~20000 microsecond in the simulator.
417 \section{Image processing speed}
419 Timings are done on 35 MHz Eyebot Mk3 using RoBIOS v2.3g. The
420 simulator ran on Pentium 133 MHz MMX. ms is time in microseconds, ips
421 is iterations per second when run in a loop.
424 \begin{tabular}{|l|r|r|r|r|}
426 & Simulator & & Eyebot \\
427 Function name & ms & ips & ms & ips \\
429 CAMGetColFrame() & n/a & n/a & 270000 & 3.7 \\
430 IPColor2Grey() & 350 & 2900 & 9200 & 110 \\
431 IPDither() & 0.31 & 3200000 & 4400 & 230 \\
432 IPLaplace() & 0.11 & 9100000 & 21000 & 49 \\
433 IPSobel() & 0.42 & 2400000 & 35000 & 28 \\
434 IPDiffer() & 0.11 & 9100000 & 8200 & 120 \\
435 LCDPutImage() & 20000 & 50 & 5500 & 180 \\
436 LCDPutGraphic() & 35000 & 29 & 13000 & 76 \\
444 \item{\href{http://www.ee.uwa.edu.au/~braunl/eyebot/ftp/ROBIOS/library.html}{Eyebot RoBIOS library documentation}, T. Bräunl, K. Schmitt, T Lampart 1998.} \\
445 http://www.ee.uwa.edu.au/~braunl/eyebot/ftp/ROBIOS/library.html
447 \item{\href{http://www.ee.uwa.edu.au/~braunl/eyebot/sim/sim.html}{Eyesim -
448 Eyebot simulator}, N. Tay, E. Nichols, G. Ong 1999.} \\
449 http://www.ee.uwa.edu.au/~braunl/eyebot/sim/sim.html
451 \item{Digital Image Processing, R. C. Gonzales and R. E. Woods,
460 \item{2000-04-21} Converted base document from HTML to TeX. Correct
461 name of EyeCam from Eyebot.
463 \item{2000-01-17} Removed some spelling errors and corrected the size
466 \item{2000-01-10} First version released to the public.