Thursday, May 31, 2012

Experiences with VMWare Workstation 8.0.3 – The good,bad and the ugly


VMs( virtual machines) are the fundamental unit of the cloud. So I was interested in getting my hands around virtualization and virtual machines. Fortunately VMWare's Workstation provides you with the opportunity. VMWare gives the user a 30 day evaluation license to evaluate Workstation 8.0.3. So I downloaded VMWare's Workstation 8.0.3 to my desktop in Windows XP. If you had read my earlier post “Installing and configuring Fedora 16 with Windows XP using a bootable USB”  I had a dual boot desktop running either XP or Fedora 16.
Installing and getting Workstation 8.0.3 started was a breeze. I then created a VM using the Fedora 16 ISO file which I had downloaded for creating the dual boot Fedora & XP. The Workstation created a VM for me in a couple of minutes. As before the VM running Fedora 16 has LiveCD in its top right corner. Or in other words it is running the OS of a virtual CD. Anyway it was great and seemed really easy to get started.
The Ugly: I wanted to do more things with the VM. I read up the documentation on “Using the WorkStation” etc.  I wanted to install the VMWare Tools, clone a VM, save a snapshot etc. When I tried to install Vmware Tools I got a message saying the CDRom was in use. I checked the setting and found the CDRom was being used to boot Fedora. I actually needed to “install to disk”. .  As in previous post I decided I needed to create free space. Unfortunately I got ahead of myself I think. While the workstation was running I tried to access Windows Disk Management. This took a long time and I also got a message saying that the device was busy. As an afterthought it appears perfectly reasonable as the Workstation must have allocated space for the VM on the disk and must have held the disk. My disk had a primary partition C: drive with Win XP, a free logical drive D: and a partition holding my Fedora 16. I foolishly deleted drive D: This is where all hell broke loose. This took a long time. When I opened Disk Management again I found that the values it was showing was out of whack. It was C: drive 1820 GB when it should have been 70GB. D:drive as 2087 GB and also sorts vague figures. I realized that I had messed up my disk.

