Don’t let the ITU rule the Internet

The ITU did not create the Internet. There was no way it could. The Internet could only be created by engineers who celebrate freedom, openness, sharing, curiosity, innovation and even humor – values that have made the Internet what it is, and which the ITU lacks. As an engineer, this comes across in a striking way when viewing the difference between the contents of technical documents the ITU release (which of course you have to purchase) and those of Internet organizations like IETF (which are free for everyone). The ITU is the old world – it should have no say in the new one.

If you oppose putting the Internet behind bars, voice you opinion on Google’s Take Action page.

.htaccess rewrite for URL parameters

Suppose you have a page at

http://www.example.com/mypage.php?ab=38

but you want people or bots that access it to see this page instead:

http://www.example.com/mypage.php?ab=38&cd=39

By the way, this is not some constrained example – it is from a real production site where the owner has little control over the PHP code.

It took a bit of experimenting plus the help of this answer to arrive at the answer, which is add the following to your .htaccess file:

RewriteEngine on
RewriteCond %{QUERY_STRING} ab=38$
RewriteRule ^mypage.php mypage.php?%{QUERY_STRING}&cd=39

Hope this saves someone some time.

Predicting software development platforms

I’m going to make three predictions today:

  • Cloud vs. PC: The PC is not going to fade into insignificance in the near (1-2 years) or more distant (3-10 years) future.
  • Tablet/Mobile vs. PC: See above.
  • Cross platform development tools are going to rise in popularity.

You are welcome to come back anytime during the next decade and prove me wrong.

Now when I say PC, I’m referring to an independent unit with a strong CPU, a good deal of dynamic and static memory, a large screen and a real keyboard.

I’ve been around long enough to see through hypes and trends. Its always amusing to see a new herd mentality thinking that this or that new technology is going to replace everything. Nothing ever solves everything. I guess its a human wish that a savior will come and with a magic solution solve every problem with one sweep. Life is more interesting and more complex than that. New technologies and methodologies fill a space that was less suited than older technologies, that’s why cloud technologies and mobile technologies are here to stay. But at the same time, old methodologies fill a space that newer ones shouldn’t try to since they will not do it as well. As I ranted on the now inactive JNEXT site, the wisdom is to keep a sense of balance and use the right combination tools and methodologies for the job. Don’t let a specific technology or methodology be your hammer.

Anyway, back to the prediction thing

  • On the Web: expect rising popularity of higher level languages that compile to JavaScript+HTML5.
  • On mobile devices, additional and improved cross platform development frameworks. Native applications will continue to be popular and HTML5 based applications won’t replace them.
  • On PCs, Qt will become more popular being the strongest multiplatform development tool. Qt applications will eventually compile to all popular mobile devices.

Now I’ll hop back to my time machine and wait for 10 years to check this post again.

How many days ago ?

I once created a site that shows you interesting things that happened a round number of days ago. You can also check when you special day birthday is, for example, at what date do you turn to be 17000 days old ?

Although the site even made the news once, I didn’t bother to maintain it, but if you’re interested, take a quick look at the Count In Days site. Perhaps you can surprise someone who isn’t aware a special birthday is coming up soon…

Changing browser associated with html files on Krusader

When I moved from Windows being my default OS to Ubuntu Linux, the thing that I missed the most was Total Commander. Over the years it got so that if I ever found myself on a computer that didn’t have it, I could immediately feel my productivity getting a hit.

On Ubuntu, I used Gnome so the natural replacement for Total Commander was Gnome Commander. Gnome Commander is OK, but it wasn’t a natural replacement for Total Commander and I didn’t feel completely at home with it. I also played with muCommander, which I still use on my Mac OS/X, but at the time it still wasn’t quite there.

I finally found and settled with Krusader. Installing Krusader requires all its’ KDE dependencies but it is well worth it.

So much for the background. I’ve recently been developing some stuff using HTML5. Whenever I’d hit Return or double-click a file with an html extension, Konqueror would launch to display it. The problem is that Konqueror does not do HTML5. I needed to change the associated application for html files but after searching high and low in the Krusader options, I found no way to do this.

