Monday, December 3, 2007

Ubuntu 6.10 + RebeccaAIML 0.9871 Installation Notes

Here's my experience in installing RebeccaAIML on my Ubuntu 6.10 machine. This notes are being used for my report for my class project.

RebeccaAIML installation notes:

1. For Linux, use the version 0.9871 (Edmonson)

* Why this version?
In the RebeccaAIML website (http://rebecca-aiml.sourceforge.net) the latest version is 1.1tp3(Slatter), but this only works under Windows. So only use this latest version if you are working in Windows. -- The developer is working on the Linux version.
* There are so many options to download, which one is it??
The file to download is: RebeccaAIML-src-9871.* (the * indicates the extension of the file. The file is in compressed format, either: .tar.gz, or .zip, or some other compressed form). Go to: http://rebecca-aiml.sourceforge.net/download.htm to download -- It is IMPORTANT that you download the source package (with a "-src" in the filename), and not any other without it (e.g. RebeccaAIML-9871.zip). The source package one has a build_files directory in it, which contains the necessary configure, and Makefile to install RebeccaAIML. Also, in the source package there are installation guides both for Linux and Windows in the files linuxInstall.txt and windowsInstall.txt, respectively. SAVE YOURSELF A HEADACHE, and don't make the same mistake as me for struggling to try to install the non-source version of the package (cause of headache: couldn't find the linuxInstall.txt, configure file, and Makefile file).
* Why use RebeccaAIML? There are some other AIML programs that's available...
I am working on this program/assignment in C++, RebeccaAIML is one of the AIML packages that is written in C++, which means, I can (relatively) easily integrate it with my program. There are other AIML packages that are also written in C++ (go to http://www.alicebot.org/downloads/programs.html to check), but from what I've seen so far, RebeccaAIML has the most comprehensive documentation, and besides, the person who developed RebeccaAIML is very nice, and was very helpful when I e-mailed him asking questions about my trouble installing RebeccaAIML. If you have trouble with RebeccaAIML which are not covered in this notes, or that you cannot find any answer to your RebeccaAIML-related problem/questions (please don't come to him with your personal questions -- talk to Rebecca instead :)) after trying, and/or searching/discussing it in the web, forums, etc., e-mail him at: foreverlinux@yahoo.com

2. Dependencies

* What are dependencies?
Dependencies are other things that need to be installed in order for RebeccaAIML to work. This is a potential headache source as well, so this is IMPORTANT as well. You have been warned.
* Why is this important?
Because unless you have these dependencies installed, you won't get past the ./configure step. You need to do: ./configure, make, and make install to install RebeccaAIML.
* Okay, so what dependencies do I need to run RebeccaAIML?
The dependencies you'll (or RebeccaAIML) need are:
o Boost - some kind of extended C++ library
o XercesC - a C++ - based XML Parser (a program that can interpret XML)
o Qt4.1.1 or Qt4.*
* If you are using Ubuntu like me (I used Ubuntu 6.10) and are inexperienced in UNIX/Linux (like me), I would strongly suggest installing the dependencies through the Synaptic Package Manager. Why? For some reason, I almost could never got anything I install manually in Ubuntu 6.10 (without Synaptic Package Manager) to work properly.
* OK, here's some more details on the dependencies that you'll need:
o Boost
+ The latest version from the website (www.boost.org) is 1.34.7. In the Synaptic Package Manager, however, there is only version 1.33.1 (use the search tool, and enter the keyword: boost).
+ Just tell me which Boost files I need to get it on with RebeccaAIML!
There should be several files that are Boost-related in the list. You will need (at least, these are what I installed which are sufficient to allow me to install RebeccaAIML):
# libboost-dev
# libboost-doc
# libboost-date-time1.33.1
# libboost-date-time-dev
# libboost-filesystem1.33.1
# libboost-filesystem-dev
# libboost-regex1.33.1
# libboost-regex-dev

+ I don't know if the -doc or the -dev files (except for libboost-dev) are necessary for RebeccaAIML to work or not.
+ NOTE: IF YOU ARE NOT INTERESTED IN THE REASONING BEHIND THOSE FILES, AND JUST WANT TO GET RIGHT INTO USING RebeccaAIML, SKIP THE FOLLOWING BULLETS AND GO STRAIGHT TO THE XercesC POINT.
+ What are these files for? Why so many?
I have no idea. I could not find any explanation in any of the documentation why any of these dependencies are necessary (except for XercesC, because it is obvious we'll need some kind of XML parser since the AIML is in XML).
+ But there are other libboost stuff not being installed, e.g. libboost-graph, libboost-iostream...
Yes, it's because only those three were asked during the ./configure. So what happened with my experience was, I did not have Boost installed, and so at a certain point in the ./configure step, it checks for Boost functionalities, and gave an error asking for Boost to be installed. After I installed Boost, then it asked for Boost filesystem. After I installed Boost filesystem, it then asked for Boost date-time. After I installed Boost date-time, it then asked for Boost regex. ONLY after I installed those, the ./configure was able to proceed past checking Boost functionalities.
# A side note to this, let me tell a little more detail on how my experience installing Boost manually went:
* As I said before, in the Boost website (www.boost.org), the latest version is 1.34.7. So, that's what I downloaded.
* I first did a ./configure with specifying a directory for the installation, i.e.:

./configure --prefix=/boost/1_34_7/

* After the ./configure, the make and make install step was not a problem.
* I found the installed Boost header (.h) files in my /usr/include/boost directory. I could not find the libboost-*.* in any of the /lib directories though. Maybe I've overlooked it if they were scattered with the other lib- files in the /usr/lib directory.
* When I went back to the RebeccaAIML directory(/directory_where_it_was_extracted/RebeccaAIML-src-9871/build_files/autoconf) and did the ./configure for RebeccaAIML, it still could not find the Boost files. I tried including the directory where the Boost files are during ./configure, but it didn't work either.
* I decided to uninstall Boost before re-installing it. According to several posts in some forums (search Google: boost uninstall) the way to uninstall Boost is to just delete the Boost installation directory.
* And so I did, and I re-installed Boost, but this time I did not use the --prefix at ./configure. This time, the ./configure failed. Maybe I have to be in super-user mode (in the terminal, type: sudo su)...
* So I re-install Boost under a shallower directory: i.e. /boost, which worked fine as before.
* Then I did ./configure for RebeccaAIML again, and still it asked for Boost. This time I noticed that it was asking for a Boost filesystem functionalities, and I noticed in the directory I specified with --prefix at the Boost ./configure (/boost), there is a directory named filesystem. So I tried copying the folder (from the terminal using:

cp -rf )


into the /usr/lib/boost directory.
* This time, the RebeccaAIML ./configure found the Boost Filesystem functionality, YAY. But, unfortunately, it then asked for another Boost functionality and at this point, I had a splitting headache and decided to rely on Synaptic Package Manager instead to install Boost and the other dependencies (source of headache: errors keep popping up during ./configure).
o Xerces-C
+ What is Xerces-C and why do we need it?
It is a C++ -based XML parser necessary to understand (parse) AIML. AIML is represented in XML form, and so to be able to extract the information represented in AIML, we need the parser to do it.
+ So which Xerces-C package or version should I get?
The latest version of Xerces-C at the point this note is written is 2.8, but in Synaptic Package Manager (in my list, at least), there are only version 2.6, and 2.7. I chose version 2.6 (see reason in the second bullet after this). Save a headache, install through Synaptic Package Manager -- never fails.
+ So which Xerces files should I install? There are several of them in the list.
Here are the files I have installed:
# libxerces26c2
# libxerces26-dev
# libxerces2-java
+ Note: the RebeccaAIML developer (foreverlinux@yahoo.com) told me that Xerces 2.7 is "badly broken", so he recommended using 2.6 or 2.8 instead. In my Synaptic Package Manager, there are only 2.6, and 2.7, so I used 2.6 instead.
# A side note: initially I had 2.7 installed, and had some error messages during make install and loading RebeccaAIML, but it still ran. After uninstalling 2.7 as recommended, and installing 2.6, I still get the same error message in make install. So, I don't know if that makes any difference
o Qt4.1.1
+ What is Qt for?
Your guess is as good as mine.
+ Any particular reason why version 4.1.1?
I don't know. Maybe that's what was used at the time this version of RebeccaAIML was developed. RebeccaAIML ./configure asked for version 4.1.1, but that version doesn't seem to be around anymore, either on Qt's website (www.trolltech.com) nor in the Synaptic Package Manager (at least, according to my list). The ones available in my Synaptic list are versions 3, and 4.2. I installed 4.2, which seems to be sufficient.
+ Show me the files I need, please.
Certainly. Here are the files I installed:
# libqt4-core
# libqt4-dev
# libqt4-gui
# libqt4-qt3support
# libqt4-sql
# libqthreads-12
# in addition, before qt4, I had libqt3-mt

* Once you have those dependencies installed (all hail Synaptic Package Manager), configuring and installing RebeccaAIML is a breeze. Well, there are still some minor coughs, but nothing serious, or so it seems.

3. FINALLY - INSTALLING RebeccaAIML

* How do I go about and install RebeccaAIML on my machine?
First, be aware all the steps explained in this note is for installing RebeccaAIML on an Ubuntu 6.10 machine like mine. I cannot guarantee it will work for other platforms/OS of Linux or even a different Ubuntu release (e.g. 6.06, 7.04). For installation under Windows there's a whole different process altogether.
o For Windows, don't use version 0.9871, instead use the latest one: 1.1tp3 (Slatter); it comes with a Windows installer. Go to http://rebecca-aiml.sourceforge.net/userGuide.htm for a step-by-step explanation for the installation in Windows.
o For Ubuntu Linux 6.10: assuming you already installed all the required dependencies and downloaded the RebeccaAIML version 0.9871 source package:

1. Extract the RebeccaAIML-src-9871.* package into some directory (you choose).
2. In the extracted directory, you should have the following contents:
1. aiml (directory)
2. bin (directory)
3. build_files (directory)
4. conf (directory)
5. doc (directory) -- (the linuxINSTALL.txt & windowsINSTALL.txt are located in here)
6. include (directory)
7. resources (directory)
8. src (directory)
9. Authors.txt
10. dev-todo.txt
11. INSTALL.txt
12. license.txt
13. README.txt
14. rebecca.spec
15. ReleaseNotes.txt

3. Go to the build_files/autoconf sub-directory.
4. In this directory is where you will be doing all the ./configure, make, and make install, or make clean (to uninstall). So, in the terminal/shell/console do:

./configure


If for some reason it does not recognize your installed Qt location, you can specify it by doing (it should give you a hint on the parameter):

./configure --with-qt-dir=


If there is a doxygen error, just ignore it -- it's some documentation on the RebeccaAIML API, but you already have it in the directory where you extract RebeccaAIML under /doc). After the ./configure is successful, do:

make


Sit back, sip your coffee, and let the system do its thing. After it is done with make, first login as a super-user, if you haven't done so:

sudo su
(then type in your password)

After that, do:

make install


Again, sit back and take another sip of your coffee, and wait until it is done. Now here's where I had some error messages -- at the end of make install, it says:

blah blah blah install blah blah blah

...

Making install in regression
make[1]: Entering directory `//RebeccaAIML-src-9871/build_files/autoconf/regression'
make[2]: Entering directory `//RebeccaAIML-src-9871/build_files/autoconf/regression'
test -z "@datadir@/Rebecca/bin/release" || mkdir -p -- "@datadir@/Rebecca/bin/release"
/bin/sh ./libtool --mode=install /usr/bin/install -c 'regression' '@datadir@/Rebecca/bin/release/regression'
libtool: install: `@datadir@/Rebecca/bin/release' must be an absolute directory name
Try `libtool --help --mode=install' for more information.
make[2]: *** [install-binPROGRAMS] Error 1
make[2]: Leaving directory `//RebeccaAIML-src-9871/build_files/autoconf/regression'
make[1]: *** [install-am] Error 2
make[1]: Leaving directory `//RebeccaAIML-src-9871/build_files/autoconf/regression'

make: *** [install-recursive] Error 1


and that's the end of the line of the make install.


4. TESTING RebeccaAIML (Ooh, this is getting exciting!)

* The first way -- and probably the easiest way, to test RebeccaAIML is to:
o Go to your RebeccaAIML installation directory (mine is at): /usr/local/share/Rebecca
o From there, go to /bin/release
o You should see a console executable. Run it: in the terminal/shell/console type:

./console

o and it should start loading a bunch of .aiml categories
o If everything goes well, you should see something like this:

[Rebecca now fully loaded]
[Number of categories loaded: 46105]
[Type /exit to exit]

Symbolic reduction: SET PREDICATES OM
[Warning star Tag Size Exceeded]
Rebecca says: Hello!
You say> hello

Internal information:
=====================
hello : Hello : *
=====================

Rebecca says: Hi there!

o And VOILA! You're chatting with Rebecca!
* The second way, which I had a less than successful experience, is to try the code from the RebeccaAIML's Sourceforge website: http://rebecca-aiml.sourceforge.net/userGuide.htm#cpp_programming
o If you are NOT using Windows, ignore the first sample code which uses

#include
using namespace rebecca;


on the top. The network thing is something that comes with the Windows installation, and not with the Linux version. Use the second example called the "embedded" variant by the guide. However, I was not successful in trying the code as-is (with some modifications to the paths). If you want to start implementing RebeccaAIML into your program, I would suggest taking a look at the console sample source code (mine is located in: /usr/local/share/Rebecca/src/samples/console).
o If you ARE doing this from Windows, then by all means, use that first example as reference. The guide says that it will save you many lines of codes of initiating the AIML components. What I understand so far about this method is that it is using the Internet Communications Engine that comes with the Windows installation of RebeccaAIML, that enables your machine to be a server and do the XML (or AIML) parsing like it was done on a web server (i.e. like browsing the internet).

And Finally, UNINSTALLING RebeccaAIML

* In the directory //RebeccaAIML-src-9871/build_files/autoconf do:

make clean

Thursday, November 8, 2007

Experience with SWIG + C/C++ = Java

Wrappers! Oh, joy.

Do you know how to be able to call C/C++ functions from Java? Wrappers...you have to create these things called "wrappers". Basically what it does is connects your C/C++ codes and your Java codes through some shared objects. "Shared objects? What in the world is that?? How am I supposed to know how to make 'shared objects'??" you ask? I had the same question. Luckily, there are some very nice fellows out there that provide us with a piece of software that is called an interface compiler, which... you guessed it, CREATES THOSE SHARED OBJECTS (and other necessary files) for us to use. Salute to them, I say! One good example of it (and the one I am using) is called SWIG (www.swig.org).

Unfortunately, I don't remember how to install SWIG on my Ubuntu 6.10 system. But I would like to share the problem I experienced in getting my Java code to call the C/C++ functions using SWIG.

To test, I used the example in the SWIG website tutorial page (www.swig.org/tutorial.html). So here goes:

You will have to write the codes for 3 files:
1. The C/C++ code (*.c) which contains the functions you wish to call from another language (in my case, Java).
2. The interface file (*.i) which is the input file for SWIG.
3. The other language code (in my case, *.java) which will call the C/C++ functions in *.c file in 1.
All the other files (shared objects, additional .c files, .java files) will be generated by SWIG. Please refer to the SWIG tutorial page for other languages, as I don't have any experience with SWIG and Python or Perl for example.

First, create your C/C++ file example.c:
/* File : example.c */

#include
double My_variable = 3.0;

int fact(int n) {
if (n <= 1) return 1; else return n*fact(n-1); } int my_mod(int x, int y) { return (x%y); } char *get_time() { time_t ltime; time(&ltime); return ctime(&ltime); }
Ok, nothing specific to point out there. It's just a straight forward C code, copied directly from the SWIG tutorial page. In fact, I'm pretty sure there's nothing in there that's specified for preparing it for the SWIG compilation. This next file, however, IS important; it is the interface file that SWIG will use to create the files necessary to make the wrapper.

/* example.i */
%module example
%{
/* Put header files here or function declarations like below */
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
%}

extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
So, if I understand it correctly, the interface file (example.i) declares all the variables and functions used in the C/C++ file (example.c). Another way to do it, is to write the header file there instead of the variables and functions one-by-one. So here's another example for the interface file using header file from the same SWIG tutorial page:

/* example.i */
%module example
%{
/* Includes the header in the wrapper code */
#include "header.h"
%}

/* Parse the header file to generate wrappers */
%include "header.h"
So, you can use either type of interface file (depends on whether or not you have the header (*.h) file). As you can see, in both formats, you have to declare the variables/functions or header file twice: once within the % and curly brackets ({}), and another just preceded with the % sign (for the one with the header file). Note that when declaring the variables/functions, they must be preceded with the extern keyword. Here's a little thing about the extern keyword...

According to one definition:

External References: extern

  • If a variable is declared (with global scope) in one file but referenced in another, the extern keyword is used to inform the compiler of the variable's existence:
    • In declare.c:
      int farvar;
    • In use.c:
      {
      extern int farvar;
      int a;
      a = farvar * 2;
      }
  • Note that the extern keyword is for declarations, not definitions
    • An extern declaration does not create any storage; that must be done with a global definition
(from: http://icecube.wisc.edu/~dglo/c_class/vstorage.html)

And another:

extern

The extern keyword is used to inform the compiler about variables declared outside of the current scope. Variables described by extern statements will not have any space allocated for them, as they should be properly defined elsewhere.

Extern statements are frequently used to allow data to span the scope of multiple files.

(from: http://www.cppreference.com/keywords/extern.html)


So, it has got something to do for variables that are being used in one code (e.g. iUseVariableA.c), which are declared in another code (e.g. iDeclareVariableA.h or iDeclareVariableA.i). Is it something like "universal" (across several codes/files) variable for the codes that are being compiled? I don't know how to explain it appropriately, so if anyone can help me explain it in plain english, that'll be awesome.

Ok, let's move on to the SWIG-ing (note to self: got to find a better way to say it... that sounded weird). So, the third, and final file you have to make is the other language (in my case, Java) where you have to call the C/C++ functions.

/* main.java */
public class main {
public static void main(String argv[]) {
System.loadLibrary("example");
System.out.println(example.getMy_variable());
System.out.println(example.fact(5));
System.out.println(example.get_time());
}
}
See how you kind of calls the getMy_variable(), fact(int), and get_time() functions that were defined in the example.c by doing example.getMy_variable(), example.fact(5), example.get_time()? Seems pretty straightforward.

Now come the exciting part... compilation!

Here's how it was explained in SWIG tutorial page for compiling for Java module (all these are done in Terminal):

$ swig -java example.i
$ gcc -c example.c example_wrap.c -I/c/jdk1.3.1/include -I/c/jdk1.3.1/include/win32
$ gcc -shared example.o example_wrap.o -mno-cygwin -Wl,--add-stdcall-alias -o example.dll
Uh-oh... yeah, after reading more carefully, I realized that this example was for Cygwin/Windows. You can figure it out by the .../win32 include directory. And more importantly, see the third line, where the output is example.dll, a Windows Dynamic Linked Library (you know it's the output file because it was preceded by the '-o' command). So, what about for Ubuntu (Linux) users like me? Fear not! There is salvation, yet.

After digging deeper into the SWIG website (and unfortunately, couldn't find exactly what I was looking for through searching the forums), I found this documentation for Linux:

$ swig -java example.i
$ gcc -fpic -c example.c example_wrap.c -I/usr/java/j2sdk1.4.2/include -I/usr/java/j2sdk1.4.2/include/linux
$ gcc -shared example.o example_wrap.o -o libexample.so
$ javac main.java
$ java main
(from: http://www.dabeaz.com/cgi-bin/wiki.pl?SwigFaq/Java)

So, first you do (everything here are done in Terminal):

$ swig -java example.i

which tells the SWIG compiler to create a Java module, with the input interface file: example.i
Cool. If it works, SWIG then creates several files in the same directory:

example.java
example.class
example.o
exampleJNI.java
exampleJNI.class
example_wrap.c
example_wrap.o

For the most part, you won't be modifying these files. You can try, but DO IT AT YOUR OWN RISK; make sure you know what you're doing :) As a side note: if you've never done Java programming, the *.class files are the compiled *.java files. So the source codes are in *.java files.

Allrighty, next let's compile the *.c files that we have: example.c and example_wrap.c (one of the result files from SWIG compilation).

$ gcc -fpic -c example.c example_wrap.c -I/usr/java/j2sdk1.4.2/include -I/usr/java/j2sdk1.4.2/include/linux

I don't know if it will make any difference if you use g++ or other C/C++ compiler rather than gcc. I used gcc and it worked fine. So, the thing to keep in mind is the -I include paths; you have to find for yourself where those java***/include and java***/include/linux are located. Mine are located in: /usr/lib/jvm/java-1.5.0-sun/include and /usr/lib/jvm/java-1.5.0-sun/include/linux, respectively, since I used Java SDK 1.5 (which I installed through Synaptic Package Manager). So my actual command looked like this:

$ gcc -fpic -c example.c example_wrap.c -I /usr/lib/jvm/java-1.5.0-sun/include -I /usr/lib/jvm/java-1.5.0-sun/include/linux

Don't forget the .../linux include directory, otherwise it will give some nasty errors. OK, that should compile nicely. Next step, compile and create the shared object.

$ gcc -shared example.o example_wrap.o -o libexample.so
Nothing to be changed here. So basically the compiler will take the object file (note the .o extension) example.o and example_wrap.o, and creates the output file which is the shared object libexample.so (i.e. library -- hence the .so extension). IMPORTANT: Note that for Linux, the output file must start with lib*** (in this case: lib+example = libexample.so), otherwise it won't work.

So now you'll have these files:

example.java
example.class
example.o
exampleJNI.java
exampleJNI.class
example_wrap.c
example_wrap.o
libexample.so

Can you see where we're going with this? We now have a example.class.... which means, now we can have a main Java routine (method, function, whatever) that instantiates (creates) the object named 'example' and thus can access the variables and/or functions (methods) of the object 'example', which variables and functions are actually defined in example.c.

So, let's create that Java routine that calls those lovely functions in example.c (again, this is from the SWIG tutorial page):

/* main.java */
public class main {
public static void main(String argv[]) {
System.loadLibrary("example");
System.out.println(example.getMy_variable());
System.out.println(example.fact(5));
System.out.println(example.get_time());
}
}
In case you're wondering, yeah, I already shown this code. But now it should be clearer; you can notice that we're calling the example functions by: "example." there. So now you just need to compile this main.java file by:

$ javac main.java
Now, here's one part where I had some problems. I got these error messages:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no example in java.library.path

Unfortunately, I didn't do the troubleshooting systematically, that I couldn't really tell which steps fixed the problem, and which don't. But, there is one more step that was not explicitly said in the SWIG tutorial. There are some conversations in some forums (alas, I forgot the link) that said you HAVE TO set the LD_LIBRARY_PATH to where your .so file is. You can do:

export LD_LIBRARY_PATH=:$LD_LIBRARY_PATH

(Don't use the brackets "<>") Apparently, that error is one that most commonly occurs. I think it should be safe to set that path before you compile the .java file, but my experience with it is that I set that path AFTER I compiled the example.i with swig, gcc the *.c files, and the gcc -shared stuff, and I kept getting error messages during compilation. So I deleted all the files that were generated by SWIG, and recompiled the whole thing from scratch. After the javac compilation was successful, I ran the main.class with:

$ java main
And it worked!

$ java main
3.0
120
Fri Nov 9 00:17:37 2007

Hooray!!! Unfortunately, I'm still not sure what's the proper procedure for an error-free, trouble-free, headache-free compilation.

Another thing I want to add is, be careful when you're writing your Java program in packages. I gave packages names on my main.java, example.java, and exampleJNI.java, and here's the error that I got:

$ javac main.java
main.java:8: cannot find symbol
symbol : variable example
location: class facerecognition.main
System.out.println(example.getMy_variable());
^
main.java:9: cannot find symbol
symbol : variable example
location: class facerecognition.main
System.out.println(example.fact(5));
^
main.java:10: cannot find symbol
symbol : variable example
location: class facerecognition.main
System.out.println(example.get_time());
^
3 errors

Unfortunately, I have limited knowledge in compiling Java from the Terminal (I've been using Eclipse). I think if using packages, compiling requires additional arguments:

$ javac -package [package name] [main program].java

I think. If anyone can fill me in on that, I'll really appreciate it.

So there you have it, my experience making wrappers for C/C++ for Java using SWIG. Now I have to create a GUI in Java for application using OpenCV...

Some useful links:
http://www.swig.org/Doc1.3/Java.html
http://www.dabeaz.com/cgi-bin/wiki.pl?SwigFaq/Java

Wednesday, October 24, 2007

Cease and Desist

Well, apparently the name "Artineering" has been used by someone commercially, therefore I cannot use the name anymore. Here's the official warning I got just recently:

"My client, Lance Dehne', business owner of ARTineering since 1985 and trademark holder of ARTineering requests that you immediately cease and desist using his Company name."

I wonder, since I'm not using the name for commercial purposes nor for profit, and I don't capitalize the word "Art" in my "Artineering", I don't understand why it is a problem. "cease and desist"?

In any case, I'm honoring the request, and I hope everybody's happy now.

For the owner of ARTineering, I apologize for using the name of your business without your consent and without checking that it was a registered name. I did not mean to cause any disruption nor any confusion to your business and your clients; I used the name since it reflects my interest in both the area of engineering and art. I'm actually happy that there actually IS an artistic engineer out there. I hope there won't be anymore problem now.

Best regards.

Thursday, August 2, 2007

Ubuntu 6.10 + Logitech QuickCam Pro 4000

Quirky little thing, the QuickCam Pro 4000 is on the Ubuntu 6.10...

First make sure your Ubuntu detects the device:
  • From the Terminal, do: lsusb (it gives a list of USB devices that are connected to your PC)
  • If it finds the webcam, it should say something like: Logitech, Inc. QuickCam Pro 4000 in one of those Bus 00# Device 00#: ID ####:#### lines. If not, I don't have an answer to that yet.
To make it work, you need the pwc driver: pwc-10.0.12-rc1 which you can obtain from http://www.saillard.org/linux/pwc. A very nice and helpful site, I must say. On the main page, under Documentation you can find a handy howto to install the driver (click on the "Read this Howto to install the driver in English" - if you're opening it in Windows, just use Notepad/Wordpad to read it). Scroll down until you find the Files section and click on the "Full source code that don't need patching the kernel" link to get the file.

Just FYI, I'm using Ubuntu 6.10 with 2.6.17-12-generic kernel. After you get into the Files page, grab the latest version: pwc.10.0.12-rc1.tar.bz2 (per the time this blog is written (Aug '07) ), the description of the file should say: "Last Updated: Apr 13, 2006, Size: 47.72 KB".

(The following explanations are done on the Terminal, unless noted otherwise)

A little quirk here... For some reason when I try to unpack the file with the command:
tar xjf pwc-10.0.12-rc1.tar.bz2

It failed with the message:
bzip2: (stdin) is not a bzip2 file.
tar: Child returned status 2
tar: Error exit delayed from previous errors

No idea why, since I do have bzip2 installed. Therefore, I prefer to download it from the website (instead of using wget http://www.saillard.org/linux/pwc/files/pwc-10.0.12-rc1.tar.bz2 from the Terminal) using Firefox (for example) and choose Open File which automatically unpacks the file with some other unpacker and just unpack it in some folder (/tmp/pwc10012rc1 for example).

Once it is unpacked in that folder, go to that folder, and you should see the Makefile in it.

Do make

Before doing anything else, check to see if you have an older version of pwc installed
  1. go to /lib/modules
  2. do ls -- you should see several folders that indicates your available kernels, for example: 2.6.17-10-generic 2.6.17-11-generic 2.6.17-12-generic
  3. go to whichever kernels (folder) you're using (for example: I use the 12, so i go to it: cd 2.6.17-12-generic)
  4. then do find -name "pwc*.ko*"
  5. if you have an older version of pwc installed, it should give some result like: ./kernel/drivers/usb/media/pwc.ko
  6. Get rid of that old file by doing: rm ./kernel/drivers/usb/media/pwc.ko (make sure you have the right path... If you're not sure, go into the folder where the file pwc.ko is, and do rm pwc.ko from there
Once you got rid of the old pwc, go back to the folder where you unpacked the new pwc, and login as root: sudo su (that's how Ubuntu does it)

Then do make install. What this does is copying the new pwc.ko into the folder where the old pwc.ko used to be. So, another way to do it is to simply copy the new pwc.ko into that folder using the cp command (i.e. cp pwc.ko /lib/modules/2.6.17-12-generic/kernel/drivers/usb/media/) Note that you have to login as root to be able to write or modify anything in those root folders (folders that are located in the ~root directory (which is one folder up from your /home directory))

After all is done, reboot your PC and you should have your Logitech QuickCam Pro 4000 up and running. I used Camorama (installed from the Package Manager) to test it out.

Here's a good website: http://www.noah.org/wiki/index.php/Logitech_QuickCam_Pro_4000_on_Ubuntu

It explains the installation process step-by-step (and far more 'cleaner' than my explanation here). However I got stuck on step 2 (imagine that) when I tried to unpack the file (see the above explanation on unpacking using tar command).

NOTE:
I tried looking the pwc up through the Package Manager. It founds a version: pwc-10.0.12-rc1-1 however, when I installed it, it didn't seem to work. So I would suggest to avoid that for now. Downloading it and installing it from the saillard.org website is straightforward enough, and doesn't cause too big of a headache.
Also, if you tried it from the website and it didn't work, don't panic and grab the libpwc files listed on the site... you don't need it for now. Look around some more (google).

Off we go with some image processing with OpenCV!

Monday, July 23, 2007

My Experience with OpenCV 1.0 + Ubuntu 6.10 - UPDATED

With the help of my awesome brother, I figured out what causes the segmentation fault.

Apparently (as I feared), my whole OpenCV installation is messed up. My recent installation of OpenCV 0.9.7 got mixed up with my earlier OpenCV 1.0. So I had to remove my 0.9.7 (using the Package Manager -- since I installed it using the Package Manager) and uninstall OpenCV 1.0 using make uninstall from the directory where I extracted the OpenCV-1.0.0.tar.gz. Now that I had it cleaned out, this time I re-installed OpenCV 1.0.

To be safe, I used the steps described (once again) in the OpenCV wiki but this time I put the install directory in my home/*myusername* directory -- my profile directory.

./configure --prefix=/home/*myusername*/opencv/1.0.0/
make
make install

In addition to that, i set the LD_LIBRARY_PATH with the directory where my OpenCV library files are located, in this case: /home/*myusername*/opencv/1.0.0/lib

export LD_LIBRARY_PATH=/home/*myusername*/opencv/1.0.0/lib

I didn't have anything in my LD_LIBRARY_PATH before that, so the above is enough. But if I already have something, I want to make sure I don't screw up the existing paths, so I have to include the current paths by adding :${LD_LIBRARY_PATH} at the end. The colon ":" tells bash that whatever comes after it is another path; in this case, is whatever is inside the current LD_LIBRARY_PATH -- that's why I need to use "$" and the curly brackets to indicate the variable name "LD_LIBRARY_PATH".

export LD_LIBRARY_PATH=/home/*yourusername*/opencv/1.0.0/lib:${LD_LIBRARY_PATH}

Now, compile my loadimage.cpp program using the same g++ command as before:

g++ loadimage.cpp -o loadimage -I /home/*myusername*/opencv/1.0.0/include/opencv/ -L /home/*myusername*/opencv/1.0.0/lib -lhighgui -lcv -lml

Yay! It works! The picture showed up, and there was no segmentation fault. *phew* My head was already about to explode trying to figure out how to make this work.

Then, trying the inversion tutorial, and the facedetect (included in OpenCV installation) everything works! Yay! Now I can go on and play around some more. Now I just need to figure out how to use this to detect poses...

Friday, July 20, 2007

My Experience with Ubuntu 6.10 + OpenCV 1.0

FINALLY!!! I'm able to use the OpenCV library on my Ubuntu 6.10!

I've been trying to use the OpenCV 1.0 but apparently (for some reason) it does not work well with my PC. Bear in mind that there could be several reasons, i.e. I didn't set up my Ubuntu, C/C++ compiler, OpenCV correctly (although I already followed the instructions in the OpenCV Wiki... or at least I think I did.) According to the Wiki, to install OpenCV 1.0 I would need to have;
  • GTK+ 2.x
  • pkgconfig
  • libpngzlib ... etc (Please refer to the Wiki if you want to know the complete list)
and so... I did all the steps in the Wiki (including getting all those libraries in the list -- I used the package manager to get them, and the same install path/configurations), up to the point where it says: "If the installation is successful, you get below message after 'make install' command is finished.
----------------------------------------------------------------------
Libraries have been installed in:
/opencv_library_install_path/opencv-1.0.0/lib

... which I never did. So I wondered if it got installed correctly or not. The Wiki tells to do "make check" at the terminal to "... check whether the library is installed properly ..." But when it was finished, it didn't give any confirmation like "Yes, OpenCV is installed properly on your machine" or "No, your machine sucks" or something.

Regardless, I think it's installed so I tried a simple program to just load an image:

// loadimage.cpp
// load an image and display it on a window using OpenCV library

#include <stdlib.h>
#include <stdio.h>
#include <cv.h> // an OpenCV header file
#include <highgui.h> // another OpenCV header file

int main() {
IplImage* img = 0;
// img : variable for the image
// IplImage is a data type for images in OpenCV

img = cvLoadImage(“photo.jpg”, 1);
// load image “photo.jpg”

cvNamedWindow(“mainWin”, CV_WINDOW_AUTOSIZE);
// create a window named “mainWin” to display the loaded image – set on autosize so it matches the dimensions of the image

cvMoveWindow(“mainWin”, 100, 100);
// place the window in the coordinates (x: 100, y: 100) -- the origin (0, 0) is the top left corner of the screen

cvShowImage(“mainWin”, img);
// display the loaded image (photo.jpg) in the created window (mainWin)

cvWaitKey(0);
// do nothing/wait until a key is pressed – then continue to the next line

if (img) printf(“success!”);
// if the image is successfully loaded, print “success!” on the screen

cvReleaseImage(&img);
// clear the memory that was used to load the image
}
// end of program



I tried compiling my program using command such as:

g++ loadimage.cpp -o loadimage -I /usr/include/opencv -L /usr/lib -lhighgui -lcv -lml

..because the .h files are in the /usr/include/opencv folder, and the library files (libhighgui.*, libcv.*, libml.*, and libcvaux.*) are in the /usr/lib folder (I've checked). No compilation errors. All good...? Not quite.

When I run it using:

./loadimage

This is what I got:

OpenCV ERROR: Unspecified error (The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support)
in function cvNamedWindow, window.cpp(71)
Terminating the application...
called from cvUnregisterType, cxpersistence.cpp(4933)
Terminating the application...
called from cvUnregisterType, cxpersistence.cpp(4933)
Terminating the application...
called from cvUnregisterType, cxpersistence.cpp(4933)

Terminating the application...
called from cvUnregisterType, cxpersistence.cpp(4933)
Terminating the application...
called from cvUnregisterType, cxpersistence.cpp(4933)

What the...?? When i removed the cvNamedWindow, cvMoveWindow, cvShowImage, and cvWaitKey, it worked however -- no compilation error, and it displayed "success!" So what's wrong??

Searching through the web, I found several people had very similar problems... however, there's a slight difference (and I don't know how significant this is) that instead of saying:

in function cvNamedWindow, window.cpp(71)

they had:


in function cvNamedWindow, window_lnx.cpp(822)

One of the replies said they were able to solve the problem by installing some other libraries such as: libwxgtk2.4 and libgtk2.0-dev as was said here (but he used Knoppix 4.0.2) -- so I tried installing those (again from the package manager), to no avail.

So I asked my friend who is more familiar with Linux/UNIX environment (I'm still a newbie at Linux)... he recommended that I look into the environment variables and make sure that the directories where the OpenCV library and header files are listed in the PATH. I checked it using:

echo $PATH

Well, it's not there. So I added to the path:

/usr/include/opencv:/usr/lib:/opencv_library_install_path/opencv/lib

to my PATH; I modified the etc/environment file using gedit a
s root:

sudo su (to get into root)
(in etc folder): gedit environment

and add my path there and saved it. I'm curious though, most people said their library is in /usr/local/include/opencv and /usr/local/lib ... peculiar... is it Ubuntu specific? Or something's wrong with my configuration?

Nope, that didn't work -- I still get the same thing: no compilation error, and the same error during execution.

So i tried the next thing mentioned in the Wiki, when compiling the program, set the PKG_CONFIG_PATH variable. Here's the guide.
Nope, still didn't help.

I couldn't find many resources to solve the problem, so finally I tried searching for OpenCV through the package manager -- I found the OpenCV version
0.9.7
for Ubuntu. Being a bit disappointed that I can't get the 1.0, I tried it anyway and the package manager automatically installed it for me. The library and header files are located in: /usr/lib and /usr/include/opencv, respectively but with suffixes 0.9.7 on the file names; so, for example: libhighgui.so is libhighgui0.9.7.so and so on.

And so, now I compile my program using the following:

g++ loadimage.cpp -o loadimage -I /usr/include/opencv/ -L /usr/lib -lcv0.9.7 -lhighgui0.9.7 -lml

..no compilation error. OK... so let's run it

./loadimage

Lo and behold! There's my image, showing up in all its glory!!! It finally worked! I'm so moved that I decided to write this entry and share my excruciating experience with you.

So, what can we get from this experience? Does this mean OpenCV 1.0 does not work with Ubuntu 6.10 yet, and only 0.9.7 works so far? Or, I messed up the installation process and my configurations... If somebody could point that out, I would be so very grateful. It's been a puzzling pain this past few weeks.

However, I don't think it's 100% working well... I still get

Segmentation fault (core dumped)

..after I hit Enter after the image loaded. Not sure what causes this yet.
I guess not many people encountered this problem, so I really would like to know what causes this. I refer to the Wiki a lot and said it didn't work, but don't think I'm blaming it or saying that it is useless ... I refer to it because I think that is the most standard guide for using OpenCV, it should work with properly configured machines -- it just turns out that it didn't work for me and my machine.

I tried some other things under Eclipse as well (setting include & library paths)... but didn't work. But I haven't tried it again after it worked with 0.9.7.

Sorry if the formatting is messed up. I still have yet to figure out how this blogging tool works.