Here a thought struck me. Maybe if I restart the system the OS will work things out. But alas when I rebooted I got this
error: No such partition
grub rescue>
I knew I had really messed up. I could not boot my system. As I had mentioned before I could not boot Windows from my CD drive as it did not work. After trying a couple of different things I tried to boot with my USB drive.
Thank God I was able to boot Fedora. I then used fdisk to see my partitions. I realized I had clobbered my 2nd partition which was showing an incorrect size. I used fdisk to set the size right. I then installed Fedora 16 on my PC by writing to disk. Unfortunately I lost my XP drive and I was left with a Linux only PC. Thanks to my fortune there was no data that I had lost. This was a new PC which I had got.
The Bad: Now with Fedora 16 up and running I decided I thought I will try to install Workstation 8.0.3 on Fedora 16. I downloaded Workstation 8.0.3 bundle and extracted it. But when it tried to run it I ran into my 1st problem.
Cannot load module pk-gtk-module & canberra-gtk-module and I also got a message “Failed”
So with some googling I found that I needed to do
yum install PackageKit-gtk-module &
yum install libcanberra-gtk2 libcanberra-gtk3 libcanberra-gtk2.i686 libcanberra-gtk3.i686
I also got the message that some kernel files needed to be compiled. When I went and checked
/lib/modules/3.1.0-7.fc16.i686 I founf that the “build” link was broken.  So I set off on another google search on how to fix the fedora build broken situation. Finally I found the answer here
I did a
yum install kernel-devel
As mentioned in the link above I rebooted the system. This seemed to create
/lib/modules/3.3.7-1.fci6.686.
The build in this directory was fine. Also giving uname -a showed that the kernel was updated to the new version.
I tried to start the Workstation 8.0.3 again. Now the number of complaints was less. I got a message saying the files needed to be compiled. When I clicked ok it went through the compilation process. I knew I was making progress. But anyway it once again bailed out with
Gtk-Message: Failed to load module "pk-gtk-module": libpk-gtk-module.so: cannot open shared object file: No such file or directory
Gtk-Message: Failed to load module "canberra-gtk-module": libcanberra-gtk-module.so: cannot open shared object file: No such file or directory
It appears that there is a patch which needs to be applied to fix the kernel. I used the following from this post
http://communities.vmware.com/thread/343441
I downloaded workstation-8.0.2-linux3.2patch (15K) and ran the commands
cd /usr/lib/vmware/modules/source
tar xfv vmnet.tar
patch -p0 < ~/workstation-8.0.2_linux-3.2.patch
tar cfv vmnet.tar vmnet-only/
vmware-modconfig --console --install-all
Though my workstation 8.0.3 this went through fine.
I also did
LD_LIBRARY_PATH=/usr/lib/gtk-2.0/modules
export LD_LIBRARY_PATH
I started the workstation 8.0.3 and lo and behold it finally came up.
I then downloaded Fedora 17 ISO file (http://fedoraproject.org/en/get-fedora-options( and created a VM with that. My PC with about ~ 1G ram groaned. It tool nearly 20 mins to be up and running.
The searching and fixing took me nearly 7 – 8 hours. I was finally able to get workstation 8.0.3 up and running with Fedora 17 VM. Do take a look at the good part of VMWare Workstation 8.0.3 : Sneak preview of Windows 8 with VMWare Workstation 8.0.3



Tuesday, May 29, 2012

Installing and configuring a dual boot Fedora 16 with Windows XP using a bootable USB


Here the steps to create a  dual boot of Fedora 16 with Windows XP using a bootable USB. I was forced to install from a USB as my DVD/CD drive had other ideas and wouldn’t read my Fedora 16 DVD.
Anyway creating a dual boot option with a USB was fairly straightforward.  I have outlined the steps below
1)       Download an image of Fedora 16 based on your hardware architecture. I downloaded Fedora 16 (Fedora-16-i686-Live-Desktop .iso) from this sitehttp://fedoraproject.org/get-fedora
2)       Next download and install the LiveUSB creator fromhttps://fedorahosted.org/liveusb-creator/
3)       Insert your USB stick into a USB slot.
4)       Run the LiveUSB creator. This will detect your USB stick. (It is possible to skip step 1 and have the LiveUSB creator download the Fedora 16 image but I was getting a SHA error. So it is better to go through Step 1)
5)       In the LiveUSB Creator window, click browse and open your downloaded ISO image, Fedora-16-i686-Live-Desktop .iso. Set the persistent storage to around 750 MB and then click create USB
6)       This will verify your download and create a bootable USB stick for you.
7)       At this point you would have to do the following. For a dual boot option you need to create free space on your disk on which you can install your Fedora 16.So I did the following. I had a primary partition C drive with 70GB and an extended partition with the logical drive D. Fortunately my PC had no data. So I deleted the D drive and then created an extended partition with 35 GB and left around 35 GB of free space.
8)       Now restart your PC. Before it boots hit F2 so that you get the BIOS setting.
9)       Go to the “boot” tab and choose Boot from USB and click Enable. Save your settings with F10.
10)   With your USB still in the USB slot the PC will continue to boot but will do so from the USB stick
11)   The system will continue to Boot. Select Start Fedora 16. The right corner should show LiveCD
12)   Click Applications. You should see “Install to hard drive”
13)   Click this. At this point please see these 2 links as they have many screen shots for configuring Fedora 17
14)   I followed these links except the step “Installation Type”. Here I chose the 4th Option “Use Free space” which I had created for 35 GB. This does not touch your data & files.
15)   In the Select Storage devices make sure you choose the “Data Storage device” (your free space) and move it right to “Install target devices”
16)   You will get a Confirm changes to disk popup. Choose write changes to disk.
17)   The installation will start and will install your Fedora 16.
18)   You can then set system time, create users etc.
19)   Your Fedora 16 installation is now ready.
20)   You might want to restart the system. You will see now options to either boot from Fedora 16 or Windows XP.
I would suggest that you select F2, go to the boot tab and disable the boot from USB first option. Now you have a dual boot option Fedora 16 or Windows XP.

Monday, May 14, 2012

Re-working the Lucy Richardson algorithm in OpenCV