The answer was that the file associations aren’t handled by Krusader but by the KDE system settings, and to change those I had to install and launch the KDE application that does that:

sudo apt-get install systemsettings
systemsettings

The first time you launch systemsettings it might whine about not having anything to display. Just close it and run it again. When it opens, click on the icon named “File Associations”. In the text box where it says “Find file type or filename” type “html”. Click the “text” type and select the “html” subtype. On the right you will see the Application Preference order (see below).

KDE system settings
KDE system settings

Select the browser you’d like to be launched when double clicking an html file from Krusader and using the “Move Up” button, click it all the way to the top. Don’t forget to click “Apply”.

Open Krusader again and you’re set to go.

Solving a puzzle with constraint programming

Constraint programming can get some getting used to. In the usual programming frame of mind (whether with functional or imperative languages) you think of the algorithm and specify to the computer, via your code, exactly what steps to go through in order to solve the problem.

With constraint programming, you don’t tell the computer what to do. You describe in detail the nature of the problem and the computer does the rest.

Einstein’s riddle is usually given as an example to be solved with constraint programming, but to be different, I’ll show something a bit trickier. This is the problem (it’s named “Meeting the Challenge”):


Eight married couples meet to lend one another some books. Couples have the same surname, employment and car. Each couple has a favourite colour. Furthermore we know the following facts:

1. Daniella Black and her husband work as Shop-Assistants.
2. The book “The Seadog” was brought by a couple who drive a Fiat and love the colour red.
3. Owen and his wife Victoria like the colour brown.
4. Stan Horricks and his wife Hannah like the colour white.
5. Jenny Smith and her husband work as Warehouse Managers and they drive a Wartburg.
6. Monica and her husband Alexander borrowed the book “Grandfather Joseph”.
7. Mathew and his wife like the colour pink and brought the book “Mulatka Gabriela”.
8. Irene and her husband Oto work as Accountants.
9. The book “We Were Five” was borrowed by a couple driving a Trabant.
10. The Cermaks are both Ticket-Collectors who brought the book “Shed Stoat”.
11. Mr and Mrs Kuril are both Doctors who borrowed the book “Slovacko Judge”.
12. Paul and his wife like the colour green.
13. Veronica Dvorak and her husband like the colour blue.
14. Rick and his wife brought the book “Slovacko Judge” and they drive a Ziguli.
15. One couple brought the book “Dame Commissar” and borrowed the book “Mulatka Gabriela”.
16. The couple who drive a Dacia, love the colour violet.
17. The couple who work as Teachers borrowed the book “Dame Commissar”.
18. The couple who work as Agriculturalists drive a Moskvic.
19. Pamela and her husband drive a Renault and brought the book “Grandfather Joseph”.
20. Pamela and her husband borrowed the book that Mr and Mrs Zajac brought.
21. Robert and his wife like the colour yellow and borrowed the book “The Modern Comedy”.
22. Mr and Mrs Swain work as Shoppers.
23. “The Modern Comedy” was brought by a couple driving a Skoda.

Who likes Violet? And can you find out everything about everyone from this?


A constraint programming solution, using Choco is given below. This should give you some insight into the nature of this type of problem solving.

import static choco.Choco.*;
import choco.cp.model.CPModel;
import choco.cp.solver.CPSolver;
import choco.kernel.model.variables.integer.*;
import choco.kernel.solver.variables.integer.IntDomainVar;
import java.util.HashMap;

