Monday, 5 March 2012

Pencil Sketches using C++ and OpenCV


When I changed my profile picture in FB to a thresholded image of a grayscale image of a picture of me looking at the computer monitor, taken from a Kinect at 45 degree angle and kept at table height (which is much lower than my neck), little did I know that my friends wouldn't believe that I indeed did it using C++ and OpenCV and not with photoshop.

Here is my present Profile Pic on FB :-
In order to make a sketch of a scene,  all you have to do is to take a picture of it and do a little bit of image processing on it. A picture is a combination of one to four two-dimensional matrices. We call each matrix as a channel. An RGB image has 3 channels. A QImage(a QT abstraction for images) has 4 channels by default, one extra channel for alpha. 

The Algorithm to do this would be something like this :-

1. Capture an RGB image using a camera
2. Convert it into a grayscale image
3. Threshold it to convert it into a binary image

Ta-Da!! That's it. Looks simpler than the algorithms we wrote in 1st semester of college. 

The first step is capturing a RGB image. Plug-in your camera to your computer. A driver is required to use the camera with the computer. The drivers might already be available for your camera, or easily available at the vendor websites. Okay, now OpenCV can  use the drivers available to get the picture from your camera. Thank god for OpenCV. 

OpenCV's API for this is cvCaptureFromCAM(int index).

This API returns a structure of type CvCapture. You can use this to read images from, by using another API cvQueryFrame, which returns a Image in Intel Picture Library Format. 

Too much technical stuff here, so what I talked about so far was just the first part. Put this in a loop and you can capture streaming video.

This is a Picture of my new Iphone 4S taken with my laptop's iSight Camera.



The next step is to convert the image into a grayscale image. I wanted to explain this part in as much detail as possible, so went through the OpenCV source files to really understand how this works under the hood, and this is what I understood.

The formula used by OpenCV to convert RGB to Gray scale is given by :

RGB[A]->Gray: Y<-0.299*R + 0.587*G + 0.114*B

This is done by the command cvCvtColor(srcImg, destImg, CV_RGB2GRAY);
Pretty straight forward. Now, to the important question here, why convert this image into a GrayScale image and not directly threshold it. Thresholding directly works on three channels independently. We would not end up with our desired results if we thresholded the 3 channel image, but rather with a color picture which has messed up color composition of the picture. Therefore, we convert it into a single channel 8-bit image from a 3 channel 8-bit image using the above formula.

This is the Image after converting it to a single channeled grayscale image :-


The next step is convert this into a Binary Image, or the Sketch. This is done by using a simple thresholding logic such as :
pixel(x,y) = White, if pixel(x,y)>threshold 
Black, otherwise

This is also called as Binary Threshold.  This is done by the command Threshold(srcImg, destImg, thresholdValue, maxValue, thresholdType). It is important that this threshold value is carefully chosen. The value here mostly varies upon lighting conditions. In very bright conditions, set it to a value around 30 - 50. In very Dark Condition, it should be between 7  and 20. The intermediate value is for intermediate lighting. Now, obviously threshold is  pixel value and here, each pixel is  represented by a 8-bit number so we can have 256 different values(Range : 0- 255). In my program, this is normalized to a scale of 0-1 for a more intuitive experience.

This is the Sketch of the image previously taken with threshold = 16 :-

I could have had better results, if I had set the threshold properly. This is another sketch of the same subject. This is a little better (Threshold = 128) :-



So there you go, that's all folks. See, making a sketch of is pretty simple with C++.
You can download the code from this link :-

Sunday, 26 February 2012

Copying and Tiling with OpenCV

Recently,a friend of mine asked, how to perform the matlab function repmat(A,m,n) in opencv.
Okay, for those of you, who want to know what repmat does, this is a normal image


a.k.a Normal Image

Now, after you tile it, this is what it looks like
a.k.a tiled image
This is the basic functionality of repmat

Now, If you are new to OpenCV, this might seem a little hard at first. But I'll explain with the code first and if you still have any doubts, send me a mail.

The basic operation is simple, copy the source image into a specific region of the destination image. Repeat this n times. Here, two questions might arise, How do you copy the original image and how the hell do you choose the region. The answer to your questions can all be found in the explanation with code section below :-

Wednesday, 28 December 2011

Installing Kinect SDK on Windows XP

Kinect is Microsoft's idea of "Bulk Advertising". They managed to promote two of their major products in their production line with a cheap, yet feature-rich piece of hardware. Note : If you're a gamer looking to buy a kinect, I suggest you leave this blog, but if you are interested in hacking the Kinect, continue reading.
   

Cheap camera, combined with free software and licenses really helped the Kinect penetrate the market. There was just one problem with this. The Kinect SDK installs only on  Windows 7. It is a significant investment to obtain Windows 7, its licenses, Visual Studio 2010 and its licenses just to work with one piece of hardware. Atleast, I wouldn't pay for it. So I went on to download the Kinect SDK to see it for myself. I thought maybe a few features might work and that's all I might need for now. Who knows?

I downloaded the KinectSDK-v1.0-beta2-x86.msi- its a 20.8 MB file that takes around 5 mins to download on a decent broadband connection. After downloading, I double clicked on the file to see what happens, I also had plans of choosing "Custom Install" and trying out various combiantions of sub-packages to see if a few features worked and others did not. Well, The installer started and this screen came:-


This showed that the installer checks for the OS-version before even starting. So I did a little research on   windows pakage installers' editors, and found this great software that allows you to edit Windows installers - or one might say these typical .msi file editors. Orca is a freeware and is available at the first link in google search for "orca download". This is the picture of KinectSDK-v1.0-beta2-x86.msi opened with orca:-





After browsing through the tables with Orca, I found this interesting one called LaunchCondition.You can see it here:-


This table stores the pre-requisite information. There it was, a description line saying, it requires Windows 7 or higher. But what do you change it to? So, after googling the version number of Windows XP, I found that there were several, but like every other versioning system, it started from 0 and went upwards. At this point, it was obvious, I made "Installer OR VersionNT" >= 0 . It sounded logical at that point. It is checking for the version. If I say >= 0,it should support any version of windows, right? 



Fingers crossed, I saved the edited installer and started the setup again. Voila! It worked. It actually worked. I'm going to test the SDK out now. Adios!