Google
 

10/21/07

Calling Matlab functions from C++

It is very useful to call matlab functions from C++. For example, I can use C++ to do most of the calculations, and just use matlab functions to plot the results, or I can use Matlab to do some matrix manipulations. Here I illustrate how to do that under linux.

1. Matlab7.4.0 (2007a) must be installed.

2. MUST have gcc-4.1.1 compiler. It seems that gcc-4.1.2 doesn't work. Check here for the supported compilers. If your system doesn't have the right compiler, install one first. See the following tips for installing the compiler.

3. Check whether your system has csh or not. If you don't have it, install it.

4. In your .bashrc file, define the LD_LIBRARY_PATH
LD_LIBRARY_PATH=/home/xxx/program/matlab74/bin/glnx86:/home/
xxx/program/matlab74/sys/os/glnx86/:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH

Also make sure that Matlab is in your path.
export PATH=/home/xxx/program/matlab74/bin/:$PATH
Note: Matlab is installed in /home/xxx/program/matlab74/ directory. You need to change according to your system.

5. Following the procedures in the matlab document. Compiling and Linking MATLAB Engine Programs . If everything works fine, this should give executable file "engdemo". Inside matlab if you want to run this you should use !./engdemo instead of the !engdemo.

6. Now you can also use the following to compile the "engdemo.c" in the linux console instead of inside matlab.
g++ -o engdemo engdemo.c -I
/home/xxx/program/matlab74/extern/include/ -L
/home/xxx/program/matlab74/bin/glnx86/ -leng -lm

Pay attention to the include path, and the lib path. Also there is the flag -leng.

Now you should be able to use the Matlab engine to call Matlab functions from c++. If you have some errors such as "matlab engine can not start" the chance is your compiler version is not the same one as matlab is built. You should use the exact same compiler as Matlab requests.
Here are some hints about setting up the right compiler.

Compiling and linking made difficult

Let's suppose we wanted to create an efficient MATLAB routine that calculates the height of the Normal probability density function (pdf) at a given point on the line. That there are at least five gazillion MATLAB implementations that already calculate this quantity is beside the point. (Normally, when you decide to write a MATLAB routine in C++, you should make sure it is worth your while!)

Before we embark on the actual C++ coding, we need to examine how MATLAB creates a MEX File. The exact procedure is system-dependent, so what I describe here may differ slightly from your setup. At school I have access to a machine installed with the Linux operating system, and I have my own Apple computer with Mac OS X. Both these operating systems are Unix-like, hence their differences will be rather cosmetic.

In order to build MEX files, we need to make sure that we have the proper compiler installed on our system. On my Linux machine, I'm using MATLAB 7.3 (R2006b), and according to MathWorks product support it was built with the GNU Compiler Collection (GCC) 3.4.5. Unfortunately, I did not have this particular version of the compiler installed on my system. Different versions of the same compiler are effectively different compilers, as they follow different conventions. You should never link libraries or object code unless they are compiled in the same way. I downloaded the GCC source from my local university FTP mirror and built the entire package on my system. GCC includes compilers for many different languages, and they can be found in the bin subdirectory of the GCC software installation. MATLAB uses three of them: the C compiler gcc, the C++ compiler g++, and the Fortran 77 compiler g77. When installing GCC, it is a bad idea to blindly follow the default installation as it may overwrite the existing compilers. You should install it in a new directory. Afterward, to make things simpler, I created a symbolic link to each of the compilers like so:

  cd /usr/bin
ln -s gcc-install-path/bin/gcc gcc-3.4.5

Then I did the same thing for the other two compilers. Since /usr/bin is in the path (see the environment variable PATH), I can call the program anywhere I am simply by typing gcc-3.4.5. By including the version number in the symbolic link, I avoid calling version 3.4.5 of gcc unless I really want to.

10/20/07

Tutorial on MATLAB executables (MEX files)

Tutorial on MATLAB executables (MEX files)

How to Compile MATLAB C++ Math Library

How to Compile MATLAB C++ Math Library

How to Compile MATLAB C++ Math Library

by Munehiro Nakazato