Here is my latest attempt at deblurring using the Lucy-Richardson algorithm. For this I looked up the chapter on Iterative deconvolution and the Lucy Richardson algorithm in scribd.
As mentioned in my previous post the blurred image can be represented as
We can represent the ill-posed blurring problem as
b(x,y)  = i(x,y) ** k(x,y) + n(x,y)
where b(x,y) is the blurred image,  i(x,y) the original image, k(x,y) the blur kernel and n(x,y) the noise function. If our estimate of the original image is good then n(x,y) = 0
Hence b(x,y) – i(x,y) ** k(x,y) = 0
If we add i(x,y) to both sides of the equation we have
i(x,y) = i(x,y) + b(x,y) – i(x,y) ** k(x,y)
This can be represented iteratively as
ik+1(x,y) = ik(x,y) + b(x,y) – ik(x,y) ** k(x,y)  (1)
The underlined terms is the error correction.
We have to add the previous estimate with the error correction to get the new estimate.
Now we can seed this by setting ik(x,y) with the blurred image.
Hence our iteration 1 we would substitute
ik(x,y) = b(x,y) in Eqn (1)
So I have done this as follows
I have chosen a blur kernel
double a[9] = {0,40,0,0,40,0,0,40,0};
In the 1st iteration I convolve the blurred image with the kernel
cvFilter2D(im,im_conv_kernel,&kernel1,cvPoint(-1,-1));  – A
To get the error correction I subtract with the convolved term
cvSub(im,im_conv_kernel,im_correction, 0);  – B
Now I add the previous estimate with the error correction to get the new estimate
cvAdd(im,im_correction,im_new_est,NULL);   – C
Finally I repeat the process
im = im_new_est;
im = cvCloneImage(im_new_est);   – D
The convolved image, the error correction and the estimates of the nth iteration is shown below
The 7th,8th and 9th iteration are shown below
The complete code is given below
// deconvlucy.cpp : Defines the entry point for the console application.
//
// ===================================================================================================================================
// ========================================================Lucy-Richardson algorithm ===================================
//
// Author: Tinniam V Ganesh
// Developed 14 May 2012
// File: deconvlucy.cpp
//=====================================================================================================================================
#include “stdafx.h”
#include “math.h”
#include
#include
#include
#define kappa 10000
int main(int argc, char ** argv)
{
IplImage* im;
IplImage* im_conv_kernel;
IplImage* im_correction;
IplImage* im_new;
IplImage* im_new_est;
IplImage* im1;
char str[80];
int i;
CvMat* cvShowDFT1(IplImage*, int, int,char*);
IplImage* cvShowInvDFT1(IplImage*, CvMat*, int, int,char*);
im1 = cvLoadImage(“kutty-1.jpg”);
cvNamedWindow(“Original-Color”, 0);
cvShowImage(“Original-Color”, im1);
im = cvLoadImage(“kutty-1.jpg”, CV_LOAD_IMAGE_GRAYSCALE );
if( !im )
return -1;
cvNamedWindow(“Original-Gray”, 0);
cvShowImage(“Original-Gray”, im);
// fk+1(x,y) = fk(x,y)
for(i=0;i < 10;i++) {
// Convolve f0(x,y)= g(x,y) with blur kernel
// f0(x,y) ** kernel
// Create a blur kernel
//double a[9]={-1,200,1,-1,200,1,-1,200,1};
//double a[9]={0,-1,0,-1,4,-1,0,-1,0};
//double a[9]={-4,40,4,-4,40,4,-4,40,4};
//double a[9]={-1,2,-1,-1,2,-1,-1,2,-1};
double a[9] = {0,40,0,0,40,0,0,40,0};
CvMat kernel1 = cvMat(3,3,CV_32FC1,a);
// Convolve the kernel with the blurred image as the seed i0(x,y) ** k(x,y)
im_conv_kernel= cvCloneImage(im);
cvFilter2D(im,im_conv_kernel,&kernel1,cvPoint(-1,-1));
cvNamedWindow(“conv”, 0);
cvShowImage(“conv”, im_conv_kernel);
// Subtract from blurred image. Error correction = b(x,y) – ik(x,y) ** k(x.y)
im_correction = cvCreateImage(cvSize(383,357),8,1);;
cvSub(im,im_conv_kernel,im_correction, 0);
cvNamedWindow(“Sub”, 0);
cvShowImage(“Sub”, im_correction);
// Add ik(x,y) with imCorrection – ik(x,y) + b(x,y) – ik(x,y) ** k(x,y)
im_new_est = cvCreateImage(cvSize(383,357),8,1);;
cvAdd(im,im_correction,im_new_est,NULL);
cvNamedWindow(“Add”, 0);
cvShowImage(“Add”, im_new_est);
sprintf(str,”Iteration – %d”,i);
cvNamedWindow(str, 0);
cvShowImage(str, im_new_est);
//Set the estimate as the previous estimate and repeat
im = im_new_est;
im = cvCloneImage(im_new_est);
}
cvWaitKey(-1);
return 0;
}