public class Meeting
{
    public static void main(String[] args)
    {
        int nElements = 8;

        String[] _attr = { "SURNAME", "EMPLOYMENT", "CAR", "COLOR", "MAN", "WIFE", "LENT", "BORROWED" };
        int SURNAME = 0; int EMPLOYMENT = 1; int CAR = 2; int COLOR = 3;
        int MAN  = 4; int WIFE = 5; int LENT = 6; int BORROWED = 7;

        String[] Surname = { "Black", "Horricks", "Smith", "Cermaks", "Kuril", "Dvorak", "Swain", "Zajac" };
        int BLACK = 0; int HORRICKS = 1; int SMITH = 2; int CERMAKS = 3; int KURIL = 4;
        int DVORAK = 5; int SWAIN = 6; int ZAJAC = 7;
 
        String[] Employment = { "Shop-Assistants", "Warehouse Managers", "Accountants", "Ticket-Collectors",
                                "Doctors", "Teachers", "Agriculturalists", "Shoppers" };
        int SHOP_ASSISTANTS = 0; int WAREHOUSE_MANAGERS = 1; int ACCOUNTANTS = 2;
        int TICKET_COLLECTORS = 3; int DOCTORS = 4; int TEACHERS = 5; int AGRICULTURALISTS = 6;
        int SHOPPERS = 7;
        
        String[] Car = { "Fiat", "Wartburg", "Trabant", "Ziguli", "Dacia", "Moskvic", "Renault", "Skoda" };
        int FIAT = 0; int WARTBURG = 1; int TRABANT = 2; int ZIGULI = 3; int DACIA = 4;
        int MOSKVIC = 5; int RENAULT = 6; int SKODA = 7;
        
        String[] Color = { "red", "brown", "white", "pink", "green", "blue", "violet", "yellow" };
        int RED = 0; int BROWN = 1; int WHITE = 2; int PINK = 3; int GREEN = 4;
        int BLUE = 5; int VIOLET = 6; int YELLOW = 7;
        
        String Man[] = { "Owen", "Stan", "Alexander", "Mathew", "Oto", "Paul", "Rick", "Robert"  };
        int OWEN = 0; int STAN = 1; int ALEXANDER = 2; int MATHEW = 3; int OTO  = 4;
        int PAUL = 5; int RICK = 6; int ROBERT = 7;
        
        String[] Wife     = { "Daniella", "Victoria", "Hannah", "Jenny", "Monica", "Irene", "Veronica", "Pamela" };
        int DANIELLA = 0; int VICTORIA = 1; int HANNAH = 2; int JENNY = 3; int MONICA  = 4;
        int IRENE = 5; int VERONICA = 6; int PAMELA = 7;

        String[] Books = { "The Seadog", "Mulatka Gabriela", "Shed Stoat", "Slovacko Judge", "Dame Commissar",
                          "Grandfather Joseph", "The Modern Comedy", "We Were Five" };
        int THE_SEADOG = 0; int MULATKA_GABRIELA = 1; int SHED_STOAT = 2; int SLOVACKO_JUDGE = 3;
        int DAME_COMMISSAR = 4; int GRANDFATHER_JOSEPH = 5; int THE_MODERN_COMEDY = 6;
        int WE_WERE_FIVE = 7;        
        
        String attvals[][] = { Surname, Employment, Car, Color, Man, Wife, Books, Books };
        
        CPModel model = new choco.cp.model.CPModel();

        // We'll assume the couples are numbered 0 to 7.
        // The value of the variable represents the couple belongs to,
        // i.e if x[SURNAME][BLACK] is 6 then couple with surname Black is couple number 6).
        
        IntegerVariable[][] x = new IntegerVariable[nElements][nElements];
        for (int i=0; i<nElements; i++)
        {
            x[i] = choco.Choco.makeIntVarArray( _attr[i], nElements, 0, nElements-1);
            // For a given attribute, Each different attribute value belongs to a
            // different couple number.
            model.addConstraint(allDifferent( x[i] ));
        }

        //1.  Daniella Black and her husband work as Shop-Assistants.
        model.addConstraint( eq( x[SURNAME][BLACK],
                                 x[EMPLOYMENT][SHOP_ASSISTANTS] ));

        model.addConstraint( eq( x[WIFE][DANIELLA],
                                 x[EMPLOYMENT][SHOP_ASSISTANTS] ));

        //2.  The book "The Seadog" was brought by a couple who drive a Fiat and love the color red.
        model.addConstraint( eq( x[LENT][THE_SEADOG],
                                 x[CAR][FIAT] ));

        model.addConstraint( eq( x[LENT][THE_SEADOG],
                                 x[COLOR][RED] ));
        
        //3.  Owen and his wife Victoria like the color brown.
        model.addConstraint( eq( x[MAN][OWEN],
                                 x[WIFE][VICTORIA] ));

        model.addConstraint( eq( x[MAN][OWEN],
                                 x[COLOR][BROWN] ));

        //4.  Stan Horricks and his wife Hannah like the color white.
        model.addConstraint( eq( x[MAN][STAN],
                                 x[WIFE][HANNAH] ));
        
        model.addConstraint( eq( x[MAN][STAN],
                                 x[COLOR][WHITE] ));

        //5.  Jenny Smith and her husband work as Warehouse Managers and they drive a Wartburg.
        model.addConstraint( eq( x[WIFE][JENNY],
                                 x[SURNAME][SMITH] ));

        model.addConstraint( eq( x[WIFE][JENNY],
                                 x[EMPLOYMENT][WAREHOUSE_MANAGERS] ));

        model.addConstraint( eq( x[WIFE][JENNY],
                                 x[CAR][WARTBURG] ));

        //6.  Monica and her husband Alexander borrowed the book "Grandfather Joseph".
        model.addConstraint( eq( x[WIFE][MONICA],
                                 x[MAN][ALEXANDER] ));

        model.addConstraint( eq( x[WIFE][MONICA],
                                 x[BORROWED][GRANDFATHER_JOSEPH] ));

        //7.  Mathew and his wife like the color pink and brought the book "Mulatka Gabriela".
        model.addConstraint( eq( x[MAN][MATHEW],
                                 x[COLOR][PINK] ));

        model.addConstraint( eq( x[MAN][MATHEW],
                                 x[LENT][MULATKA_GABRIELA] ));

        //8.  Irene and her husband Oto work as Accountants.
        model.addConstraint( eq( x[MAN][OTO],
                                 x[WIFE][IRENE] ));
        
        model.addConstraint( eq( x[MAN][OTO],
                                 x[EMPLOYMENT][ACCOUNTANTS] ));

        //9.  The book "We Were Five" was borrowed by a couple driving a Trabant.
        model.addConstraint( eq( x[BORROWED][WE_WERE_FIVE],
                                 x[CAR][TRABANT] ));

        //10. The Cermaks are both Ticket-Collectors who brought the book "Shed Stoat".
        model.addConstraint( eq( x[SURNAME][CERMAKS],
                                 x[EMPLOYMENT][TICKET_COLLECTORS] ));
  
        model.addConstraint( eq( x[SURNAME][CERMAKS],
                                 x[LENT][SHED_STOAT] ));

        //11. Mr and Mrs Kuril are both Doctors who borrowed the book "Slovacko Judge".
        model.addConstraint( eq( x[SURNAME][KURIL],
                                 x[EMPLOYMENT][DOCTORS] ));

        model.addConstraint( eq( x[SURNAME][KURIL],
                                 x[BORROWED][SLOVACKO_JUDGE] ));

        //12. Paul and his wife like the color green.
        model.addConstraint( eq( x[MAN][PAUL],
                                 x[COLOR][GREEN] ));

        //13. Veronica Dvorak and her husband like the color blue.
        model.addConstraint( eq( x[SURNAME][DVORAK],
                                 x[WIFE][VERONICA] ));

        model.addConstraint( eq( x[SURNAME][DVORAK],
                                 x[COLOR][BLUE] ));

        //14. Rick and his wife brought the book "Slovacko Judge" and they drive a Ziguli.
        model.addConstraint( eq( x[MAN][RICK],
                                 x[WIFE][VERONICA] ));

        model.addConstraint( eq( x[MAN][RICK],
                                 x[LENT][SLOVACKO_JUDGE] ));

        model.addConstraint( eq( x[MAN][RICK],
                                 x[CAR][ZIGULI] ));

        //15. One couple brought the book "Dame Commissar" and borrowed the book "Mulatka Gabriela".
        model.addConstraint( eq( x[LENT][DAME_COMMISSAR],
                                 x[BORROWED][MULATKA_GABRIELA] ));

        //16. The couple who drive a Dacia, love the color violet.
        model.addConstraint( eq( x[CAR][DACIA],
                                 x[COLOR][VIOLET] ));

        //17. The couple who work as Teachers borrowed the book "Dame Commissar".
        model.addConstraint( eq( x[EMPLOYMENT][TEACHERS],
                                 x[BORROWED][DAME_COMMISSAR] ));
        
        //18. The couple who work as Agriculturalists drive a Moskvic.
        model.addConstraint( eq( x[EMPLOYMENT][AGRICULTURALISTS],
                                 x[CAR][MOSKVIC] ));

        //19. Pamela and her husband drive a Renault and brought the book "Grandfather Joseph".
        model.addConstraint( eq( x[WIFE][PAMELA],
                                 x[CAR][RENAULT] ));

        model.addConstraint( eq( x[WIFE][PAMELA],
                                 x[LENT][GRANDFATHER_JOSEPH] ));

        //20. Pamela and her husband borrowed the book that Mr and Mrs Zajac brought.
        for (int book = 0; book<nElements; book++)
            model.addConstraint( ifOnlyIf( eq( x[WIFE][PAMELA],
                                               x[BORROWED][book] ),
                                           eq( x[SURNAME][ZAJAC],
                                               x[LENT][book])));
        
        //21. Robert and his wife like the color yellow and borrowed the book "The Modern Comedy".
        model.addConstraint( eq( x[MAN][ROBERT],
                                 x[COLOR][YELLOW] ));

        model.addConstraint( eq( x[MAN][ROBERT],
                                 x[BORROWED][THE_MODERN_COMEDY] ));
    
        //22. Mr and Mrs Swain work as Shoppers.
        model.addConstraint( eq( x[SURNAME][SWAIN],
                                 x[EMPLOYMENT][SHOPPERS] ));

        //23. "The Modern Comedy" was brought by a couple driving a Skoda.        
        model.addConstraint( eq( x[LENT][THE_MODERN_COMEDY],
                                 x[CAR][SKODA] ));

        // Create the solver
        CPSolver solver = new CPSolver();
        solver.read( model );

        // solver.solve();
        solver.solveAll();

        if (!solver.isFeasible())
            return;
        
        int colWidth[] = calcAttrWidths(_attr, attvals);

        do 
        {
            IntDomainVar[][]  s = new IntDomainVar[nElements][nElements];
            HashMap<Integer, String[]> couples = new HashMap<Integer, String[]>();

            System.out.print( "         ");
            for (int i=0; i<nElements; i++)
            {
                s[i] = solver.getVar( x[i] );
                couples.put( i, new String[ nElements ] );
                System.out.print( padRight( _attr[i], colWidth[i]) );
            }
            System.out.println();
            
            for (int i=0; i<nElements; i++) // iterate over attributes
                for (int j=0; j<nElements; j++)  // iterate over attribute values
                {
                    //  s[i][j].getVal() is the couple number where attribute i
                    //              has an attribute value of j
                    
                    int coupleNumber = s[i][j].getVal();
                    String[] attrs = couples.get( coupleNumber );
                    attrs[i] =  attvals[i][j];
                }

            
            for (int couple=0; couple<nElements; couple++)
            {
                System.out.print( "couple " + (couple+1) + ":" );
                String[] attrs = couples.get( couple );
                for (int attr=0; attr<nElements; attr++)
                    System.out.print( padRight( attrs[ attr ], colWidth[ attr ] ) );
                System.out.println();
            }
            System.out.println("---------------------");
            solver.printRuntimeStatistics();
        }
        while (solver.nextSolution() == Boolean.TRUE);
    }
    