RedPin Who need this?

  • (Scenario 1) If you need to write complicated matrix operations in C/C++
    You can save your time by using MATLAB Math Library.

  • (Scenario 2) If you want to call your own MATLAB functions from C/C++
    MATLAB compiler translates them into C++ codes.

  • (Scenario 3) If you need a speed boost of your MATLAB function or M-files
    You can use MATLAB compiler to translate your M-files into MEX-files which you can call from Matlab.
  • RedPin Manuals

    The manuals are available from MathWorks.
    Example codes are available in
    /usr/local/matlab6_R12/extern/examples/cppmath

    RedPin To Begin

    You need add specific library to your LD_LIBRARY_PATH

    Solaris: /usr/local/matlab6_12/extern/lib/sol2
    SGI 64 (such as guinan): /usr/local/matlab5.3.1/extern/lib/sgi64

    Example:

    # setenv LD_LIBRARY_PATH "/usr/local/matlab6_12/extern/lib/sol2:$LD_LIBRARY_PATH"

    RedPin Use MBUILD - the easiest way

    The easiest way to compile the code is mbuild tool

    When you run mbuild for the first time, I recommend you to setup mbuild

    # /usr/local/matlab6_R12/bin/mbuild -setup

    Then,

    # /usr/local/matlab6_R12/bin/mbuild ex1.cpp

    That's it !! It's very easy, isn't it?

    For Windows

    mbuild is in [matlab]\bin\mbuild, where [matlab] is the location of MATLAB instllation.

    RedPin Manual Compile

    For some situation, mbuild may not work well. In this case, you have to manually compile as shown below. The order to specify libraries is important.

    For Solaris

    As long as I know, MATLAB Math Library works only with Sun's C++ compilers (CC). It causes error with GNU C++ (g++)
    # CC -DSOL2 -DUNIX -DX11 -DNDEBUG -O3 +d ex1.cpp \
    -I/usr/local/matlab6_R12/extern/include/cpp \
    -I/usr/local/matlab6_R12/extern/include -L/usr/local/matlab6_R12/extern/lib/sol2 \
    -lmatpp -lmmfile -lmatlb -lmat -lmx -lnsl -lm

    For SGI 64 (guinan)

    # CC -64 -LANG:bool -DCOMPILER_HAS_BOOL ex1.cpp \
    -I/usr/local/matlab5.3.1/extern/include/cpp \
    -I/usr/local/matlab5.3.1/extern/include \
    -L/usr/local/matlab5.3.1/extern/lib/sgi64 \
    -lmatpp -lmmfile -lmcc -lmatlb -lmat -lmx -lm

    RedPin NOTE

    The directories in this documentation are specific to IFP Lab Workstations in Beckman Institute. You will need to change the file locations depending on your environment. Ask your System Administrator.

    10/8/07

    Ubuntu install matlab 2007.

    Have the following errors:

    -------------------------------------------------------------------

    An error status was returned by the program 'xsetup',
    the X Window System version of 'install'. The following
    messages were written to standard error:

    /data/matlab/update/install/main.sh: 168: /data/matlab/update/bin/glnx86/xsetup: Permission denied

    Attempt to fix the problem and try again. If X is not available
    or 'xsetup' cannot be made to work then try the terminal
    version of 'install' using the command:

    install* -t or INSTALL* -t

    -------------------------------------------------------------------

    Sorry! Setup aborted . . .

    To solve it:
    1. umount /cdrom
    2. mount -t iso9660 /dev/cdrom /cdrom
    3. /cdrom/install
    Now it will start. I don't know how to install matlab if I copy all the files to the hard disk.

    10/6/07

    Compile Qt with OpenGL support.

    When compile the source, make sure use the following to include opengl

    ./configure -opengl

    python problem.

    python configure.py
    from the latest PyQt4 snapshot, I got the following error message:
    Error: Failed to create ./qtdirs using platform linux-g++. Make sure your
    compiler is installed correctly and you have a working make on your PATH.

    use the following to solve problem.
    ln -s /usr/local/Trolltech/Qt.xx/bin/qmake /usr/bin/qmake

    export QTDIR = /usr/local/Trolltech/Qt.xxx/

    LIBS

    LIBS += -L/usr/local/lib/ -lqwtplot
    There is no space between L and /usr/local/lib.

    Enable and Disable Ubuntu Root Password -- Debian Admin

    Enable and Disable Ubuntu Root Password -- Debian Admin

    sudo” means superuser do. “sudo” will prompt for “Password:”. Please specify user password

    As you have noticed during the Ubuntu installation there was no question about the root password, as you might have been used to see during other Linux distribution installation process.Because of this your root accout is inactive.

    If you want to enable root account (which is not recommended) enter the following command.

    $sudo passwd root

    This will prompt for a new root password and once you confirm it, you can start using the root account to login.

    If you want to disable root account in ubuntu you need to lock the root account by using the following command

    $sudo passwd -l root

    If you want to work on a root console you’d better use the following command

    $sudo -i

    9/22/07

    VPN configuration.

    I have tried kvpnc. It is very nice and easy to use. It supports different vpn programs, such as cisco, openvpn etc.

    8/23/07

    C++ Naming Standards (DRAFT)

    It is helpful to use the name convention consistently when you write the program. In this site I got the following "standard". I think it is very useful so I copy it here.


    The following standards are intended to provide guidance for development of names defined within C++ programs developed by the IHFS project. The standards are derived from the C++ Coding Standards developed by the European Laboratory for Particle Physics (CERN) which can be found at http://axaonl.cern.ch:8000/a_doc$www/ONLINE/CXX_CODING_STANDARDS.HTML#names

    All Upper Case Abbreviations

    All upper case abbreviations are acceptable when the abbreviation is well known and in common use. e.g. - RFC

    Class Names

    Use upper case letters as word separators, lower case for the rest of a word First character in a name is upper case No underscores '_'

    Class Library Names

    Until Namespaces are widely implemented in C++, libraries in danger of conflicting with other libraries should choose some sort of unique prefix to avoid name conflicts. It's common for a prefix to be two characters, but a longer length is acceptable.

    Method Names

    Use the same rule as for class names.

    Class Attribute Names

    Use lower case attribute names Separate keywords with underscores '_'

    Method Argument Names

    The first character should be lower case. All words beginning after the first letter should be upper case as with class names.

    Variable Names on the Stack

    use all lower case letters use underscore '_' as the word separator.

    Pointer Variables

    Pointers should be prefixed by a 'ptr' Place the * close to the pointer type not the variable name

    Reference Variables

    References should be prefixed with 'ref'

    Global Variables

    Global variables should be prefixed with 'glo'.

    Static Variables

    Static variables should be prefixed with 'sta'

    Type Names

    When possible, make a typedef for types based on builtin types. Typedef names should use the same naming policy as for a class with the word Type appended.

    C Function Names

    In a C++ project there should be very few C functions. For C functions use the GNU convention of all lower case letters with '_' as the word delimiter.

    Enum Names

    Labels All Upper Case with '_' Word Separators

    8/20/07

    Install Chinese fonts on ubuntu (feisty).

    1. Need to use "System Settings", then select "Regional and Language" to choose the language.
    2. sudo dpkg-reconfigure locales

    8/12/07

    firefox crashes.

    It always crashes when I logged into my gmail account. It turned out that it is due to the plugin "flashplayer". When I entered the home directory,
    cd ./mozilla
    cd firefox
    cd plugins
    I just deleted the libflash*.o
    Now firefox works.

    Install Qt4.3

    I had the following error:

    In file included from kernel/qpsprinter.cpp:97:
    kernel/qt_x11.h:65:22: X11/Xlib.h: No such file or
    directory
    kernel/qt_x11.h:71:23: X11/Xutil.h: No such file or
    directory
    kernel/qt_x11.h:72:21: X11/Xos.h: No such file or
    directory
    kernel/qt_x11.h:73:23: X11/Xatom.h: No such file or
    directory
    kernel/qt_x11.h:84:34: X11/extensions/shape.h: No such
    file or directory

    Solved by following:
    installed "xlibs-dev" package

    8/6/07

    ubuntu boot up message.

    I could not see any message when the computer starts up. The solution is to press: Ctrl+Alt+F1

    8/4/07

    fstab and User permission.

    User Permissions

    To give read/write permission to everyone, add this phrase to the options for the file_system in your file /etc/fstab:

    "gid=users,umask=000"

    You need to have root access to edit that file. The whole line will look something like this:

    /dev/hdxy   /mnt/hdxy  file_system  noatime,user,exec,dev,suid,gid=users,umask=000  0  0
    • x will be a letter starting with a, then b,c,....
    • y will be a number starting with 1, then 2,3,....

    File types:

    • Linux file systems:
      • ext2, ext3, jfs, reiserfs, reiser4, xfs, swap.
    • Windows:
      • vfat = FAT 32, FAT 16
      • ntfs= NTFS

    Additional Options: (From wiki.linuxquestions.org):

    • sync/async - All I/O to the file system should be done (a)synchronously.
    • auto - The filesystem can be mounted automatically (at bootup, or when mount is passed the -a option). This is really unnecessary as this is the default action of mount -a anyway.
    • noauto - The filesystem will NOT be automatically mounted at startup, or when mount passed -a. You must explicitly mount the filesystem.
    • dev/nodev - Permit any user to mount the filesystem. This automatically implies noexec
    • exec / noexec - Permit/Prevent the execution of binaries from the filesystem.
    • suid/nosuid - Permit/Block the operation of suid, and sgid bits.
    • ro - Mount read-only.
    • rw - Mount read-write.
    • user - Permit any user to mount the filesystem. This automatically implies noexec, nosuid,nodev unless overridden.
    • nouser - Only permit root to mount the filesystem. This is also a default setting.
    • defaults - Use default settings. Equivalent to rw, suid, dev, exec, auto, nouser, async.
    • _netdev - this is a network device, mount it after bringing up the network. Only valid with fstype nfs.

    The "umask" is "user mask" and it sets the permission bits for permission that is not allowed if you wish to change the default.

    VFAT/NTFS:

    Syntax is "odd" at first.

    • To set a permissions of 777, umask=000
    • to set permissions of 700, umask=077
      • o= Sets owner. Syntax: must use owned by USER ID # not name.
      • g= sets group ownership of mount point. Again syntax is by GROUP ID # not name.

    022 means everything is allowed for root, writing/executing are allowed for group and world.


    Following is my /etc/fstab file.

    # /etc/fstab: static file system information.
    #
    #
    proc /proc proc defaults 0 0
    /dev/sda6 / ext3 defaults,errors=remount-ro 0 1
    /dev/sdb1 /backup ext3 rw,uid=1000,gid=1000 0 2
    /dev/sda5 /data vfat rw,noatime,uid=1000,gid=1000,user 0 0
    /dev/sda12 /home ext3 defaults 0 2
    /dev/sda10 /tmp ext3 defaults 0 2
    /dev/sda7 /usr ext3 defaults 0 2
    /dev/sda8 /usr/local ext3 defaults 0 2
    /dev/sda9 /var ext3 defaults 0 2
    #/dev/sdb2 /win vfat rw,user,auto,umask=000 0 0
    /dev/sdb2 /win vfat rw,user,auto,uid=1000,gid=1000 0 0
    /dev/sda1 /windows vfat defaults 0 0
    /dev/sda11 none swap sw 0 0
    /dev/scd0 /media/cdrom0 udf,iso9660 user,noauto 0 0
    /dev/fd0 /media/floppy0 auto rw,user,noauto 0 0


    7/18/07

    Install source navigator failed.

    I tried to install this program, but had very hard time. At the beginning the computer complaining that it can not find the tcl script file. This part is solved by:

    configure --help
    There is an option --withtclconfig, use this option as: --withtclconfig=/usr/lib/tcl8.4/
    This is solved. But when I use "make" to compile the program, it says no rules to xxx libdb.a. I have libdb.a in my /usr/lib/ though.

    Anyway, I don't want to spend more time on this stupid program any more.

    6/8/07

    compile cpp with opencv.

    In order to use opencv, when you compile the program you need to use the following:
    g++ `pkg-config --cflags opencv` -o test test.cpp `pkg-config --libs opencv`
    Or you can execute the commands to get the parameters used.
    > pkg-config --cflags opencv
    -I/usr/local/include/opencv
    > pkg-config --libs opencv
    -L/usr/local/lib -lcxcore -lcv -lhighgui -lcvaux -lml
    Now you can use something similar to the following:
    > g++ -I/usr/local/include/opencv -o test opencv_test.cpp -L/usr/local/lib/ -lcxcore -lhighgui -lm

    5/19/07

    Adding extra fonts.

    Adding Extra Fonts

    The fonts that come with X are quite limited. You may want to install the msttcorefonts package to provide Microsoft TrueType core fonts for use in X.

    To install them, run

    apt-get install msttcorefonts

    at the command line as root. If you get an error

    E: Couldn't find package msttcorefonts

    you may need to edit your /etc/apt/sources.list to include the contrib section in your source entry.

    5/16/07

    Install and use dislin under linuxe (debian).

    1. Download and install the library according to the README file.
    2. Copy /usr/local/dislin/dislin.h to /usr/local/include/
    3. Copy /usr/local/dislin/libdislin.a to /usr/local/lib/
    Now it should work using the following options when compile the program.
    > g++ test.cpp -lXt -ldislin -lm
    Don't forget the -lXt

    Another option is:
    > g++ test.cpp /usr/local/dislin/lib/dislin-9.1.a -lm -L/usr/X11R6/lib -lXt

    I assumed in the above example that dislin is installed in: /usr/local/dislin/. There is no need to change /etc/profile or set the envionment varibles as the README suggested. Here is a very useful link:

    http://people.scs.fsu.edu/~burkardt/cpp_src/dislin/dislin.html


    Use dislin:
    //
    // Specify the format of the output file.
    //
    // metafl ( "PNG" ); //if want to save as png file
    metafl("XWIN"); //this just show the graph on screen
    //
    // Specify the name of the output graphics file.
    //
    // setfil ( "dislin_ex01.png" ); //only when you want to save the figure.

    disini ( );
    pagera ( );
    complx ( );
    axspos ( 450, 1800 );
    axslen ( 2200, 1200 );

    name ( "X-axis", "x" );
    name ( "Y-axis", "y" );

    labdig ( -1, "x" );
    ticks ( 10, "xy" );

    titlin ( "Demonstration of CURVE", 1 );
    titlin ( "SIN(X), COS(X)", 3 );

    graf ( 0.0, 360.0, 0.0, 90.0, -1.0, 1.0, -1.0, 0.5 );
    title ( );

    color ( "red" );
    curve ( xray, y1ray, N ); //This is the data transfer part.

    color ( "green" );
    curve ( xray, y2ray, N );

    color ( "fore" );
    dash ( );
    xaxgit ( );

    disfin ( );

    5/13/07

    Make movie using imagemagick.

    Command-line animations using ImageMagick

    Tuesday July 12, 2005 (09:01 AM GMT)
    By: Shashank Sharma

    Printer-friendly Email story

    If the success of the "Shrek," "Toy Story," "Stuart Little," "The Incredibles," and many other Hollywood hits is any indication, animations add glitz to the mundane. While animation in the movies still requires professional animation packages like Blender, you can make simple animations using the command-line wizardry of ImageMagick.

    There are three basic steps to making an animation. First you need an idea. Next, you need a set of images to run through in individual frames. You can get the images from your digital camera or your scanner or draw them using ImageMagick or the GIMP. Once you have these ready, all you need to do is to put them together into an animation.

    Your first animation

    A basic animation could just run through several images. You can do this easily using the animate command:

    animate image1.gif image2.gif image3.gif

    Basic Animation
    A basic animation

    IM displays the images in the order they are listed. Since animate does not save animations, its use is limited to testing. This animation will quickly blur through all the three GIF files.

    If you need to pause on an image before moving to the next one, use the -delay switch. It sets the time pause between images in units of 100th of a second:

    animate -delay 200 frame1.gif frame2.gif frame3.gif

    This sequence of images will spend two seconds on each image. But this command runs the animation just once. It's left to the -loop switch to determine the number of times an animation is to cycle through the frames:

    animate -delay 300 frame1.gif frame2.gif frame3.gif -loop 3

    This loops the animation three times. -loop 0 loops the animation infinitely.

    Placing images

    To save an animation we use the convert command, supplying a filename with an appropriate extension. Use .gif if you want to use your animation on a Web site, or use .mpeg and .avi if you want these to play on a media player.

    convert -delay 30 frame1.gif frame2.gif frame3.gif \
    > -loop 0 playme.gif

    This results in an animation, playme.gif, made up of three images looping infinitely.

    The animations we have creating so far adjust their size depending upon the size of the constituent images. This can cause havoc if you use them within Web pages. We need to specify a canvas on which to lay out our animation and its constituent images. Let's use a big canvas and place the same image onto it at different places:

    convert -delay 0 -size 100x100 xc:green \
    > -delay 50 -page +32+62 ball.gif -page +2+35 ball.gif \
    > -delay 10 -page +31+2 ball.gif -page +62+32 ball.gif \
    > -loop 0 anim.gif

    The -page switch places the images at the specified locations. We have also used -delay with every image to set its own pause time.

    You can also use the -pause switch to supply the time delay between animation loops:

    convert -delay 0 -size 100x100 xc:green \
    > -delay 50 -page +32+62 ball.gif -page +2+35 ball.gif \
    > -delay 10 -page +31+2 ball.gif -page +62+32 ball.gif \
    > -loop 0 -pause 3 anim.gif

    The anim.gif image is a green canvas of 100x100 pixels, within which the same image is displayed at multiple locations, each for a specified time, and the sequence repeats after three seconds.

    Note that in this animation, new images appear alongside other images. If you want the previous image to disappear before the new one arrives on a clean canvas, use the -dispose switch. It controls the way an image should to be treated after being displayed:

    convert -dispose none -delay 0 base.gif \
    > -dispose previous -delay 100 \
    > -page +32+62 ball.gif -page +2+35 ball.gif \
    > -page +31+2 ball.gif -page +62+32 ball.gif \
    > -loop 0 animation.gif

    An animation made with the dispose previous switch
    An animation made with the dispose previous switch

    The most important option of dispose is previous. In an animation, the images before dispose previous become the base image, and the animation returns to this base image after each image is displayed. The dispose in the base image in the example above is thus set to zero. So, base.gif becomes the base image, and the animation returns to it after displaying each image in the sequence. So, the effective order of the animation is: base.gif->big.gif->base.gif->ball.gif->base.gif->c ircle.gif, and so on.

    Using convert you can also combine two animations into one file:

    convert animation.gif anim.gif combined_anim.gif

    This combines the first two GIF files into the last animation in the listed sequence.

    Conclusion

    ImageMagick is a robust command-line utility capable of doing simple image manipulations like cropping images and changing image formats to drawing various shapes, mosaics, and 3D images to creating animations.

    You can create some interesting animations using the commands in this article. You could animate trees swaying in the winds, create ripples in a pond, show cloud movement through the sky, or lip-sync yourself to "Hasta la vista, baby."

    Shashank Sharma is a computer science student who loves to write about free and open source software for new users.

    Slashdot Slashdot it!

    5/12/07

    mtl problem.

    in the install file, it is said it is not necessary to install. But it turn out there is something tricky. I just copied the mtl folder to the /usr/local/include, and it doesn't work. The computer complained that std::enum etc. has multiple defination. After I recompile the mtl from source, the problem solved. I don't know exactly what it did when I compile mtl.
    I did the following:
    1. untar/unzip the file.
    2. cd mtl
    3. ./configure
    4. su to root
    5. make install
    That is it. And the problem solved. There is something stupid MTL did. I will finally get rid of mtl from my program. It is not a very good library, at least for my code. I will use uBlast or TNT instead.

    5/10/07

    Function Objects in C++

    Frequently we need to treat a function as a first class object in C++. One place these are frequently needed is in numerical methods code. For example a numerical integrator needs to somehow be handed a function to integrate. Some languages do this easily: for example functional languages such as Lisp and Haskell. But C++ is a little weaker in this regard.

    Pointers to Functions

    In the old days of C the way to do this was to hand in a pointer to a function. In fact this is exactly what is used throughout Numerical Recipes in C [2]. An example in that style is the following:


    float f(float x) {
    float y = 2;
    float z = 3;
    return x*x+y*y+z*z;
    }

    int main() {
    . . .
    . . .
    integrate(&f,0,1);
    . . .
    }

    But this has some problems. What if we have a function f() of three arguments but want to integrate it along the line y=2, z=3. We need to integrate a helper function

    float f(float x,float y,float z) {
    return x*x+y*y+z*z;
    }

    float g(float x) {
    return f(x,y,z);
    }

    float y,z;

    int main() {
    . . .
    . . .
    y = 2;
    z = 3;
    integrate(&g,0,1);
    . . .
    }

    Virtual Functions

    That's a pretty ugly solution requiring a global variable. In order to lose the global variables a void * argument is added to the function to be integrated and to the integrate() function. The void * can be handed into the integrand which can dereference it to find a package containing extra arguments. A full example might look like:



    struct Data {
    float y,z;
    };

    float f(float x,void *d) {
    Data *p = (Data *)d;
    return x*x+p->y*p->y+p->z*p->z;
    }

    int main() {
    . . .
    . . .
    Data d;
    d.y = 2;
    d.z = 3;
    integrate(f,0,1,&d);
    . . .
    }

    That's pretty horrible even though it's more or less the standard in the C world! In Scheme we can simply build a function on the fly like: (lambda (x) (f x y z)). Can we do something like this in C++?

    C++ has a mechanism for handling pointers to functions that hides the fact that you are manipulating pointers to functions: virtual functions. Using these we can have our integrator function call a function whose identity isn't yet determined at runtime. Here's an example:



    class Integrand {
    public:
    float evaluate(float) = 0;
    float integrate(float x0,float x1) {
    . . .
    }
    };

    class F : public Integrand {
    float y,z;
    public:
    Integrand(float y0,float z0) : y(y0), z(z0) {
    }
    float evaluate(float x) {
    return x*x+y*y+z*z;
    }
    }

    int main() {
    . . .
    . . .
    F f(2,3);
    integrate(f,0,1);
    . . .
    }

    That's certainly much more elegant. But unfortunately it's authoritarian. It forces users of the integrate method to derive their functions from Integrand. What if you want to hand the same function to a numerical differentiator? Will you have to write the same function again, only derived from another base class? It would be nice if we could make completely generic function objects that can be used in multiple ways.

    Generic Function Objects via Templates

    The next approach is much more generic. It makes only one assumption about the function object that is passed in - that has operator() defined. (Incidentally, objects with such a method are often called functors or functoids. The latter is to be preferred as the former already has a perfectly good but quite different meaning.)


    template
    float integrate(const F &f,float x0,float x1) {
    . . .
    . . . f(x) . . .
    . . .
    }

    class F {
    float y,z;
    public:
    F(float y0,float z0) : y(y0), z(z0) { }
    float operator()(float x) const {
    return x*x+y*y+z*z;
    }
    };

    int main() {
    . . .
    . . .
    F f(2,3);
    integrate(f,0,1);
    . . .
    }
    This has many great advantages. The function object, f, can be pointer to a function: integrate(sin,0,1) would work for example Or it can be an object with operator() defined. One nice advantage over using virtual functions and function pointers is that it can use knowledge about the function object at runtime to optimise.

    What we've actually made here is what computer scientists call a closure [3]. That's an aggregate made of a function and some of its arguments. We can't yet evaluate it because we don't yet know all of its arguments, so it's in a kind of suspended animation waiting for its final arguments.

    Polymorphic Function Objects

    But there's one more thing that would make the function objects even more useful. Suppose that our integral method had a whole battery of algorithms that it could throw at an integrand. Maybe one of those methods involves evaluating the function at complex arguments. As it stands this would be impossible. F only defines operator()(float) and so can only operate on floats. We'd like to write our function in a type independent way. What springs to mind is a polymorphic function object. Unfortunately there is no way to take the address of a polymorphic function. But there is a simple modification we can make to the class F above. Here it is:


    class F {
    float y,z;
    public:
    F(float y0,float z0) : y(y0), z(z0) { }
    template
    X operator()(X x) const {
    return x*x+y*y+z*z;
    }
    };

    With the help of a template member function F is truly polymorphic. Our integration algorithm can throw any type it likes at F, as long as the methods operator() uses understand. In fact, it's even possible for the integrate function to reconstruct a symbolic representation of the function for a large class of functions by applying operator() to symbolic types that have the arithmetic operators appropriately defined. With a little extra work we can do some real functional programming and even port Haskell code [1] directly to C++..

    We have now come a long way from old-fashioned C function pointers.

    References

    [1] fc++: Functional Programming in C++
    [2] Numerical Recipes
    [3] Functions and Closures

    function object or functors.

    Defining a Function Object
    By Danny Kalev

    from the following link:
    http://www.inquiry.com/techtips/cpp_pro/10min/10min0100.asp

    Although pointers to functions are widely used for implementing function callbacks, C++ offers a significantly superior alternative to them, namely function objects. Function objects (also called "functors") are ordinary class objects that overload the () operator. Thus, syntactically, they behave like ordinary functions.

    There are several advantages in using a function object instead of a pointer to function. First, they are more resilient to design changes because the object can be modified internally without changing its external interface. A function object can also have data members that store the result of a previous call. When using ordinary functions, you need to store the result of a previous call in a global or a local static variable. However, global and local static variables have some undesirable characteristics. Finally, compilers can inline a call made through a function object, thereby enhancing performance even further. In contrast, it is nearly impossible to inline a function call made through a pointer.

    This solution will show how to define and use a function object that implements a negation operation. The first step consists of declaring an ordinary class and overloading the () operator:

    class Negate
    {
    public:
    int operator() (int n) { return -n;}
    };

    The overloaded () might look a bit confusing because it has two pairs of parentheses. Remember that the first pair is always empty because it serves as the operator's name; the parameter list appears in the second pair of parentheses. Unlike other overloaded operators, whose number of parameters is fixed, the overloaded () operator may take any number of parameters.

    Because the built-in negation operator is unary (it takes only a single operand), our overloaded () operator also takes a single parameter. The return type is identical to the parameter's type—int, in our example. The function body is trivial; it simply returns the negated argument.

    Using the Function Object
    We now define a function named Callback() to test our function object. Callback() takes two arguments: an int and a reference to Negate. Callback() treats neg, the function object, as if it were a function's name:

    #include
    using std::cout;

    void Callback(int n, Negate & neg)
    {
    int val = neg(n); //1 invoke overloaded ()
    cout << val =" neg.operator()(n);" t=""> T operator() (T t) const {return -t;}
    };

    int main()
    {
    GenericNegate negate;
    cout<<> or less<> to sort() to force a descending or ascending sorting order, respectively:

    #include // for greater<> and less<>
    #include //for sort()
    #include
    using namespace std;

    int main()
    {
    vector vi;
    //..fill vector
    sort(vi.begin(), vi.end(), greater() );//descending
    sort(vi.begin(), vi.end(), less() ); //ascending
    }



    gdb problem.

    I had gdb problem. It complained "no symbol table", something like that. I don't know exactly how I fixed it. But it seems that after I installed the following packages, it disappeared.

    libstdc++2.10-dbg
    libstdc++2.10-dev
    libstdc++5-3.3-dev
    libstdc++6-dbg
    libstdc++6-dev
    libstdc++6-4.1-dev

    then restared kdevelop, now it works! Also make sure that the -g option is in the compile options.

    check the dynamic link problem.

    when I used gnuplot, it gives some error. Use the following to check and find the reasons for the error.


    > ldd `which gnuplot`
    linux-gate.so.1 => (0xffffe000)
    libreadline.so.5 => /lib/libreadline.so.5 (0xb7ee5000)
    libncurses.so.5 => /lib/libncurses.so.5 (0xb7ea4000)
    libz.so.1 => /usr/lib/libz.so.1 (0xb7e8f000)
    libstdc++.so.5 => not found
    libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0xb7e6a000)
    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7e5f000)
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7d2e000)
    libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb7d2a000)
    /lib/ld-linux.so.2 (0xb7f31000)
    It is clear that libstdc++.so.5 not found. So need to install it.

    5/4/07

    introduction to programming with openCV

    Please note that this article is from the following link. Sometimes, the good articles on the web just disappear due to different reasons. I copy this one here just for my reference. Please refer to the original one.


    Introduction to programming with OpenCV

    Gady Agam

    Department of Computer Science

    January 27, 2006

    Illinois Institute of Technology

    Abstract:

    The purpose of this document is to get you started quickly with OpenCV without having to go through lengthy reference manuals. Once you understand these basics you will be able to consult the OpenCV manuals on a need basis.


    Contents

    Introduction

    Description of OpenCV

    • General description
      • Open source computer vision library in C/C++.
      • Optimized and intended for real-time applications.
      • OS/hardware/window-manager independent.
      • Generic image/video loading, saving, and acquisition.
      • Both low and high level API.
      • Provides interface to Intel's Integrated Performance Primitives (IPP) with processor specific optimization (Intel processors).

    • Features:
      • Image data manipulation (allocation, release, copying, setting, conversion).
      • Image and video I/O (file and camera based input, image/video file output).
      • Matrix and vector manipulation and linear algebra routines (products, solvers, eigenvalues, SVD).
      • Various dynamic data structures (lists, queues, sets, trees, graphs).
      • Basic image processing (filtering, edge detection, corner detection, sampling and interpolation, color conversion, morphological operations, histograms, image pyramids).
      • Structural analysis (connected components, contour processing, distance transform, various moments, template matching, Hough transform, polygonal approximation, line fitting, ellipse fitting, Delaunay triangulation).
      • Camera calibration (finding and tracking calibration patterns, calibration, fundamental matrix estimation, homography estimation, stereo correspondence).
      • Motion analysis (optical flow, motion segmentation, tracking).
      • Object recognition (eigen-methods, HMM).
      • Basic GUI (display image/video, keyboard and mouse handling, scroll-bars).
      • Image labeling (line, conic, polygon, text drawing)

    • OpenCV modules:
      • cv - Main OpenCV functions.
      • cvaux - Auxiliary (experimental) OpenCV functions.
      • cxcore - Data structures and linear algebra support.
      • highgui - GUI functions.

    Resources

    • Reference manuals:
      • /docs/index.htm

    • Web resources:
      • Official webpage: http://www.intel.com/technology/computing/opencv/

      • Software download: http://sourceforge.net/projects/opencvlibrary/

    • Books:
      • Open Source Computer Vision Library by Gary R. Bradski, Vadim Pisarevsky, and Jean-Yves Bouguet, Springer, 1st ed. (June, 2006).

    • Sample programs for video processing (in /samples/c/):
      • color tracking: camshiftdemo
      • point tracking: lkdemo
      • motion segmentation: motempl
      • edge detection: laplace

    • Sample programs for image processing (in /samples/c/):
      • edge detection: edge
      • segmentation: pyramid_segmentation
      • morphology: morphology
      • histogram: demhist
      • distance transform: distrans
      • ellipse fitting: fitellipse

    OpenCV naming conventions

    • Function naming conventions:
          cvActionTargetMod(...)

      Action = the core functionality (e.g. set, create)
      Target = the target image area (e.g. contour, polygon)
      Mod = optional modifiers (e.g. argument type)

    • Matrix data types:
          CV_(S|U|F)C

      S = Signed integer
      U = Unsigned integer
      F = Float

      E.g.: CV_8UC1 means an 8-bit unsigned single-channel matrix,
      CV_32FC2 means a 32-bit float matrix with two channels.

    • Image data types:
          IPL_DEPTH_(S|U|F)

      E.g.: IPL_DEPTH_8U means an 8-bit unsigned image.
      IPL_DEPTH_32F means a 32-bit float image.

    • Header files:
          #include 
      #include
      #include
      #include // unnecessary - included in cv.h

    Compilation instructions

    • Linux:
      g++ hello-world.cpp -o hello-world \
      -I /usr/local/include/opencv -L /usr/local/lib \
      -lm -lcv -lhighgui -lcvaux

    • Windows:
      In the project preferences set the path to the OpenCV header files and
      the path to the OpenCV library files.

    Example C Program

    ////////////////////////////////////////////////////////////////////////
    //
    // hello-world.cpp
    //
    // This is a simple, introductory OpenCV program. The program reads an
    // image from a file, inverts it, and displays the result.
    //
    ////////////////////////////////////////////////////////////////////////
    #include
    #include
    #include
    #include
    #include


    int main(int argc, char *argv[])
    {
    IplImage* img = 0;
    int height,width,step,channels;
    uchar *data;
    int i,j,k;

    if(argc<2){>\n\7");
    exit(0);
    }

    // load an image
    img=cvLoadImage(argv[1]);
    if(!img){
    printf("Could not load image file: %s\n",argv[1]);
    exit(0);
    }

    // get the image data
    height = img->height;
    width = img->width;
    step = img->widthStep;
    channels = img->nChannels;
    data = (uchar *)img->imageData;
    printf("Processing a %dx%d image with %d channels\n",height,width,channels);

    // create a window
    cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
    cvMoveWindow("mainWin", 100, 100);

    // invert the image
    for(i=0;i

    GUI commands

    Window management

    • Create and position a window:
        cvNamedWindow("win1", CV_WINDOW_AUTOSIZE);
      cvMoveWindow("win1", 100, 100); // offset from the UL corner of the screen

    • Load an image:
        IplImage* img=0;
      img=cvLoadImage(fileName);
      if(!img) printf("Could not load image file: %s\n",fileName);

    • Display an image:
        cvShowImage("win1",img);

      Can display a color or grayscale byte/float-image. A byte image is assumed to have values in the range $[0..255]$. A float image is assumed to have values in the range $[0..1]$. A color image is assumed to have data in BGR order.

    • Close a window:
        cvDestroyWindow("win1");

    • Resize a window:
        cvResizeWindow("win1",100,100); // new width/heigh in pixels

    Input handling

    • Handle mouse events:
      • Define a mouse handler:
          void mouseHandler(int event, int x, int y, int flags, void* param)
        {
        switch(event){
        case CV_EVENT_LBUTTONDOWN:
        if(flags & CV_EVENT_FLAG_CTRLKEY)
        printf("Left button down with CTRL pressed\n");
        break;

        case CV_EVENT_LBUTTONUP:
        printf("Left button up\n");
        break;
        }
        }

        x,y: pixel coordinates with respect to the UL corner

        event: CV_EVENT_LBUTTONDOWN, CV_EVENT_RBUTTONDOWN, CV_EVENT_MBUTTONDOWN,
        CV_EVENT_LBUTTONUP, CV_EVENT_RBUTTONUP, CV_EVENT_MBUTTONUP,
        CV_EVENT_LBUTTONDBLCLK, CV_EVENT_RBUTTONDBLCLK, CV_EVENT_MBUTTONDBLCLK,
        CV_EVENT_MOUSEMOVE:

        flags: CV_EVENT_FLAG_CTRLKEY, CV_EVENT_FLAG_SHIFTKEY, CV_EVENT_FLAG_ALTKEY,
        CV_EVENT_FLAG_LBUTTON, CV_EVENT_FLAG_RBUTTON, CV_EVENT_FLAG_MBUTTON

      • Register the handler:
          mouseParam=5;
        cvSetMouseCallback("win1",mouseHandler,&mouseParam);

    • Handle keyboard events:
      • The keyboard does not have an event handler.

      • Get keyboard input without blocking:
          int key;
        key=cvWaitKey(10); // wait 10ms for input

      • Get keyboard input with blocking:
          int key;
        key=cvWaitKey(0); // wait indefinitely for input

      • The main keyboard event loop:
          while(1){
        key=cvWaitKey(10);
        if(key==27) break;

        switch(key){
        case 'h':
        ...
        break;
        case 'i':
        ...
        break;
        }
        }

    • Handle trackbar events:
      • Define a trackbar handler:
          void trackbarHandler(int pos)
        {
        printf("Trackbar position: %d\n",pos);
        }

      • Register the handler:
          int trackbarVal=25;
        int maxVal=100;
        cvCreateTrackbar("bar1", "win1", &trackbarVal ,maxVal , trackbarHandler);

      • Get the current trackbar position:
          int pos = cvGetTrackbarPos("bar1","win1");

      • Set the trackbar position:
          cvSetTrackbarPos("bar1", "win1", 25);

    Basic OpenCV data structures

    Image data structure

    • IPL image:
      IplImage
      |-- int nChannels; // Number of color channels (1,2,3,4)
      |-- int depth; // Pixel depth in bits:
      | // IPL_DEPTH_8U, IPL_DEPTH_8S,
      | // IPL_DEPTH_16U,IPL_DEPTH_16S,
      | // IPL_DEPTH_32S,IPL_DEPTH_32F,
      | // IPL_DEPTH_64F
      |-- int width; // image width in pixels
      |-- int height; // image height in pixels
      |-- char* imageData; // pointer to aligned image data
      | // Note that color images are stored in BGR order
      |-- int dataOrder; // 0 - interleaved color channels,
      | // 1 - separate color channels
      | // cvCreateImage can only create interleaved images
      |-- int origin; // 0 - top-left origin,
      | // 1 - bottom-left origin (Windows bitmaps style)
      |-- int widthStep; // size of aligned image row in bytes
      |-- int imageSize; // image data size in bytes = height*widthStep
      |-- struct _IplROI *roi;// image ROI. when not NULL specifies image
      | // region to be processed.
      |-- char *imageDataOrigin; // pointer to the unaligned origin of image data
      | // (needed for correct image deallocation)
      |
      |-- int align; // Alignment of image rows: 4 or 8 byte alignment
      | // OpenCV ignores this and uses widthStep instead
      |-- char colorModel[4]; // Color model - ignored by OpenCV

    Matrices and vectors

    • Matrices:
      CvMat                      // 2D array
      |-- int type; // elements type (uchar,short,int,float,double) and flags
      |-- int step; // full row length in bytes
      |-- int rows, cols; // dimensions
      |-- int height, width; // alternative dimensions reference
      |-- union data;
      |-- uchar* ptr; // data pointer for an unsigned char matrix
      |-- short* s; // data pointer for a short matrix
      |-- int* i; // data pointer for an integer matrix
      |-- float* fl; // data pointer for a float matrix
      |-- double* db; // data pointer for a double matrix


      CvMatND // N-dimensional array
      |-- int type; // elements type (uchar,short,int,float,double) and flags
      |-- int dims; // number of array dimensions
      |-- union data;
      | |-- uchar* ptr; // data pointer for an unsigned char matrix
      | |-- short* s; // data pointer for a short matrix
      | |-- int* i; // data pointer for an integer matrix
      | |-- float* fl; // data pointer for a float matrix
      | |-- double* db; // data pointer for a double matrix
      |
      |-- struct dim[]; // information for each dimension
      |-- size; // number of elements in a given dimension
      |-- step; // distance between elements in a given dimension


      CvSparseMat // SPARSE N-dimensional array

    • Generic arrays:
      CvArr*     // Used only as a function parameter to specify that the
      // function accepts arrays of more than a single type, such
      // as: IplImage*, CvMat* or even CvSeq*. The particular array
      // type is determined at runtime by analyzing the first 4
      // bytes of the header of the actual array.

    • Scalars:
      CvScalar
      |-- double val[4]; //4D vector

      Initializer function:

      CvScalar s = cvScalar(double val0, double val1=0, double val2=0, double val3=0);

      Example:

      CvScalar s = cvScalar(20.0);
      s.val[0]=10.0;

      Note that the initializer function has the same name as the data structure only starting with a lower case character. It is not a C++ constructor.

    Other data structures

    • Points:
      CvPoint      p = cvPoint(int x, int y);
      CvPoint2D32f p = cvPoint2D32f(float x, float y);
      CvPoint3D32f p = cvPoint3D32f(float x, float y, float z);

      E.g.:
      p.x=5.0;
      p.y=5.0;

    • Rectangular dimensions:
      CvSize       r = cvSize(int width, int height);
      CvSize2D32f r = cvSize2D32f(float width, float height);

    • Rectangular dimensions with offset:
      CvRect       r = cvRect(int x, int y, int width, int height);

    Working with images

    Allocating and releasing images

    • Allocate an image:
      IplImage* cvCreateImage(CvSize size, int depth, int channels);

      size: cvSize(width,height);

      depth: pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,
      IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F, IPL_DEPTH_64F

      channels: Number of channels per pixel. Can be 1, 2, 3 or 4. The channels
      are interleaved. The usual data layout of a color image is
      b0 g0 r0 b1 g1 r1 ...

      Examples:

      // Allocate a 1-channel byte image
      IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);

      // Allocate a 3-channel float image
      IplImage* img2=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);

    • Release an image:
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
      cvReleaseImage(&img);

    • Clone an image:
      IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
      IplImage* img2;
      img2=cvCloneImage(img1);

    • Set/get the region of interest:
      void  cvSetImageROI(IplImage* image, CvRect rect);
      void cvResetImageROI(IplImage* image);
      vRect cvGetImageROI(const IplImage* image);

      The majority of OpenCV functions support ROI.

    • Set/get the channel of interest:
      void cvSetImageCOI(IplImage* image, int coi); // 0=all
      int cvGetImageCOI(const IplImage* image);

      The majority of OpenCV functions do NOT support COI.

    Reading and writing images

    • Reading an image from a file:
        IplImage* img=0;
      img=cvLoadImage(fileName);
      if(!img) printf("Could not load image file: %s\n",fileName);

      Supported image formats: BMP, DIB, JPEG, JPG, JPE, PNG, PBM, PGM, PPM,
      SR, RAS, TIFF, TIF

      By default, the loaded image is forced to be a 3-channel color image. This default can be modified by using:

        img=cvLoadImage(fileName,flag);

      flag: >0 the loaded image is forced to be a 3-channel color image
      =0 the loaded image is forced to be a 1 channel grayscale image
      <0>

    • Writing an image to a file:
        if(!cvSaveImage(outFileName,img)) printf("Could not save: %s\n",outFileName);

      The output file format is determined based on the file name extension.

    Accessing image elements

    • Assume that you need to access the $k$-th channel of the pixel at the $i$-row and $j$-th column. The row index $i$ is in the range $[0,\mbox{height}-1]$. The column index $j$ is in the range $[0,\mbox{width}-1]$. The channel index $k$ is in the range $[0,\mbox{nchannels}-1]$.

    • Indirect access: (General, but inefficient, access to any type image)

      • For a single-channel byte image:
        IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
        CvScalar s;
        s=cvGet2D(img,i,j); // get the (i,j) pixel value
        printf("intensity=%f\n",s.val[0]);
        s.val[0]=111;
        cvSet2D(img,i,j,s); // set the (i,j) pixel value

      • For a multi-channel float (or byte) image:
        IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
        CvScalar s;
        s=cvGet2D(img,i,j); // get the (i,j) pixel value
        printf("B=%f, G=%f, R=%f\n",s.val[0],s.val[1],s.val[2]);
        s.val[0]=111;
        s.val[1]=111;
        s.val[2]=111;
        cvSet2D(img,i,j,s); // set the (i,j) pixel value

    • Direct access: (Efficient access, but error prone)

      • For a single-channel byte image:
        IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
        ((uchar *)(img->imageData + i*img->widthStep))[j]=111;

      • For a multi-channel byte image:
        IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
        ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
        ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
        ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R

      • For a multi-channel float image:
        IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
        ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
        ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
        ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R

    • Direct access using a pointer: (Simplified and efficient access under limiting assumptions)

      • For a single-channel byte image:
        IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
        int height = img->height;
        int width = img->width;
        int step = img->widthStep/sizeof(uchar);
        uchar* data = (uchar *)img->imageData;
        data[i*step+j] = 111;

      • For a multi-channel byte image:
        IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
        int height = img->height;
        int width = img->width;
        int step = img->widthStep/sizeof(uchar);
        int channels = img->nChannels;
        uchar* data = (uchar *)img->imageData;
        data[i*step+j*channels+k] = 111;

      • For a multi-channel float image (assuming a 4-byte alignment):
        IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
        int height = img->height;
        int width = img->width;
        int step = img->widthStep/sizeof(float);
        int channels = img->nChannels;
        float * data = (float *)img->imageData;
        data[i*step+j*channels+k] = 111;

    • Direct access using a c++ wrapper: (Simple and efficient access)

      • Define a c++ wrapper for single-channel byte images, multi-channel byte images, and multi-channel float images:
        template class Image
        {
        private:
        IplImage* imgp;
        public:
        Image(IplImage* img=0) {imgp=img;}
        ~Image(){imgp=0;}
        void operator=(IplImage* img) {imgp=img;}
        inline T* operator[](const int rowIndx) {
        return ((T *)(imgp->imageData + rowIndx*imgp->widthStep));}
        };

        typedef struct{
        unsigned char b,g,r;
        } RgbPixel;

        typedef struct{
        float b,g,r;
        } RgbPixelFloat;

        typedef Image RgbImage;
        typedef Image RgbImageFloat;
        typedef Image BwImage;
        typedef Image BwImageFloat;

      • For a single-channel byte image:
        IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
        BwImage imgA(img);
        imgA[i][j] = 111;

      • For a multi-channel byte image:
        IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
        RgbImage imgA(img);
        imgA[i][j].b = 111;
        imgA[i][j].g = 111;
        imgA[i][j].r = 111;

      • For a multi-channel float image:
        IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
        RgbImageFloat imgA(img);
        imgA[i][j].b = 111;
        imgA[i][j].g = 111;
        imgA[i][j].r = 111;

    Image conversion

    • Convert to a grayscale or color byte-image:
      cvConvertImage(src, dst, flags=0);

      src = float/byte grayscale/color image
      dst = byte grayscale/color image
      flags = CV_CVTIMG_FLIP (flip vertically)
      CV_CVTIMG_SWAP_RB (swap the R and B channels)

    • Convert a color image to grayscale:


      Using the OpenCV conversion:

      cvCvtColor(cimg,gimg,CV_BGR2GRAY); // cimg -> gimg


      Using a direct conversion:

      for(i=0;iheight;i++) for(j=0;jwidth;j++)
      gimgA[i][j]= (uchar)(cimgA[i][j].b*0.114 +
      cimgA[i][j].g*0.587 +
      cimgA[i][j].r*0.299);

    • Convert between color spaces:

      cvCvtColor(src,dst,code); // src -> dst

      code = CV_2
      / = RGB, BGR, GRAY, HSV, YCrCb, XYZ, Lab, Luv, HLS

      e.g.: CV_BGR2GRAY, CV_BGR2HSV, CV_BGR2Lab

    Drawing commands

    • Draw a box:
      // draw a box with red lines of width 1 between (100,100) and (200,200)
      cvRectangle(img, cvPoint(100,100), cvPoint(200,200), cvScalar(255,0,0), 1);

    • Draw a circle:
      // draw a circle at (100,100) with a radius of 20. Use green lines of width 1
      cvCircle(img, cvPoint(100,100), 20, cvScalar(0,255,0), 1);

    • Draw a line segment:
      // draw a green line of width 1 between (100,100) and (200,200)
      cvLine(img, cvPoint(100,100), cvPoint(200,200), cvScalar(0,255,0), 1);

    • Draw a set of polylines:
      CvPoint  curve1[]={10,10,  10,100,  100,100,  100,10};
      CvPoint curve2[]={30,30, 30,130, 130,130, 130,30, 150,10};
      CvPoint* curveArr[2]={curve1, curve2};
      int nCurvePts[2]={4,5};
      int nCurves=2;
      int isCurveClosed=1;
      int lineWidth=1;

      cvPolyLine(img,curveArr,nCurvePts,nCurves,isCurveClosed,cvScalar(0,255,255),lineWidth);

    • Draw a set of filled polygons:
      cvFillPoly(img,curveArr,nCurvePts,nCurves,cvScalar(0,255,255));

    • Add text:
      CvFont font;
      double hScale=1.0;
      double vScale=1.0;
      int lineWidth=1;
      cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC, hScale,vScale,0,lineWidth);

      cvPutText (img,"My comment",cvPoint(200,400), &font, cvScalar(255,255,0));

      Other possible fonts:

      CV_FONT_HERSHEY_SIMPLEX, CV_FONT_HERSHEY_PLAIN,
      CV_FONT_HERSHEY_DUPLEX, CV_FONT_HERSHEY_COMPLEX,
      CV_FONT_HERSHEY_TRIPLEX, CV_FONT_HERSHEY_COMPLEX_SMALL,
      CV_FONT_HERSHEY_SCRIPT_SIMPLEX, CV_FONT_HERSHEY_SCRIPT_COMPLEX,

    Working with matrices

    Allocating and releasing matrices

    • General:
      • OpenCV has a C interface to matrix operations. There are many alternatives that have a C++ interface (which is more convenient) and are as efficient as OpenCV.
      • Vectors are obtained in OpenCV as matrices having one of their dimensions as 1.
      • Matrices are stored row by row where each row has a 4 byte alignment.

    • Allocate a matrix:
      CvMat* cvCreateMat(int rows, int cols, int type);

      type: Type of the matrix elements. Specified in form
      CV_(S|U|F)C. E.g.: CV_8UC1 means an
      8-bit unsigned single-channel matrix, CV_32SC2 means a 32-bit signed
      matrix with two channels.

      Example:
      CvMat* M = cvCreateMat(4,4,CV_32FC1);

    • Release a matrix:
      CvMat* M = cvCreateMat(4,4,CV_32FC1);
      cvReleaseMat(&M);

    • Clone a matrix:
      CvMat* M1 = cvCreateMat(4,4,CV_32FC1);
      CvMat* M2;
      M2=cvCloneMat(M1);

    • Initialize a matrix:
      double a[] = { 1,  2,  3,  4,
      5, 6, 7, 8,
      9, 10, 11, 12 };

      CvMat Ma=cvMat(3, 4, CV_64FC1, a);

      Alternatively:

      CvMat Ma;
      cvInitMatHeader(&Ma, 3, 4, CV_64FC1, a);

    • Initialize a matrix to identity:
      CvMat* M = cvCreateMat(4,4,CV_32FC1);
      cvSetIdentity(M); // does not seem to be working properly

    Accessing matrix elements

    • Assume that you need to access the $(i,j)$ cell of a 2D float matrix.

    • Indirect matrix element access:
      cvmSet(M,i,j,2.0); // Set M(i,j)
      t = cvmGet(M,i,j); // Get M(i,j)

    • Direct matrix element access assuming a 4-byte alignment:
      CvMat* M    = cvCreateMat(4,4,CV_32FC1);
      int n = M->cols;
      float *data = M->data.fl;

      data[i*n+j] = 3.0;

    • Direct matrix element access assuming possible alignment gaps:
      CvMat* M    = cvCreateMat(4,4,CV_32FC1);
      int step = M->step/sizeof(float);
      float *data = M->data.fl;

      (data+i*step)[j] = 3.0;

    • Direct matrix element access of an initialized matrix:
      double a[16];
      CvMat Ma = cvMat(3, 4, CV_64FC1, a);
      a[i*4+j] = 2.0; // Ma(i,j)=2.0;

    Matrix/vector operations

    • Matrix-matrix operations:
      CvMat *Ma, *Mb, *Mc;
      cvAdd(Ma, Mb, Mc); // Ma+Mb -> Mc
      cvSub(Ma, Mb, Mc); // Ma-Mb -> Mc
      cvMatMul(Ma, Mb, Mc); // Ma*Mb -> Mc

    • Elementwise matrix operations:
      CvMat *Ma, *Mb, *Mc;
      cvMul(Ma, Mb, Mc); // Ma.*Mb -> Mc
      cvDiv(Ma, Mb, Mc); // Ma./Mb -> Mc
      cvAddS(Ma, cvScalar(-10.0), Mc); // Ma.-10 -> Mc

    • Vector products:
      double va[] = {1, 2, 3};
      double vb[] = {0, 0, 1};
      double vc[3];

      CvMat Va=cvMat(3, 1, CV_64FC1, va);
      CvMat Vb=cvMat(3, 1, CV_64FC1, vb);
      CvMat Vc=cvMat(3, 1, CV_64FC1, vc);

      double res=cvDotProduct(&Va,&amp;Vb); // dot product: Va . Vb -> res
      cvCrossProduct(&Va, &amp;Vb, &Vc); // cross product: Va x Vb -> Vc
      end{verbatim}

      Note that Va, Vb, Vc, must be 3 element vectors in a cross product.


    • Single matrix operations:
      CvMat *Ma, *Mb;
      cvTranspose(Ma, Mb); // transpose(Ma) -> Mb (cannot transpose onto self)
      CvScalar t = cvTrace(Ma); // trace(Ma) -> t.val[0]
      double d = cvDet(Ma); // det(Ma) -> d
      cvInvert(Ma, Mb); // inv(Ma) -> Mb

    • Inhomogeneous linear system solver:
      CvMat* A  = cvCreateMat(3,3,CV_32FC1);
      CvMat* x = cvCreateMat(3,1,CV_32FC1);
      CvMat* b = cvCreateMat(3,1,CV_32FC1);
      cvSolve(&A, &amp;b, &x); // solve (Ax=b) for x

    • Eigen analysis (of a symmetric matrix):
      CvMat* A  = cvCreateMat(3,3,CV_32FC1);
      CvMat* E = cvCreateMat(3,3,CV_32FC1);
      CvMat* l = cvCreateMat(3,1,CV_32FC1);
      cvEigenVV(&A, &amp;E, &l); // l = eigenvalues of A (descending order)
      // E = corresponding eigenvectors (rows)

    • Singular value decomposition:
      CvMat* A  = cvCreateMat(3,3,CV_32FC1);
      CvMat* U = cvCreateMat(3,3,CV_32FC1);
      CvMat* D = cvCreateMat(3,3,CV_32FC1);
      CvMat* V = cvCreateMat(3,3,CV_32FC1);
      cvSVD(A, D, U, V, CV_SVD_U_T|CV_SVD_V_T); // A = U D V^T

      The flags cause U and V to be returned transposed (does not work well without the transpose flags).

    Working with video sequences

    Capturing a frame from a video sequence

    • OpenCV supports capturing images from a camera or a video file (AVI).

    • Initializing capture from a camera:
      CvCapture* capture = cvCaptureFromCAM(0); // capture from video device #0

    • Initializing capture from a file:
      CvCapture* capture = cvCaptureFromAVI("infile.avi");

    • Capturing a frame:
      IplImage* img = 0;
      if(!cvGrabFrame(capture)){ // capture a frame
      printf("Could not grab a frame\n\7");
      exit(0);
      }
      img=cvRetrieveFrame(capture); // retrieve the captured frame

      To obtain images from several cameras simultaneously, first grab an image from each camera. Retrieve the captured images after the grabbing is complete.

    • Releasing the capture source:
      cvReleaseCapture(&capture);

      Note that the image captured by the device is allocated/released by the capture function. There is no need to release it explicitly.

    Getting/setting frame information

    • Get capture device properties:
      cvQueryFrame(capture); // this call is necessary to get correct
      // capture properties
      int frameH = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
      int frameW = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
      int fps = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
      int numFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);

      The total frame count is relevant for video files only. It does not seem to be working properly.

    • Get frame information:
      float posMsec   =       cvGetCaptureProperty(capture, CV_CAP_PROP_POS_MSEC);
      int posFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES);
      float posRatio = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO);

      Get the position of the captured frame in [msec] with respect to the first frame, or get its index where the first frame starts with an index of 0. The relative position (ratio) is 0 in the first frame and 1 in the last frame. This ratio is valid only for capturing images from a file.

    • Set the index of the first frame to capture:
      // start capturing from a relative position of 0.9 of a video file
      cvSetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO, (double)0.9);

      This only applies for capturing from a file. It does not seem to be working properly.

    Saving a video file

    • Initializing a video writer:
      CvVideoWriter *writer = 0;
      int isColor = 1;
      int fps = 25; // or 30
      int frameW = 640; // 744 for firewire cameras
      int frameH = 480; // 480 for firewire cameras
      writer=cvCreateVideoWriter("out.avi",CV_FOURCC('P','I','M','1'),
      fps,cvSize(frameW,frameH),isColor);

      Other possible codec codes:

      CV_FOURCC('P','I','M','1')    = MPEG-1 codec
      CV_FOURCC('M','J','P','G') = motion-jpeg codec (does not work well)
      CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec
      CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec
      CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec
      CV_FOURCC('U', '2', '6', '3') = H263 codec
      CV_FOURCC('I', '2', '6', '3') = H263I codec
      CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec

      A codec code of -1 will open a codec selection window (in windows).

    • Writing the video file:
      IplImage* img = 0;
      int nFrames = 50;
      for(i=0;i

      To view the captured frames during capture, add the following in the loop:

      cvShowImage("mainWin", img);
      key=cvWaitKey(20); // wait 20 ms

      Note that without the 20[msec] delay the captured sequence is not displayed properly.

    • Releasing the video writer:
      cvReleaseVideoWriter(&writer);


    next_inactive up previous
    Gady Agam 2006-03-31

    Installing OpenCV from CVS on Ubuntu Edgy

    The following is from:

    http://www.ryanbruce.org/
    very good instruction.

    Installing OpenCV from CVS on Ubuntu Edgy

    November 30th, 2006 by ryanmbruce

    These are my notes concerning the installation of OpenCV from CVS on Ubuntu Edgy. While I’ll try to be helpful if you have problems, I’m not responsible for blowing up your system.

    The charade:
    Check out the OpenCV code from cvs:

    cvs -d:pserver:anonymous@opencvlibrary.cvs.sourceforge.net:/cvsroot/opencvlibrary login
    cvs -z3 -d:pserver:anonymous@opencvlibrary.cvs.sourceforge.net:/cvsroot/opencvlibrary co -P opencv

    Then make sure pkg-config and g++ are installed:

    sudo apt-get install g++ pkg-config

    At this point, you should be able to configure and install opencv, but it probably won’t find some of the libraries it needs to work with video and certain image formats. To get all the functionality of OpenCV, I installed the following packages (Some of these are in the multiverse repositories. Go here to find out how to add more repositories):

    sudo apt-get install libgtk2.0-dev libavcodec-dev libavformat-dev libjpeg62-dev libtiff4-dev

    Now you can run:

    cd opencv && ./configure

    Check to make sure all of the fancy features you want show up as enabled. The packages we installed earlier make my configuration show up something like so:

    General configuration =============================================
    Compiler: g++
    CXXFLAGS: -Wall -fno-rtti -pipe -O3 -g -march=i686 -ffast-math -fomit-frame-pointer
    Install path: /usr/local

    HighGUI configuration =============================================

    Windowing system --------------
    Use Carbon / Mac OS X: no
    Use gtk+ 2.x: yes
    Use gthread: yes

    Image I/O ---------------------
    Use libjpeg: yes
    Use zlib: yes
    Use libpng: yes
    Use libtiff: yes
    Use libjasper: no
    Use libIlmImf: no

    Video I/O ---------------------
    Use QuickTime / Mac OS X: no
    Use xine: no
    Use ffmpeg: yes
    Use dc1394 & raw1394: yes
    Use v4l: yes
    Use v4l2: yes

    Wrappers for other languages =========================================
    SWIG
    Python no

    Additional build settings ============================================
    Build demo apps yes

    Now run make ...

    If everything looks good, we can now compile and install OpenCV:

    make && sudo make install && sudo ldconfig

    You may need to run the following command if /usr/local isn’t in your library search path (make sure you trust users who have write access to /usr/local/lib):

    sudo sh -c 'echo "/usr/local/lib" >> /etc/ld.so.conf && ldconfig'

    Instead, some guides may instruct you to change the LD_LIBRARY_PATH environment variable, but this is not the best way to get your programs to work. Modifying this variable is generally used as a hack to get things working in the moment, but it should not be used as a permanent solution, as it poses security problems. This means that you shouldn’t try setting this variable in any startup scripts… See this page about shared libraries.

    Now you can start writing programs which employ the functionality of OpenCV. The best way learn how to do this is by looking at the sample applications. You can compile the sample applications by doing the following:

    cd samples/c
    chmod u+x build_all.sh
    ./build_all.sh

    Now you can run the sample apps just like any other executable:

    ./ProgramName --ProgramOptions

    Please comment if you find problems or have suggestions.

    Troubleshooting:
    If you get an error like the following one after running your application, then you didn’t correctly add /usr/local/lib to the library search path. Go back and do it correctly…

    ./ProgramName: error while loading shared libraries:
    libcxcore.so.1: cannot open shared object file: No such file or directory

    Links:
    http://www.hci.iastate.edu/575x/doku.php
    The wiki for a class using OpenCV. There are examples, tutorials, problems, and students’ solutions all open to the public.

    http://opencvlibrary.sourceforge.net
    The official OpenCV wiki.

    5/3/07

    install dwww.

    dwww is very good. It will search the documents in the system (not a search engine) and make it very easy to find the help or manuals.

    5/2/07

    change apt-get default archives directory.

    In /etc/apt/, edit a file apt.conf if it doesn't exist. In this file add the following:
    Dir::Cache::archives "the/location/you/want/" ;
    do not forget ;
    In the director you want you must have similar lay out of directory. for example
    /home/user/var/cache/apt/archives/
    in the above directory you must have partial(director) also.
    You can use the following to make the directory:
    mkdir -p /home/user/var/cache/apt/archives/partial/
    Then your apt.conf can be the following:

    Dir::Cache::archives "/home/user/var/cache/apt/archives/";

    Another way is:
    aptitude -o Dir::Cache::archives "/home/user/var/cache/apt/archives/"
    I did not try this one, though it is supposed to work.

    4/23/07

    C++ currying.

    http://www.numerical-recipes.com/forum/showthread.php?t=526

    NR and extra parameters.

    http://www.thescripts.com/forum/thread509195.html

    4/21/07

    image zoomin.

    When zoom in the image, the number of pixels occupied by the objects increases. I think there is some interpolations!!

    4/14/07

    source navigator

    It is a very nice tool for source/code reading.

    4/13/07

    sort two vectors.

    cvcl-20060527/src/include/cvclutil.h - Google Code Search
    sort one vector based on the other.

    template
    std::pair strPair(const std::string& f, const T& t) {
    return std::pair(f, t);
    }

    typedef std::pair StrPair;

    //! Sort two vectors based on the first vector
    template
    void sort2(std::vector& keys, std::vector& vals) {
    DebugAssert(keys.size()==vals.size(), "sort2()");
    // Create std::vector of pairs std::vector > pairs;
    for(size_t i=0, iend=keys.size(); i pairs.push_back(strPair(keys[i], vals[i]));
    // Sort pairs
    StrPairLess comp;
    sort(pairs.begin(), pairs.end(), comp);
    DebugAssert(pairs.size() == keys.size(), "sort2()");
    // Split the pairs back into the original vectors
    for(size_t i=0, iend=pairs.size(); i keys[i] = pairs[i].first;
    vals[i] = pairs[i].second;
    }
    }

    }

    4/12/07

    using magick++

    c++ -o example example.cpp `Magick++-config --cppflags --cxxflags --ldflags --libs`


    Now I want to use kdevelop as my IDE and use Qmake. How to use magick++ library now?
    1. in a console type:
    >
    Magick++-config --cppflags --cxxflags --ldflags --libs

    -I/usr/include
    -pthread
    -L/usr/lib -L/usr/X11R6/lib -lfreetype -lz -L/usr/lib
    -lMagick++ -lWand -lMagick -llcms -ltiff -lfreetype -ljasper -ljpeg -lpng -ldpstk -ldps -lXext -lXt -lSM -lICE -lX11 -lbz2 -lxml2 -lz -lpthread -lm -lpthread

    The above is the output.
    So in the src. pro file, add the following:

    INCLUDEPATH += /usr/include /usr/include/magick

    LIBS = -lfreetype -lz -lMagick++ -lWand -lMagick -llcms -ltiff -lfreetype -ljasper -ljpeg -lpng -ldpstk -ldps -lXext -lXt -lSM -lICE -lX11 -lbz2 -lxml2 -lz -lpthread -lm -lpthread


    Now recompile the project. It should work.