Friday, May 11, 2012

Deblurring with OpenCV:Wiener filter reloaded


The problem of deblurring has really caught my fancy though I have only had partial success with it. Deblurring is basically an ill-posed problem where there are 2 unknowns namely the original image and a blurring function. There are many solutions to this problem involving a fair amount of mathematics.
Every now and then I will sneak into some white paper on this topic only to beat a hasty retreat gulping for air as I get drowned in the abstract math. Anyway my search led me to the following presentation “Deblurring in CT (Computer Tomography)” by Kriti Sen Sharma which seemed to make a lot of sense. This presentation shows how a PSF (Point Spread Function or the blur kernel) can blur an image as shown below.
Further it can be shown that the Wiener filter can be represented as

W(u) = P(u*)
——-
|P(u)|^2 + K

Where P(u) is PSD (Point Spread Distribution) of the blur kernel. K is S/N or signal to noise ratio.
For the PSF I took the Gaussian distribution given in Wikipedia – Gaussian blur given by



I tried with various values of SIGMA. The best value was SIGMA = 0.014089642. I get just one pixel with a value of > 0.  This is shown below.








I also tried various values of K. The larger the K the clearer was the DFT INVERSE. This was the best I got.
I am still nowhere near removing the blur but I will get there sometime in the future.
Any and all comments welcome.

I am including the code executed with Visual Studio 2010 express
//======================================================================================================================
// Wiener filter implemention using Gaussian blur kernel
// Developed by: Tinniam V Ganesh
// Date: 11 May 2012
//======================================================================================================================
#include “stdafx.h”
#include “math.h”
#include
#include
#include

#define kappa 10000