    public static String padRight(String s, int n)
    {
         return String.format("%1$-" + n + "s", s);  
    }
    
    public static int[] calcAttrWidths(  String[] attrs, String[][] attvals )
    {
        int nElements = attrs.length;
        int[] atmax = new int[ nElements ];
        for (int i=0; i<nElements; i++)
            atmax[i] = attrs[i].length()+1;

        for (int i=0; i<nElements; i++)
        {
            int max = atmax[i];
            for (int j=0; j<nElements; j++)
            {
                int lenVal = attvals[i][j].length();
                if ( max < lenVal )
                    max = lenVal;
            }
            atmax[i] = max + 1;
        }
        return atmax;
    }

}

Constraint Programming

Constraint programming is a field that is about solving problems where you have to find a solution in a (usually large) search space given specific constraints. A classic problem of this sort is the eight queens puzzle.

There are quite a few good constraint program libraries, among them are java based Choco and C++ based Gecode.

At first I didn’t understand why such powerful libraries provide the eight queen puzzle as an example that can be solved using constraint programming, as it is trivial to generate all the solutions to the eight queens puzzle with simple DFS. I wrote the following C program to illustrate this (which actually shows all the solutions to the n queen problem using Depth First Search):

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    int *lines;
    int s,i, currentLine;


    if ( argc != 2 ) {
        printf( "Usage: nqueens <board-size>n" );
        return -1;
    }

    s = atoi( argv[1] );

    if ( s < 1 ) {
        printf( "Board size must be a positive number.n" );
        return -1;
    }

    lines = (int*) malloc( s * sizeof( int ) );

    for ( i=0; i < s; i++ ) {
        lines[ i ] = 0;
    }
    currentLine = 0;

    // begin the DFS
    while ( currentLine > -1 ) {
        while ( lines[ currentLine ]<s && !safe(currentLine, lines) )
            lines[ currentLine ]++;

        if ( lines[ currentLine ] == s ) {
            lines[ currentLine ] = 0;
            currentLine--;
            if ( currentLine > -1 )
                lines[currentLine]++;
            continue;
        }

        if (currentLine == s-1) {
            for (i=0; i<s; i++)
                printf( " %d", lines[ i ] );
            printf("n");
            lines[ currentLine ]++;
            continue;
        }

        currentLine++;
    }

    free( lines );
}

