Reproduced original (with strikethrough): http://blog.csdn.net/xiajun07061225/article/details/5813726
Http://blog.163.com/kksunshine@yeah/blog/static/1186123882010111565210317/
I recently studied C ++ to read *. BMP files, and I would like to thank the author for his selfless dedication.
========================================================== ========================================================== ========================================================== ==============
To recognize characters in an image, you must first process the image and read the image information. Therefore, you must first understand the image structure and storage method. A digital image processing programming entry published by Tsinghua University has helped me a lot. In chapter 1, the Windows bitmap and palette give me a basic understanding of BMP images. Color charts can be represented by RGB models. Basically, all colors can be formed by a combination of these three colors. However, there are actually some differences. Bitmap smaller than 24 uses the color palette, which is an R, G, and B table, mainly to save storage space. The BMP file structure is as follows:
Figure 1 BMP bitmap Structure
The first part is the bitmap file header.BitmapfileheaderIs a structure, which is defined as follows:
Typedef struct tagbitmapfileheader {
Word bftype;
DWORD bfsize;
Word bfreserved1;
Word bfreserved2;
DWORD bfoffbits;
} Bitmapfileheader;
The length of this structure is fixed and 14 bytes (word is a 16-bit integer without a symbol, DWORD is a 32-bit integer without a symbol). The fields are described as follows:
Bftype
Specifies that the first two bytes of the. BMP file are "BM ".
Bfsize
Specify the file size, including the 14 bytes.
Bfreserved1, bfreserved2
Reserved Words, no need to consider
Bfoffbits
It is the number of offset bytes from the file header to the actual bitmap data, that is, the sum of the length of the first three parts in Figure 1.3.
The second part is the bitmap information header.BitmapinfoheaderIs also a structure, which is defined as follows:
Typedef struct tagbitmapinfoheader {
DWORD bisize;
Long biwidth;
Long biheight;
Word biplanes;
Word ititcount
DWORD bicompression;
DWORD bisizeimage;
Long bixpelspermeter;
Long biypelspermeter;
DWORD biclrused;
DWORD biclrimportant;
} Bitmapinfoheader;
The length of this structure is fixed. It is 40 bytes (long is a 32-bit integer). The description of each field is as follows:
Bisize
Specify the length of this structure, which is 40.
Biwidth
Specify the image width in pixels.
Biheight
Specifies the Image Height, in pixels.
Biplanes
It must be 1.
Bibitcount
Specify the number of digits to be used when the color is used. The commonly used values are 1 (black and white two-color chart), 4 (16-color graph), 8 (256 colors), and 24 (true color graph) (The New. BMP format supports 32-bit colors, I will not discuss it here ).
Bicompression
Specifies whether the bitmap is compressed. Valid values include bi_rgb, bi_rle8, bi_rle4, and bi_bitfields (all constants defined by windows ). It should be noted that the Windows bitmap can adopt the rle4 and rle8 compression formats, but not much is used. We will discuss only the first case of no compression, that is, the case where bicompression is bi_rgb.
Bisizeimage
The number of bytes occupied by the actual bitmap data can also be calculated from the following formula:
Bisizeimage = biwidth' × biheight
Note that the biwidth' in the above formula must be an integer multiple of 4 (so it is not biwidth, but biwidth', indicating that it is greater than or equal to biwidth and the nearest integer to 4. For example, if biwidth = 240, biwidth' = 240; If biwidth = 241, biwidth' = 244 ).
If bicompression is bi_rgb, this item may be zero.
Bixpelspermeter
Specify the horizontal resolution of the target device. The unit is the number of pixels per meter. The definition of resolution is described in Chapter 4th.
Biypelspermeter
Specifies the vertical resolution of the target device, in the same unit as above.
Biclrused
Specifies the number of colors actually used by the image. If the value is zero, the number of colors used is 2 ititcount.
Biclrimportant
Specify the number of important colors in the image. If the value is zero, all colors are considered important.
Part 3: palettePaletteOf course, this is for bitmap files that require the color palette. Some bitmaps, such as true color charts, have been mentioned earlier, do not need a color palette. bitmapinfoheader is directly followed by bitmap data.
The color palette is actually an array with a total of biclrused elements (if the value is zero, there are 2 bibitcount elements ). The type of each element in the array is an rgbquad structure, which occupies 4 bytes. Its definition is as follows:
Typedef struct tagrgbquad {
Byte rgbblue; // The Blue weight of the color.
Byte rgbgreen; // The green weight of the color.
Byte rgbred; // The Red weight of the color.
Byte rgbreserved; // reserved value
} Rgbquad;
The fourth part is the actual image data. For bitmap that uses the color palette, the image data is the index value of the image pigment in the color palette. For a true color chart, the image data is the actual R, G, and B values. The following describes two-color, 16-color, 256-color bitmap, and true-color bitmap.
For a two-color bitmap, one bit can represent the color of the pixel (generally 0 indicates black, 1 indicates white), so one byte can represent 8 pixels.
For a 16-color bitmap, four digits can represent the color of one pixel, so one byte can represent two pixels.
For a 256-color bitmap, one byte can represent one pixel.
For a true color chart, three bytes can represent one pixel. Wow, it's a good deal of space! No way. Who told you to make the color look brighter.
Pay attention to the following two points:
(1) the number of bytes in each row must be an integral multiple of 4. If not, it must be completed. This is already mentioned in the previous section of bisizeimage.
(2) In general, the data in the. BMP file is from bottom to top, from left to right. That is to say, what is first read from the file is the first pixel on the left of the bottom row of the image, and then the second pixel on the left ...... Next is the first pixel on the left and the second pixel on the left ...... And so on. The last result is the rightmost pixel of the top row.
After learning about this, you can grayscale the image and program the black and white two-color image. Read the pixel information of the BMP file and store it in a one-dimensional array. Other information includes the width and height. After the image is processed, the array is processed directly. The next step is to perform noise reduction. Some images often have noise, which affects the recognition effect. Therefore, noise reduction is required. There are many ways to remove noise. My approach is to process a pixel as follows: Take the average value of the pixel at 9 points in total with 8 points around it, and the effect is OK.
I will refer to a Master's Degree Thesis of engineering from Harbin Institute of Technology in the following operations. The above ideas are very clear and I feel very good. The first step is normalization, which is to program an image of 32*32 size.
Another method is non-linear normalization, but the above formula for solving the quality and divergence is not clear, and it does not tell how to normalize with the quality and divergence. So I adopted linear normalization. The effect is worse than that of NLE.
Feature Extraction is performed after normalization.
The grid feature is to divide 32*32 images into 4*4 with 16 blocks, each with 64 small blocks. Just calculate the number of black pixels. Traversing features include horizontal traversing features and vertical traversing features. The horizontal traversal feature divides an image into eight rows and four rows in each row. Calculate the number of changes from white pixels to black pixels for each row. The first eight dimensions of horizontal traversal feature T1, T2,..., T8 are obtained. The last eight dimensions of horizontal traversal feature are solved using the formula. Pi = Ti/[(t1 + T2 +... + T8) * 10 + 0.5]. Vertical traversal features are similar.
The 16-dimensional grid features, 16-dimensional horizontal traversing features, and 16-dimensional vertical traversing features combine a total of 48 features. Weighted features can also be obtained to form a 64-bit feature.
Finally, template matching. Matching is performed based on the sum of squares of the Difference values of the corresponding feature values.
# Include <math. h> # include <iomanip. h> # include <stdlib. h> # include <windows. h> # include <stdio. h> # include <stdlib. h> # include <iostream. h> # include <fstream. h> // The following module completes the BMP image (the color image is obtained from 8 bitwise images of 24bit rgb, and the file name is "unsigned char * pbmpbuf" in xiang_su_zhi.txt; // The Int BMP width pointer for reading image data; // Image Width int bmpheight; // Image Height rgbquad * pcolortabl E; // color table pointer int bibitcount; // image type, the number of bits per pixel // read the bitmap data, width, height, color table, and number of bits per pixel into the memory, stored in the corresponding global variable bool readbmp (char * BMP name) {file * fp = fopen (BMP name, "rb "); // open the specified image file in binary read mode if (FP = 0) return 0; // skip the bitmap file header structure bitmapfileheader fseek (FP, sizeof (bitmapfileheader), 0 ); // define the bitmap information header structure variable, read the bitmap information header into the memory, and store it in the variable head bitmapinfoheader head; fread (& Head, sizeof (bitmapinfoheader), 1, FP); // obtains information such as the image width, height, and the number of digits occupied by each pixel. biwidth; bmpheight = head. biheight; bibitcount = head. bibitcount; // defines the variable to calculate the number of bytes occupied by pixels in each line of the image (must be a multiple of 4) int linebyte = (BMP width * bibitcount/8 + 3)/4*4; // grayscale images have a color table, and the color table items are 256 If (bibitcount = 8) {// apply for the space required by the color table, read the color table into the memory pcolortable = new rgbquad [256]; fread (pcolortable, sizeof (rgbquad), 256, FP);} // space required to apply for bitmap data, read bitmap data into memory pbmpbuf = new unsigned C Har [linebyte * bmpheight]; fread (pbmpbuf, 1, linebyte * bmpheight, FP); fclose (FP); // close the file return 1; // file read Successful} // specify the bitmap data, width, height, and color table pointer of an image and the number of digits occupied by each pixel, write it to the bool savebmp (char * BMP name, unsigned char * imgbuf, int width, int height, int bibitcount, rgbquad * pcolortable) in the specified file) {// If the bitmap data pointer is 0, no data is passed in. The function returns if (! Imgbuf) return 0; // color table size, in bytes. The gray image color table size is 1024 bytes, and the color image color table size is 0 int colortablesize = 0; If (bibitcount = 8) colortablesize = 1024; // The number of bytes in each row of the image data to be stored is a multiple of 4. Int linebyte = (width * bibitcount/8 + 3)/4*4; // open the file * fp = fopen (BMP name, "WB") in binary mode; If (FP = 0) return 0; // apply for bitmap file header Structure Variables, fill in the file header information bitmapfileheader filehead; filehead. bftype = 0x4d42; // BMP Type // bfsize is the sum of the four components of the image file filehead. bfsize = sizeof (bitmapfileheader) + sizeo F (bitmapinfoheader) + colortablesize + linebyte * height; filehead. bfreserved1 = 0; filehead. bfreserved2 = 0; // bfoffbits is the sum of the space required for the first three parts of the image file filehead. bfoffbits = 54 + colortablesize; // write the file header into the file fwrite (& filehead, sizeof (bitmapfileheader), 1, FP); // apply for bitmap information header Structure Variables, fill in the Information header information bitmapinfoheader head; head. bibitcount = bibitcount; head. biclrimportant = 0; head. biclrused = 0; head. bicompression = 0; head. biheight = height; head. bi Planes = 1; head. bisize = 40; head. bisizeimage = linebyte * height; head. biwidth = width; head. bixpelspermeter = 0; head. biypelspermeter = 0; // write the bitmap information header into the memory fwrite (& head, sizeof (bitmapinfoheader), 1, FP); // If the grayscale image has a color table, write File if (bibitcount = 8) fwrite (pcolortable, sizeof (rgbquad), 256, FP); // write bitmap data into file fwrite (imgbuf, height * linebyte, 1, FP); // close the file fclose (FP); return 1 ;}//------------------------------------------------ -------------------------------------- // The following is the void doit () function for reading pixels {// read the specified BMP file into the memory char readpath [] = "NV. BMP "; readbmp (readpath ); // output the image information cout <"width =" <BMP width <"Height =" <bmpheight <"bibitcount =" <bibitcount <Endl; // cyclic variable, image coordinate // number of bytes per line int linebyte = (BMP width * bibitcount/8 + 3)/4*4; // cyclic variable, for color images, traverse the three components of each pixel: int m = 0, n = 0, count_xiang_su = 0; // set the first part of the image in the lower left corner to black ofstream OUTFILE ("image example .txt", IOS :: in | IOs: Tru NC); If (bibitcount = 8) // for Grayscale Images {// assets // the following images are divided into 8*8 small units, the pixel value is stored in the specified text. Since the pixel data of the BMP image is from // bottom left: from left to right, from top to bottom int L1 = 0; int hang = 63; int lie = 0; // int L2 = 0; // int fen_ge = 8; For (INT fen_ge_hang = 0; fen_ge_hang <8; fen_ge_hang ++) // 64*64 matrix row loops {for (INT fen_ge_lie = 0; fen_ge_lie <8; fen_ge_lie ++) // 64*64 column matrix loop {// -------------------------------------------------- for (L1 = hang; L1> hang-8; L1 --) // 8*8 matrix rows {for (INT L2 = lie; L2 <lie + 8; L2 ++) // 8*8 matrix columns {M = * (pbmpbuf + L1 * linebyte + l2); OUTFILE <m <"; count_xiang_su ++; if (Count_xiang_su % 8 = 0) // read the text file {OUTFILE <Endl ;}}// export hang = 63-fen_ge_hang * 8 every 8x8 matrices; // 64*64 matrix row transformation lie + = 8; // 64*64 matrix column transformation // This row (64) composed of eight 8*8 matrix rows} Hang-= 8; // 64*64 matrix column transformation lie = 0; // 64*64 juzhen} // double xiang_su [2048]; // ofstream OUTFILE ("xiang_su_zhi.txt", IOS: In | IOs: trunc); If (! OUTFILE) {cout <"Open error! "<Endl; exit (1) ;}else if (bibitcount = 24) {// color image for (INT I = 0; I <bmpheight; I ++) {for (Int J = 0; j <BMP width; j ++) {for (int K = 0; k <3; k ++) // each pixel RGB three components are set to 0 to black {// * (pbmpbuf + I * linebyte + J * 3 + k)-= 40; M = * (pbmpbuf + I * linebyte + J * 3 + k); OUTFILE <m <""; count_xiang_su ++; If (count_xiang_su % 8 = 0) {OUTFILE <Endl ;}// n ++ ;}n ++ ;}}cout <"the total number of pixels is:" <n <Endl; cout <"--------------------------------------------------" <Endl;} // Save the image data disk char writepath [] = "nvcpy. BMP "; // save savebmp (writepath, pbmpbuf, BMP width, bmpheight, bibitcount, pcolortable) after image processing; // clear the buffer. pbmpbuf and pcolortable are global variables, delete [] pbmpbuf; If (bibitcount = 8) Delete [] pcolortable;} void main () {doit ();}