int main(int argc, char ** argv)
{
int height,width,step,channels,depth;
uchar* data1;
CvMat *dft_A;
CvMat *dft_B;
CvMat *dft_C;
IplImage* im;
IplImage* im1;
IplImage* image_ReB;
IplImage* image_ImB;
IplImage* image_ReC;
IplImage* image_ImC;
IplImage* complex_ImC;
CvScalar val;
IplImage* k_image_hdr;
int i,j,k;
FILE *fp;
fp = fopen(“test.txt”,”w+”);
int dft_M,dft_N;
int dft_M1,dft_N1;
CvMat* cvShowDFT1(IplImage*, int, int,char*);
void cvShowInvDFT1(IplImage*, CvMat*, int, int,char*);
im1 = cvLoadImage(“kutty-1.jpg”);
cvNamedWindow(“Original-Color”, 0);
cvShowImage(“Original-Color”, im1);
im = cvLoadImage(“kutty-1.jpg”, CV_LOAD_IMAGE_GRAYSCALE );
if( !im )
return -1;
cvNamedWindow(“Original-Gray”, 0);
cvShowImage(“Original-Gray”, im);

IplImage* k_image;
int rowLength= 11;
long double kernels[11*11];
CvMat kernel;
int x,y;
long double PI_F=3.14159265358979;
//long double SIGMA = 0.84089642;
long double SIGMA = 0.014089642;
//long double SIGMA = 0.00184089642;
long double EPS = 2.718;
long double numerator,denominator;
long double value,value1;
long double a,b,c,d;
numerator = (pow((float)-3,2) + pow((float) 0,2))/(2*pow((float)SIGMA,2));
printf(“Numerator=%f\n”,numerator);
denominator = sqrt((float) (2 * PI_F * pow(SIGMA,2)));
printf(“denominator=%1.8f\n”,denominator);
value = (pow((float)EPS, (float)-numerator))/denominator;
printf(“Value=%1.8f\n”,value);
for(x = -5; x < 6; x++){
for (y = -5; y < 6; y++)
{
//numerator = (pow((float)x,2) + pow((float) y,2))/(2*pow((float)SIGMA,2));
numerator = (pow((float)x,2) + pow((float)y,2))/(2.0*pow(SIGMA,2));
denominator = sqrt((2.0 * 3.14159265358979 * pow(SIGMA,2)));
value = (pow(EPS,-numerator))/denominator;
printf(” %1.8f “,value);
kernels[x*rowLength +y+55] = (float)value;
}
printf(“\n”);
}
printf(“———————————\n”);
for (i=-5; i < 6; i++){
for(j=-5;j < 6;j++){
printf(” %1.8f “,kernels[i*rowLength +j+55]);
}
printf(“\n”);
}
kernel= cvMat(rowLength, // number of rows
rowLength, // number of columns
CV_32FC1, // matrix data type
&kernels);
k_image_hdr = cvCreateImageHeader( cvSize(rowLength,rowLength), IPL_DEPTH_32F,1);
k_image = cvGetImage(&kernel,k_image_hdr);
height = k_image->height;
width = k_image->width;
step = k_image->widthStep/sizeof(float);
depth = k_image->depth;
channels = k_image->nChannels;
//data1 = (float *)(k_image->imageData);
data1 = (uchar *)(k_image->imageData);
cvNamedWindow(“blur kernel”, 0);
cvShowImage(“blur kernel”, k_image);
dft_M = cvGetOptimalDFTSize( im->height – 1 );
dft_N = cvGetOptimalDFTSize( im->width – 1 );
//dft_M1 = cvGetOptimalDFTSize( im->height+99 – 1 );
//dft_N1 = cvGetOptimalDFTSize( im->width+99 – 1 );
dft_M1 = cvGetOptimalDFTSize( im->height+3 – 1 );
dft_N1 = cvGetOptimalDFTSize( im->width+3 – 1 );
printf(“dft_N1=%d,dft_M1=%d\n”,dft_N1,dft_M1);
// Perform DFT of original image
dft_A = cvShowDFT1(im, dft_M1, dft_N1,”original”);
//Perform inverse (check)
//cvShowInvDFT1(im,dft_A,dft_M1,dft_N1, “original”); – Commented as it overwrites the DFT
// Perform DFT of kernel
dft_B = cvShowDFT1(k_image,dft_M1,dft_N1,”kernel”);
//Perform inverse of kernel (check)
//cvShowInvDFT1(k_image,dft_B,dft_M1,dft_N1, “kernel”);- Commented as it overwrites the DFT
// Multiply numerator with complex conjugate
dft_C = cvCreateMat( dft_M1, dft_N1, CV_64FC2 );
printf(“%d %d %d %d\n”,dft_M,dft_N,dft_M1,dft_N1);
// Multiply DFT(blurred image) * complex conjugate of blur kernel
cvMulSpectrums(dft_A,dft_B,dft_C,CV_DXT_MUL_CONJ);
//cvShowInvDFT1(im,dft_C,dft_M1,dft_N1,”blur1?);
// Split Fourier in real and imaginary parts
image_ReC = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1);
image_ImC = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1);
complex_ImC = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 2);
printf(“%d %d %d %d\n”, dft_M,dft_N,dft_M1,dft_N1);
//cvSplit( dft_C, image_ReC, image_ImC, 0, 0 );
cvSplit( dft_C, image_ReC, image_ImC, 0, 0 );
// Compute A^2 + B^2 of denominator or blur kernel
image_ReB = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1);
image_ImB = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1);
// Split Real and imaginary parts
cvSplit( dft_B, image_ReB, image_ImB, 0, 0 );
cvPow( image_ReB, image_ReB, 2.0);
cvPow( image_ImB, image_ImB, 2.0);
cvAdd(image_ReB, image_ImB, image_ReB,0);
val = cvScalarAll(kappa);
cvAddS(image_ReB,val,image_ReB,0);
//Divide Numerator/A^2 + B^2
cvDiv(image_ReC, image_ReB, image_ReC, 1.0);
cvDiv(image_ImC, image_ReB, image_ImC, 1.0);
// Merge Real and complex parts
cvMerge(image_ReC, image_ImC, NULL, NULL, complex_ImC);
// Perform Inverse
cvShowInvDFT1(im, (CvMat *)complex_ImC,dft_M1,dft_N1,”Weiner o/p k=10000 SIGMA=0.014089642″);
cvWaitKey(-1);
return 0;
}
CvMat* cvShowDFT1(IplImage* im, int dft_M, int dft_N,char* src)
{
IplImage* realInput;
IplImage* imaginaryInput;
IplImage* complexInput;
CvMat* dft_A, tmp;
IplImage* image_Re;
IplImage* image_Im;
char str[80];
double m, M;
realInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1);
imaginaryInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1);
complexInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 2);
cvScale(im, realInput, 1.0, 0.0);
cvZero(imaginaryInput);
cvMerge(realInput, imaginaryInput, NULL, NULL, complexInput);
dft_A = cvCreateMat( dft_M, dft_N, CV_64FC2 );
image_Re = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1);
image_Im = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1);
// copy A to dft_A and pad dft_A with zeros
cvGetSubRect( dft_A, &tmp, cvRect(0,0, im->width, im->height));
cvCopy( complexInput, &tmp, NULL );
if( dft_A->cols > im->width )
{
cvGetSubRect( dft_A, &tmp, cvRect(im->width,0, dft_A->cols – im->width, im->height));
cvZero( &tmp );
}
// no need to pad bottom part of dft_A with zeros because of
// use nonzero_rows parameter in cvDFT() call below
cvDFT( dft_A, dft_A, CV_DXT_FORWARD, complexInput->height );
strcpy(str,”DFT -”);
strcat(str,src);
cvNamedWindow(str, 0);
// Split Fourier in real and imaginary parts
cvSplit( dft_A, image_Re, image_Im, 0, 0 );
// Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2)
cvPow( image_Re, image_Re, 2.0);
cvPow( image_Im, image_Im, 2.0);
cvAdd( image_Re, image_Im, image_Re, NULL);
cvPow( image_Re, image_Re, 0.5 );
// Compute log(1 + Mag)
cvAddS( image_Re, cvScalarAll(1.0), image_Re, NULL ); // 1 + Mag
cvLog( image_Re, image_Re ); // log(1 + Mag)
cvMinMaxLoc(image_Re, &m, &M, NULL, NULL, NULL);
cvScale(image_Re, image_Re, 1.0/(M-m), 1.0*(-m)/(M-m));
cvShowImage(str, image_Re);
return(dft_A);
}
void cvShowInvDFT1(IplImage* im, CvMat* dft_A, int dft_M, int dft_N,char* src)
{
IplImage* realInput;
IplImage* imaginaryInput;
IplImage* complexInput;
IplImage * image_Re;
IplImage * image_Im;
double m, M;
char str[80];
realInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1);
imaginaryInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1);
complexInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 2);
image_Re = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1);
image_Im = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1);
//cvDFT( dft_A, dft_A, CV_DXT_INV_SCALE, complexInput->height );
cvDFT( dft_A, dft_A, CV_DXT_INV_SCALE, dft_M);
strcpy(str,”DFT INVERSE – “);
strcat(str,src);
cvNamedWindow(str, 0);
// Split Fourier in real and imaginary parts
cvSplit( dft_A, image_Re, image_Im, 0, 0 );
// Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2)
cvPow( image_Re, image_Re, 2.0);
cvPow( image_Im, image_Im, 2.0);
cvAdd( image_Re, image_Im, image_Re, NULL);
cvPow( image_Re, image_Re, 0.5 );
// Compute log(1 + Mag)
cvAddS( image_Re, cvScalarAll(1.0), image_Re, NULL ); // 1 + Mag
cvLog( image_Re, image_Re ); // log(1 + Mag)
cvMinMaxLoc(image_Re, &m, &M, NULL, NULL, NULL);
cvScale(image_Re, image_Re, 1.0/(M-m), 1.0*(-m)/(M-m));
//cvCvtColor(image_Re, image_Re, CV_GRAY2RGBA);
cvShowImage(str, image_Re);
}