int safe( int currentLine, int* lines ) {
    int i;

    for ( i = currentLine-1; i > -1; i-- ) {
        if ( lines[ currentLine ] == lines[ i ] ||
                abs( lines[currentLine]-lines[i]) == (currentLine-i) )
        {
            return 0;
        }
    }

    return 1;
}

However, when the number of queens grows, the time it takes for the naive DFS method above grows much faster, and getting all the solutions for 30 queens and higher required waiting more time than I had patience for.

I then tested what Choco and Gecode could do with the same problem and was amazed. Both libraries generated results in seconds for 300 queens and higher. Note that each added queen exponentially expands the search space so this is very impressive.

Combining Qt and OpenCV

Before writing a minimal sample for some technology, I usually take the time to see if there already exist one on the net. For a simple example that illustrates how to combine Qt and OpenCV I found the following post. Just download the project at the end of that post.

This post explains compiling the sample code using Qt Creator.

Mac OS/X

In previous posts, I’ve mentioned how to install Qt and OpenCV on the OS/X by manually downloading and building them, however, the shortest route to get the above sample to compile and run on the Mac is to install Qt and OpenCV as follows:

brew install opencv
brew install qt

if you get errors during one of these installations, look at the message – its usually solvable by adding write permissions to the folder mentioned in the message. Note that its best that you uninstall any previous versions of Qt and OpenCV prior to doing that.

