Lab environment:
1. Linux operating system
2. qt3 programming and development environment
3, C ++ programming language Fourier transform and Fourier inverse transform 1.1. Main source code
ReadImage () reads data from images
Writeimage () writes data to the image
FFT () Fast Fourier Transformation
IFFT () Fast Fourier inverse transformation
Adjustimagesize () Adjust the image size
Fourier () Fourier Transformation
Ifourier () Fourier inverse transformation
1.1.1Read data from images
Void imageprocess: ReadImage (complex <double> data [], const qimage & srcimage)
{
Byte * pimagebytes = srcimage. Bits (); // the first data address.
Int depth = srcimage. Depth (); // The number of bits per pixel
Int linebytes = srcimage. bytesperline (); // The number of bytes per row
Int W = srcimage. Width (); // width
Int H = srcimage. Height (); // high
Byte * pbyte;
// Read each pixel and convert it to a gray value through Traversal
Int I, J;
For (I = 0; I
{
For (j = 0; j <W; j ++)
{
If (8 = depth) // uses the 256 color palette and 8-bit color index.
{
Pbyte = pimagebytes + I * linebytes + J;
Data [I * w + J] = complex <double> (* pbyte, 0 );
}
Else if (32 = depth) // 32-bit representation. The data format is 0xffbbggrr or 0 xaabbggrr.
{
Pbyte = pimagebytes + I * linebytes + J * 4;
// Convert the RGB mode to the yiq color mode, and use y as the gray value.
Byte pixelvalue = (byte) (0.299 * (float) pbyte [0] + 0.587 * (float) pbyte [1]
+ 0.114 * (float) pbyte [2]);
Data [I * w + J] = complex <double> (pixelvalue, 0 );
}
Else
{
Cout <"invalid format. Depth =" <depth <"\ n ";
Return;
}
}
}
}
1.1.2Write data into images
// Coef is the proportional coefficient, which is mainly used to adjust the gray value for observation.
Void imageprocess: writeimage (qimage & destimage, const complex <double> data [], double coef)
{
Int linebytes = destimage. bytesperline ();
Int depth = destimage. Depth ();
Int W = destimage. Width ();
Int H = destimage. Height ();
Byte * pimagebytes = destimage. Bits ();
Byte * pbyte;
For (INT I = 0; I
{
For (Int J = 0; j <W; j ++)
{
Double spectral = ABS (data [I * w + J]) * coef; // grayscale Value Adjustment
Spectral = spectral & gt; 255? 255: spectral;
// Write Data Based on Image Format
If (8 = depth)
{
Pbyte = pimagebytes + I * linebytes + J;
* Pbyte = spectral;
}
Else if (32 = depth)
{
Pbyte = pimagebytes + I * linebytes + J * 4;
Pbyte [0] = pbyte [1] = pbyte [2] = spectral;
}
Else
{
Return;
}
}
}
}
1.1.3Recursive form of Fast Fourier Transformation
// Array a is the input, array Y is the output, and the power level of 2 is the length of the array
Void imageprocess: FFT (const complex <double> A [], complex <double> Y [], int power)
{
If (0 = power)
{
Y [0] = A [0];
Return;
}
Int n = 1 <power;
Double angle = 2 * PI/N;
Complex <double> Wn (COS (angle), sin (angle ));
Complex <double> W (1, 0 );
Complex <double> * a0 = new complex <double> [n/2];
Complex <double> * a1 = new complex <double> [n/2];
Complex <double> * Y0 = new complex <double> [n/2];
Complex <double> * Y1 = new complex <double> [n/2];
For (INT I = 0; I <n/2; I ++)
{
A0 [I] = A [2 * I];
A1 [I] = A [2 * I + 1];
}
// Split into two sub-FFT Processes
FFT (A0, y0, power-1 );
FFT (A1, Y1, power-1 );
Complex <double> U;
For (int K = 0; k <n/2; k ++) // butterfly Algorithm
{
U = W * Y1 [k];
Y [k] = y0 [k] + U;
Y [K + n/2] = y0 [k]-U;
W = W * wn;
}
Delete [] A0;
Delete [] A1;
Delete [] y0;
Delete [] Y1;
}
1.1.4Fast Fourier inverse transformation
// Y indicates the input, a indicates the output, and 2 indicates the length of the array.
Void imageprocess: IFFT (const complex <double> Y [], complex <double> A [], int power)
{
Int COUNT = 1 <power;
Complex <double> * x = new complex <double> [count];
Memcpy (X, Y, sizeof (complex <double>) * count );
Int I;
For (I = 0; I <count; I ++)
{
X [I] = complex <double> (X [I]. Real (),-X [I]. imag (); // binds the complex number.
}
FFT (X, A, power); // call the Fast Fourier Transform Algorithm
For (I = 0; I <count; I ++)
{
A [I] = complex <double> (A [I]. Real ()/count,-A [I]. imag ()/count); // the combination of the plural
}
Delete [] X;
}
1.1.5Adjust the image size
// Returns an exponential value of 2 for both width and height.
Void imageprocess: adjustimagesize (qimage & image)
{
Int W = 1;
Int H = 1;
Int width = image. Width ();
Int Height = image. Height ();
WP = 0, HP = 0;
While (w * 2 <= width) {w * = 2; WP ++ ;}
While (H * 2 <= height) {H * = 2; HP ++ ;}
Qimage adjustedimage (W, H, image. Depth (), image. numcolors (), image. bitorder ());
Byte * destbytes = adjustedimage. Bits ();
Byte * srcbytes = image. Bits ();
Int linebytes = image. bytesperline ();
Int bytesperpixel = image. Depth ()/8; // The number of bytes per pixel
For (INT I = 0; I
{
Memcpy (destbytes + I * w * bytesperpixel, srcbytes + I * linebytes,
Sizeof (byte) * w * bytesperpixel );
}
Image = adjustedimage; // update the image
}
1.1.6Main Process of Fourier Transformation
Void imageprocess: Fourier ()
{
Int W = currentimage. Width ();
Int H = currentimage. Height ();
If (needadjust) // adjust the image size to a power of 2 for Fast Fourier Transformation
{
Adjustimagesize (currentimage); // adjust the size
Needadjust = false;
If (currentimagedata)
{
Delete [] currentimagedata;
}
Currentimagedata = new complex <double> [w * H];
ReadImage (currentimagedata, currentimage); // read data
}
Else if (null = currentimagedata)
{
Currentimagedata = new complex <double> [w * H];
ReadImage (currentimagedata, currentimage); // read data
}
W = currentimage. Width (); // update width and height
H = currentimage. Height ();
Complex <double> * TD = currentimagedata; // The currently read data is in the time domain
Complex <double> * FD = new complex <double> [w * H]; // Save the conversion result in the requested space.
Int I, J;
For (I = 0; I
{
FFT (& TD [w * I], & FD [w * I], WP );
}
Memcpy (TD, FD, sizeof (complex <double>) * w * H );
Complex <double> * columnt = new complex <double> [H];
Complex <double> * columnf = new complex <double> [H];
For (I = 0; I <W; I ++) // adjust the row and column data and perform fast Fourier transformation in the Y direction.
{
For (j = 0; j
{
Columnt [J] = TD [J * w + I];
}
FFT (columnt, columnf, HP );
For (j = 0; j
{
FD [J * w + I] = columnf [J];
}
}
Delete [] columnt;
Delete [] columnf;
Writeimage (currentimage, FD, 0.02); // write data
Delete [] currentimagedata;
Currentimagedata = FD;
Pdisplabel-> setpixmap (qpixmap (currentimage ));
}
1.1.7Fourier inverse transformation
The concept of Fourier inverse transformation is similar to that of Fourier change, except that the time domain is interchangeable with the frequency domain, and then the fast Fourier inverse transformation IFFT is called instead of the fast Fourier transformation FFT.
1.2. Run
1.2.1Square
Enter a 256*256 image with a white background and a black square in the middle, as shown in Figure 1-1. The result after Fourier transformation is 1-2 (Note: The method of moving to center is not used ).
Figure 1-1
Figure 1-2
1.2.2Rotate 45Degrees
After rotating Figure 1-1 to 45 degrees, the input values are 1-3. The Fourier transformation result is 1-4.
Figure 1-3
Figure 1-4
1.2.3Input rectangular Image
The input image is 1-5. The Fourier transformation result is 1-6.
Figure 1-5
Figure 1-6
1.2.4Fourier inverse transformation
Perform Fourier inverse transformation on 1-2 of the Fourier Transformation Result graph. The result is the same as that of the source image 1-1, as shown in figure 1-7:
Figure 1-7
Image Enhancement
Image enhancement is a very important image processing technology. To facilitate human observation and machine processing, we can process a given image. There are many ways to enhance the image. The following two methods are implemented: smooth and sharpening.
2.1. Main source code
2.1.1Smooth
The template is implemented as follows:
Void imageprocess: smooth ()
{
Int W = currentimage. Width ();
Int H = currentimage. Height ();
If (null = currentimagedata) // determine whether to re-read the data
{
Currentimagedata = new complex <double> [w * H];
ReadImage (currentimagedata, currentimage );
}
// Copy a copy of data for easy computing
Complex <double> * buffer = new complex <double> [w * H];
Memcpy (buffer, currentimagedata, sizeof (complex <double>) * w * H );
// Calculate based on the template
// The Image Boundary (I = 0 or H, J = 0 or W) is ignored for simplified encoding, and the overall effect is not affected.
Int I, J;
For (I = 1; I
{
For (j = 1; j <w-1; j ++)
{
Complex <double> K;
K = buffer [(I-1) * w + J-1];
K + = buffer [(I-1) * w + J];
K + = buffer [(I-1) * w + J + 1];
K + = buffer [I * w + J-1];
K + = buffer [I * w + J];
K + = buffer [I * w + J + 1];
K + = buffer [(I + 1) * w + J-1];
K + = buffer [(I + 1) * w + J];
K + = buffer [(I + 1) * w + J + 1];
K = complex <double> (K. Real ()/9, 0 );
Currentimagedata [I * w + J] = K;
}
}
Writeimage (currentimage, currentimagedata );
Pdisplabel-> setpixmap (qpixmap (currentimage ));
}
2.1.2Sharpen
Use Laplace sharpening. The template is as follows:
Void imageprocess: Sharp ()
{
Int W = currentimage. Width ();
Int H = currentimage. Height ();
If (null = currentimagedata) // determines whether data needs to be read.
{
Currentimagedata = new complex <double> [w * H];
ReadImage (currentimagedata, currentimage );
}
// Copy a copy of data for easy computing
Complex <double> * buffer = new complex <double> [w * H];
Memcpy (buffer, currentimagedata, sizeof (complex <double>) * w * H );
// Calculate based on the template
// The Image Boundary (I = 0 or H, J = 0 or W) is ignored for simplified encoding, and the overall effect is not affected.
Int I, J;
Complex <double> K;
For (I = 1; I
{
For (j = 1; j <w-1; j ++)
{
K = buffer [I * w + J];
K = complex <double> (K. Real () * 5, 0 );
K-= buffer [(I-1) * w + J];
K-= buffer [I * w + J-1];
K-= buffer [I * w + J + 1];
K-= buffer [(I + 1) * w + J];
Currentimagedata [I * w + J] = K;
}
}
Writeimage (currentimage, currentimagedata );
Pdisplabel-> setpixmap (qpixmap (currentimage ));
}
2.2. Run
The smoothing result of the Input Image 2-1 is Fig 2-2, and the sharpening result is Fig 2-3.
Figure 2-1 Original Image
Figure 2-2 smooth image
Figure 2-3 sharpen the image
Image Analysis
This part mainly realizes template matching of images. Template matching is a very primitive pattern recognition method. There are many template matching algorithms. The algorithm used here is to calculate the similarity between the two. Select a coordinate in the target image and select an area in the upper left corner of the coordinate to calculate the similarity between the region and the template, the point with the highest similarity is the matching point. The degree of similarity is determined by the degree of difference between the two. The calculation of the degree of difference is M =. The difference between pixels will be accumulated. To increase the calculation speed, you can set the threshold value. When M is greater than the threshold value, it is determined that the block area does not match, and continue to look for the next area.
3.1. Main source code
Void imageprocess: Match ()
{
// Let the user select a template
Qstring filename = qfiledialog: getopenfilename ("/home/tanqiyu", "Images (*. PNG *. XPM
. Jpg) ", this," open file dialog "," Choose a model image ");
If (qstring: null = filename)
{
Return;
}
// Read template data
Qimage modelimage (filename );
Int Mw = modelimage. Width ();
Int MH = modelimage. Height ();
Complex <double> * modelimagedata = new complex <double> [MW * MH];
ReadImage (modelimagedata, modelimage );
Unsigned long T = MW * MH * 8; // set a threshold value based on the size of the matching template.
Unsigned long M = T; // initial variance
Int rI =-1; // Z coordinate in the upper left corner (Ri, RJ)
Int RJ =-1;
Int W = currentimage. Width ();
Int H = currentimage. Height ();
If (null = currentimagedata) // determine whether to read the Target Image Data
{
Currentimagedata = new complex <double> [w * H];
ReadImage (currentimagedata, currentimage );
}
// Traverse the target image and select the coordinates in the upper left corner. Do not cross-border the size of the template image.
Int I, J;
For (I = 0; I
{
For (j = 0; j <w-MW + 1; j ++)
{
// Match the MW * MH area in the upper left corner of the vertex (I, j)
Bool overflag = false;
Unsigned long K = 0; // sum of the Difference values
Int U, V;
For (u = 0; U <MH &&! Overflag; U ++)
{
For (V = 0; v <MW &&! Overflag; V ++)
{
K + = ABS (currentimagedata [(I + u) * w + J + V]. Real ()
-Modelimagedata [u * MW + V]. Real (); // calculates the difference and accumulates
If (k> = T) // determine whether the threshold value is greater
{
Overflag = true;
}
}
}
If (k <m) // determines whether a more matched region is found.
{
Ri = I;
RJ = J;
M = K;
}
}
}
// If the matching area is found, the point outside the matching area of the target image is set to white for observation.
If (Ri! =-1)
{
For (I = 0; I
{
For (j = 0; j <W; j ++)
{
If (I <Ri | j <rj | I> RI + Mh-1 | j> RJ + MW-1)
{
Currentimagedata [I * w + J] = complex <double> (255, 0 );
}
}
}
}
Writeimage (currentimage, currentimagedata );
Pdisplabel-> setpixmap (qpixmap (currentimage ));
}
3.2. Run
The target image is shown in Figure 3-1 and Figure 3-2 matching template. The matching result is shown in Figure 3-3.
Figure 3-1 Target Image
Figure 3-2 matching Template
Matching result