Thursday, April 22, 2010

Python Image Library - Part 2: OpenCV

Now that I have my PIL installation working it's time to get some complicated image processing done and OpenCV is, pretty much, the best choice out there at the moment - especially since it's development became active again and numerous bugs have been fixed, new functions added, etc.

This FAQ at the very bottom of the page points to an adaptors.py module that has the functions to convert back and forth between Ipl & PIL and Ipl & numpy. The module does indeed come with the latest distribution of OpenCV. Unfortunately, it has not been updated since about version 1.0...

Fear not, with few minor tweaks to accommodate new IplImage structure you can get it to load your PIL Image into the IplImage. (Later I found the code that essentially does the same here).

So what now you ask? Yes it worked. Kind of. The image of red strawberry comes out as a bright blue strawberry once converted to Ipl. It appears that the kind soul at OpenCV that provided the conversion code entirely missed the issue of Ipl images being BGR while PIL Image is RGB. Mind you, it works in the opposite direction as PIL has two mode input parameters: one for input image mode and one for the output image mode, so it just knows to shift the color bits.

Back to searching. There seems to be a good number of solutions consisting of complicated pixel-by-pixel shifting, flipping, etc. Many of them rely on old OpenCV CvMat and IplImage structures where you actually had access to the data directly in a linear array fashion. I must say, while trying to get said solutions to work I got some very entertaining variations on the display of that strawberry.

And then, I found it. And I mean The IT solution. I was actually searching for some different approach keyword and the result was a preview of a PIL Handbook. So here is the solution:

pi=Image.open("image.jpg")
r,g,b=pi.split()
pi2=Image.merge("RGB",(b,g,r))

That's all. Now you have your BGR-ready image that you pass along to the IplImage, which comes out with the strawberry being a correctly-red colour.

Here's the entire conversion code from the PIL cookbook with this fix added:

import Image, cv
pi = Image.open('building.jpg') # PIL image
cv_im = cv.CreateImageHeader(pi.size, cv.IPL_DEPTH_8U, 3)
r,g,b=pi.split()
pi2=Image.merge("RGB",(b,g,r))
cv.SetData(cv_im, pi2.tostring())


Enjoy :)

Python Image Library - Part 1

I love Python. I love it's simplicity and immediate gratification in the form of immediate result without endless makefiles and compilation errors. So, for one of my unreasonable project ideas I have decided to use Python - especially since I finally managed to get down to the Interface Builder and Cocoa programming that I've been avoiding and that I'm starting to get a hang of.

One part of the project receives camera frame images in a packed binary format. Luckily, I have found some code online that shift-unpacks it into a buffer that can then be directly passed to the PIL Image class. So, now all I have to do is get PIL onto my Snow Leopard. Sounds simple, right?

Welll..... This is where it all started going bad. I got bit by (turns out infamous) "***The _imaging C module is not installed" error. There seems to be a small number of possible fixes that have worked for some but not others that have encountered it. The solutions ranged from re-installing all involved libraries to downgrading to libjped6b (while current version is 8) to force-recompiling everything into 32 bits. I've tried them all except for the 32 bit suggestion - I just migrated all my libraries to 64 bit after upgrading from OS 10.5 to 10.6 and I wasn't about to start messing it all up again.

So, after days of looking for alternatives I decided to give it another day. On one of the posts that I found someone stated that PIL is asking for libjpeg6b specifically and you cannot expect it to work with version 7! So I fink downloaded version 6b, pointed the JPEG_ROOT to /sw/lib, etc. Guess what - it didn't work. In fact, it got all unhappy as version 6b has wrong architecture!

Then I had a moment of enlightenment - "fink remove libjpeg, libjpeg-bin, libjpeg-shlibs" (My shlibs failed to remove because of numerous dependencies but the most important thing is that the other two are NOT on your system). I went through all the places that could have retained any old version of libjpeg making sure to remove them all. Once I had only the latest libjpeg left compiled for x86_64 (which happens by default on 10.6) PIL build worked.

So there you have it. Hope this helps someone else out there tearing through the good, the bad, and the ugly of open source.