The ShowImage sample also requires pkg-config which is not installed by default. For that simply

brew install pkg-config

Again the above works great and saves you manually installing all the dependencies of pkg-config.

At this point, launch Qt Creator, and open the project ShowImage.pro
When you build the project you could get the following error during the build:

sh: pkg-config: command not found

At first I thought it was strange since invoking pkg-config from the command line worked, so it was definitely in the search path (which was confirmed by invoking which pkg-config from the command line). After some searching I realized that Qt Creator does not use the shell path to look for pkg-config. In order to let Qt Creator know where to find pkg-config you should explicitly add the path to the build environment by clicking the Projects icon on the left and adding the path the pkg-config in the Build Environment details (see below).

Qt Creator Build Envoronment
Qt Creator Build Environment

On Ubuntu

Loading and compiling the ShowImage.pro in Ubuntu had it’s own problems. Compilation failed with an error of

bits/predefs.h: No such file or directory

which was somewhere along the include tree required by Qt4.

I found the answer to this here and a sudo apt-get install gcc-multilib solved that compilation issue. This seemed strange since my ubuntu is a 32-bit installation and this solution was to install 32-bit headers on a 64-bit system – but for the time being I let that slide. However this left me with this new hurdle:

moc_mainwindow.cpp:14:2: error: #error "This file was generated using the moc from 4.7.3. It"
moc_mainwindow.cpp:15:2: error: #error "cannot be used with the include files from this version of Qt."
moc_mainwindow.cpp:16:2: error: #error "(The moc has changed too much.)"

