Please consider this version of MVTec HORUS still beta. This version is our first port to FreeBSD and there are still some problems, mostly regarding Motif. MVTec HORUS is a very sophisitcated tool. Up to now it consists of more than 21 MB source code. Please forgive us the bugs in the first version, report them to us, and the next version will be even better!
Thank you.
Most vision applications are in the field of manufacturing, industrial inspection, and quality control. MVTec HORUS offers a wide range of realtime operators to help you improve your manufacturing process.
Remote sensing is a growing market. If you want to start in this business, you need a tool for processing multi-channel images. MVTec HORUS eases the interpretation with powerful segmentation techniques.
MVTec HORUS offers operators to process a wide range of medical images from different modalities. Image segmentation is not easy in this area due to noise and other artifacts. However, a few minutes of interactive MVTec HORUS programming can solve most of the typical problems you might consider.
Camera calibration is the key to obtain exact 3D measurements from video images. MVTec HORUS calibrates your camera with a few lines of code.
Color is a key feature for many applications. MVTec HORUS gives you a set of easy-to-use operators for handling color images.
For Further Information,
please go to the end of this document or contact MVTec Software GmbH directly
under the address http://www.mvtec.com/.
Installation
Installing the MVTec HORUS demo is quite simple. Note,
that only steps 6, 7, and 8 are mandatory. So if you just want to
give MVTec HORUS a try there is no need to recompile the
kernel.
You need approx. 28 MB space on your harddisk to install MVTec HORUS.
options SYSVSHM options SYSVSEM options SYSVMSGenabled.
device meteor0 options METEOR_SYSTEM_DEFAULT=METEOR_PAL options METEOR_ALLOC_PAGES="433"The system default to choose (PAL/NTSC) depends on your local TV standard.
The correct number of pages to allocate is computed the following way:
largest width to grab: 768 pixel (PAL) largest height to grab: 576 pixel (PAL) max. byte per pixel: 4 (RGB_24) size of page (byte): 4096If you want to grab PAL signals in full resolution the correct number of pages to allocate is (768*576*4/4096)+1 = 433. If you don't have enough memory or intend to grab smaller images only you may decrease this value.
hdevelop is capable of grabbing full, half and quarter resolution of PAL or NTSC signals in RGB_24 or YUV_16. See the help pages for 'query_framegrabber' etc. for more info. Then do a 'cd /dev; ./MAKEDEV meteor0'.
The Matrox Meteor framegrabber won't work with Pentium Pro boards using the Intel Natoma chipset revision 1. This is due to a bug in the Natoma chipset. There is no software workaround.
device qcam0 at isa? port "IO_LPT1" conflicts flags 1to the kernel configuration. Then do a 'cd /dev; ./MAKEDEV qcam0'.
Please note that the QuikCam code in hdevelop is untested. (Since we don't own a QuickCam, we programed it from the specs only ...)
#HAVE_FPU= yesFinally do
cd /usr/src/lib/msun make depend make all make installThe new math library is now in place and ready to be used.
cd /usr/local tar xvf {path to HORUS demo archive}/horusdemo.tar.gzThe tar file should have created the directories
horus/README horus/app-defaults horus/bin horus/doc -> doc_english horus/doc_english horus/examples horus/help horus/images horus/filter
setenv HORUSROOT /usr/local/horusThe HORUSROOT variable points to the root directory of the MVTec HORUS installation. Setting it is mandatory.
setenv HORUSIMAGES /usr/local/horus/imagesThe HORUSIMAGES variable points to a directory hierarchy containing images you intend to use with MVTec HORUS. This way, images can be loaded without stating the absolute directory path. Of course, even with the use of HORUSIMAGES it is still possible to load images via their absolute path. HORUSIMAGES is optional.
Put these variables in your .login or .profile
#! /bin/sh # do not list LS-R rm LS-R # follow symlinks find * -type f -follow -print | sort > LS-Rhdevelop reads the contents of LS-R to locate images on disk.
If you use Accelerated-X (like we do), a
[SETTINGS] BackingStore = YES;in /etc/Xaccel.ini is sufficient. Restart the X-Server afterwards.
Hdevelop is a highly interactive programming environment faciliating the rapid prototyping of typical image analysis and machine vision applications.
Hinspector is an interactive visualization environment
fully integrated into hdevelop allowing all the
analysis of two-dimensional data (images and segmentation
results) in order to determine parameters of operators rapidly.
Hdevelop
Hdevelop is the main tool to work with. When started,
it presents three windows: The "HORUS develop" window, the
"Variables" window and the "Graphics Window" window.
The "HORUS develop" window
This is the main window. Here you create, run, and debug
all programs written in hdevelop. At the top row of the window you
should see the following menu entries:
The last area holds the parameters of the selected operator. If
no operator is selected, this area is empty.
The "Variables" window
This window is used to inspect the numerical and iconic variables
that are currently used by the program. In the top row to the
right the iconic variables are displayed. Click on a variable to
display it in the Graphics window. Do not drag and drop (middle
button) variables to the Graphics window: That code is currently
broken in the FreeBSD port, sorry. In the lower variable area,
numerical variables are displayed.
To the left of the variable window, four icons are displayed:
At the top of the window there are four buttons:
We're still working on further information for this chapter,
sorry. The documentation will be published on the Web, as soon
as it is finished.
The "HORUS Display Manager"
window
We're still working on further information for this chapter,
sorry. The documentation will be published on the Web, as soon
as it is finished.
Examples
In this chapter a few of the hdevelop examples provided
with this demo are explained. It is not possible to cover all of
them in detail but it is straightforward to load the programs and
view the operators' help texts.
diff_seq.dev
This program does simple image sequence processing: The aim is to
detect movements. To do this, two succeding images of the sequence
are subtracted and the resulting image is postprocessed by
suitable operators (e.g. texture operators like laws
followed by a threshold would work too). The result is
satisfying. However, this approach only works for constant
illumination.
eyes.dev
The aim of this program is finding the eyes of a
mandrill. Actually, this task could also be done with only three
MVTec HORUS operators:
01 read_image (Image, 'monkey') 02 threshold__ (Image, Region, 128, 255) 03 connection (Region, ConnectedRegions) 04 select_shape(ConnectedRegions, SelectedRegions, ['area','anisometry'], 'and', [500,1], [50000,1.7])The example mainly intends to teach loop programming in hdevelop (In hdevelop loops are seldom needed. There are better solutions in nearly all cases imaginable).
The program looks like this (line numbers added for reading convenience):
01 dev_close_window () 02 read_image (Image, 'monkey') 03 get_image_pointer__ (Image, Pointer, Type, Width, Height) 04 dev_open_window (0, 0, Width, Height, 'black', WindowID) 05 dev_set_draw ('fill') 06 dev_set_part (0, 0, Height-1, Width-1) 07 threshold__ (Image, Region, 128, 255) 08 dev_set_color ('white') 09 connection (Region, ConnectedRegions) 10 select_shape (ConnectedRegions, SelectedRegions, 'anisometry', 'and', 1.0, 1.7) 11 Number := |SelectedRegions| 12 Eyes := [] 13 for i := 1 to Number by 1 14 ObjectSelected := SelectedRegions[i] 15 area_center (ObjectSelected, Area, Row, Column) 16 excentricity (ObjectSelected, Anisometry, Bulkiness, StructureFactor) 17 dev_set_color ('green') 18 if ((Area > 500) and (Area < 50000)) 19 dev_set_color ('red') 20 Eyes := [ObjectSelected,Eyes] 21 endif 22 endfor 23 dev_display (Image) 24 dev_set_color ('red') 25 dev_display (Eyes)The steps in detail:
01 dev_close_window () 02 read_image (Image, 'ic') 03 get_image_pointer__ (Image, Pointer, Type, Width, Height) 04 dev_open_window (0, 0, Width, Height, 'black', WindowID) 05 dev_set_draw ('fill') 06 dev_set_part (0, 0, Height-1, Width-1) 07 dev_display (Image) 08 dev_set_colored (12) 09 decompose3 (Image, Red, Green, Blue) 10 trans_from_rgb (Red, Green, Blue, Hue, Saturation, Intensity, 'hsv') 11 threshold__ (Saturation, Colored, 100, 255) 12 reduce_domain (Hue, Colored, HueColored) 13 threshold__ (HueColored, Red, 10, 19) 14 connection (Red, RedConnect) 15 select_shape (RedConnect, RedLarge, 'area', 'and', 150.000000, 99999.000000) 16 shape_trans (RedLarge, Resistors, 'rectangle2') 17 threshold__ (HueColored, Blue, 114, 137) 18 connection (Blue, BlueConnect) 19 select_shape (BlueConnect, BlueLarge, 'area', 'and', 150.000000, 99999.000000) 20 shape_trans (BlueLarge, Capacitors, 'rectangle2') 21 threshold__ (Intensity, Dark, 0, 50) 22 dilation_rectangle1 (Dark, DarkDilation, 14, 14) 23 connection (DarkDilation, ICLarge) 24 add_channels (ICLarge, Intensity, ICLargeGray) 25 threshold__ (ICLargeGray, ICDark, 0, 50) 26 shape_trans (ICDark, IC, 'rectangle2') 27 dilation_rectangle1 (IC, ICDilation, 5, 1) 28 difference (ICDilation, IC, SearchSpace) 29 dilation_rectangle1 (SearchSpace, SearchSpaceDilation, 14, 1) 30 union1 (SearchSpaceDilation, SearchSpaceUnion) 31 reduce_domain (Intensity, SearchSpaceUnion, SearchGray) 32 mean__ (SearchGray, SearchMean, 15, 15) 33 dyn_threshold__ (SearchGray, SearchMean, PinsRaw, 5.000000, 'light') 34 connection (PinsRaw, PinsConnect) 35 fill_up (PinsConnect, PinsFilled) 36 select_shape (PinsFilled, Pins, 'area', 'and', 10, 100) 37 dev_display (Image) 38 dev_set_draw ('margin') 39 dev_set_line_width (3) 40 dev_set_color ('red') 41 dev_display (IC) 42 dev_set_color ('green') 43 dev_display (Resistors) 44 dev_set_color ('blue') 45 dev_display (Capacitors) 46 dev_set_color ('yellow') 47 dev_display (Pins)First, any leftover graphics windows are closed, then the color image is read and displayed in a new graphics window with the right size (lines 1-8). In lines 5 and 8, some output mode initialization is done. Then the RGB image is decomposed into its R, G, and B channels (lines 9). It is easiest to detect resistors and capacitors by color (reddish and blueish). The channels are therefore transformed into HSI coding (Hue, Saturation, Intensity). That way, a classification by color is much simpler than in RGB, if the colors are not pure. Colored objects (i.e. high saturation) are detected (line 11) and distinguished in red and blue objects (lines 13 and 17). After a little postprocessing to filter artifacts (lines 15 and 19), the resistors (variable Resistors) and capacitors (variable Capacitors) are identified correctly.
The chips are the darkest patches of the image, so a simple threshold (line 21) should yield good results. Problems arise, if the chip area is not homogenous enough. Therefore the threshold result is morphologically enlarged (line 22), split into connection components (line 23) and thresholded again (line 25). The result are several logical regions, each of which consist of one or more physical regions - you can best verify this with by observing variable ICDark in 12 color mode (enabled via the "Graphics window"/"Parameters" menu. The surrounding rectangles (line 26) of the logical regions match the chips exactly.
Finally the chip pins have to be detected. Since they are in the direct vicinity of the chips, the search space is limited to the areas a few pixels to the left and right of the chips. This search space is computed by morphological operators using the detected chip regions (lines 27 to 30). Since the greyvalue of the pins is not very stable, it can't be used as a feature. However, the greyvalue differences between neighbouring pixels can be used (line 33). Finally the artifacts are filtered (lines 34 to 36) and the pins are identified (variable Pins).
Finally the results are displayed in lines 37 to 47.
marks.dev
Here the goal is to detect the marks on the walking person. The
algorithm is similar to the examples above. A very powerful
operator in this example is fill_interlaced__. This
operator is needed, if image sequences with large interlacing
effects are processed. fill_interlaced__ filters these
effects, resulting in a smooth image for further processing.
meteor_grab.dev
This is a minimalist framegrabber application: The program opens
a Meteor grabber and displays the grabbed images in an infinite
loop.
particles.dev
In this program, blood cells have to be counted. This is quite
difficult, because there are large artifacts in the image and
the image itself is very noisy. Nevertheless, the solution in
hdevelop takes only a few lines of code.
stamps.dev
This little program shows how easy programming in
hdevelop is and how powerful five lines of code can be:
The program recognizes stamps in a stamp catalogue. The algorithm
is as follows: Stamps are darker than the background (white page),
therefore white is mapped out. And stamps are larger than letters,
therefore all the small regions are mapped out. The leftover
objects are the stamps (variable Stamps).
vessel.dev
This program requires a little interaction: It tries to distiguish
the inside of a capillary tube from its outside. Since the image
is very bad, some user support is needed. First, the texture is
enhanced with a texture filter (laws_byte), then the user
is asked to mark the inside and outside with a polygon (set points
with the left mouse button, close the polygon with the right mouse
button). From the mean greyvalues, a suitable threshold boundary
is computed and the capillary borders are found (variable
Vessel).
arithmetic.dev
The rest of the examples shows some capabilities of
hdevelop, that are sometimes needed but are not related
to actual image processing. Error messages that may occur in
these examples are intended!
This program provides some mathematical operators to demonstrate
the mathematical capabilities of hdevelop. Basically
all the operators from the C math library can be used. Step
through the example program and watch the variables-window. As
you see, hdevelop can do simple arithmetics, vector
arithmetics and string processing. On errors, hdevelop
provides you with warnings.
comparisons.dev
By stepping through this example, you can see the results
of several comparisons in the variables-window.
sine.dev
Plots a sine curve in the graphics-window.
string.dev
The last example: Shows some string formating. Watch the
variables-window: The format options are the same as in the C
printf function.
Known Bugs
Please bear in mind that this version of MVTec HORUS is
our first port to FreeBSD. The main development platforms of
MVTec HORUS are HP/UX and Solaris, so there may still
be some flaws in the code (notably because of the BSD vs. SysV
differences and the different Motif versions: FreeBSD is our
only platform running Motif 2.0 - The code is well tested on 1.2
but 2.0 seems to be something totally different). However, we
continue our work on the BSD port and plan to release bugfix
updates over the Net (see
below).
The Bugs:
Generally: Avoid Drag and Drop at this stage of the port. Motif 2.0 seems to have some incompatibilities to 1.2. Use clicks/double clicks/etc. instead. Sorry for the inconvenience.
static_routes="loopback" route_loopback="${hostname} localhost"in the /etc/sysconfig networking section seems to cure this problem (further testing needed).
MVTec HORUS is tested to run on the following hard- and
software platforms:
SUN Sparc (SunOS and Solaris), SUN Sparc
Ultra (Solaris), HP 9000 (HP/UX 9.*, 10.*) Silicon Graphics
(Irix), ALPHA (OSF/1), Intel x86 (FreeBSD, Linux), IBM RS6000
(AIX), and others (upon request). The MVTec HORUS also
run on Windows NT. A port of the interactive MVTec tools is on
its way.
MVTec HORUS is developed and sold by MVTec Software GmbH:
MVTec Software GmbH
Orleansstraße 34
D-81667 München
Germany - Deutschland
++49 - (89) - 48095 291
++49 - (89) - 48095 292
General: mvtec@mvtec.com
Sales: sales@mvtec.com
Technical Support: support@mvtec.com
For FreeBSD related bug reports and questions (but only those, please) send a mail to Walter Hafner. I did the FreeBSD port, but I am only marginally involved in the further MVTec HORUS development otherwise.