A solution for this was explained by Anjum Kaiser here and indeed a

make distclean
qmake
make

from the command line resulted in an executable that worked.

However I wanted to make sure I can build a working executable from Qt Creator and attempting to build the project from Qt Creator after make distclean from the command line, returned the following error:

libopencv_calib3d.so: could not read symbols: File in wrong format

This got me thinking about the 32-bit/64-bit issue and it dawned on my that Qt Creator might not be building the project the same way it is built from the command line. A quick look in the Qt Creator projects configuration showed that indeed g++64 was specified instead of g++32. Fixing this (below) enabled smooth compilation.

Qt Config configure g++32 on Ubuntu
Qt Config configure g++32 on Ubuntu

However – when attempting to run the app – yet another surprise:

error while loading shared libraries: libopencv_highgui.so.2.4: 
cannot open shared object file: No such file or directory

a locate libopencv_highgui.so (remember to sudo updatedb first) showed that the library exists at /usr/lib but the loader doesn’t know about it. The next step was then sudo vi /etc/ld.so.conf, adding /usr/lib to the end of the file and finally sudo ldconfig.

This, finally, did the trick and the app could be successfully compiled and launched from within Qt Creator on Ubuntu 12.04

Installing OpenCV

OpenCV is considered by many to be the best open source computer vision library. It has versions for Windows, Linux, Mac, iOS and Android. As Windows installation is usually easier, I’ll focus on Linux/Mac.

OpenCV uses cmake (Cross Platform Make) to configure and build the library. You can download cmake for the relevant platforms here (unless you’re interested in compiling it, I suggest downloading the binary distribution).

Once cmake is installed (make sure its in the path by running cmake from the command line), download the OpenCV sources for Linux/Mac (a tar’ed bz2 archive) and extract them to a directory. Next, cd to that directory and issue:

cmake .
make
sudo make install

if you need to uninstall for any reason just issue sudo make uninstall from the same directory.

On OS/X a simpler (and possibly better option) is brew install opencv (brew), which will automate all the above.

Qt learning curve journal, part II

Being able to make and run the Qt samples is cool, but to really dig into learning a framework I prefer to have the ability to easily navigate to declarations, easily debug, auto completion, in short – an IDE.

There are two options that I recommend. The first is QtCreator – the IDE that comes with Qt. Although the site claims that “Qt Creator IDE can also be downloaded as a standalone application, although we recommend to get it via the SDK above if you need a complete Qt development environment”, I haven’t managed to find in in the SDK bundle. However you can download binary and source versions from here.

The second option is NetBeans which the cross platform IDE I’ve liked the most since I first tried it in back in 2003. I checked if it has built-in support for Qt. It does.

For developing Qt applications you need only download the smaller sized NetBeans for C++ from this page. You can easily create, compile and run a Qt project from NetBeans by following the explanation on this page.

Having done this, you have access to all the NetBeans goodies when developing your Qt application.

I’m sure Qt will work well with eclipse and other frameworks, though I haven’t checked and therefore can’t comment on them.