Using C/C + + to call opencv library to program and display pictures under Ubuntu

Keywords: C OpenCV

1, Requirements:

Learn and understand the internal code, location code coding rules and font data storage format of Chinese characters. Under Ubuntu, use C/C + + (or python) to call opencv library to program and display a picture, open a text file named "logo.txt" (there is only one line of text file, including your own name and student number), and read the font data of the corresponding characters in the Chinese character 24 * 24 dot matrix font library (file HZKf2424.hz in the compressed package) according to the name and student number, Overlay the name and student number to the lower right of this picture.

2, Chinese character dot matrix library

(1) Chinese character coding

1. Location code

It is stipulated in the national standard GD2312-80 that all national standard Chinese characters and symbols are allocated in a square of 94 rows and 94 columns
In the array, each row of the square array is called a "zone", numbered from zone 01 to zone 94, and each column is called a "bit", numbered as
From 01 bits to 94 bits, the area code and bit number of each Chinese character and symbol in the square array are combined to form four ARAS
The number is their "location code". The first two digits of the location code are its area code and the last two digits are its bit code. Just use the location code
A Chinese character or symbol can be uniquely determined. Conversely, any Chinese character or symbol also corresponds to a unique symbol
Location code. The location code of the Chinese character "mother" is 3624, indicating that it is 24 digits in area 36 of the square matrix, and the location code of the question mark "?" is
0331, then it is in 3l of zone 03.

2. Internal code

The internal code of Chinese characters refers to the code that represents a Chinese character in the computer. The internal code is slightly different from the location code. As mentioned above
As described above, the area code and bit code of Chinese location code are between 1 ~ 94. If the location code is directly used as the internal code, it will
Confused with basic ASCII code. In order to avoid the conflict between the built-in code and the basic ASCII code, it is necessary to avoid the basic ASCII code
The control code (00H~1FH) in shall also be different from the characters in the basic ASCII code. In order to achieve these two points, you can
First add 20H to the area code and bit code respectively, and then add 80h on this basis (here "H" means that the first two digits are hexadecimal
Number). After these processes, it takes two bytes to represent a Chinese character with internal code, which are called high byte and low word respectively
Section, the internal code of these two bytes is represented according to the following rules:
High byte = area code + 20h + 80h (or area code + A0H)
Low byte = bit code + 20h + 80h (or bit code + AOH)
Because the hexadecimal numbers in the value range of area code and bit code of Chinese characters are 01h ~ 5eh (i.e. 01 ~ 9 in decimal system)
4) Therefore, the value range of high-order byte and low-order byte of Chinese characters is a1h ~ FEH (i.e. 161 ~ 254 in decimal system).
For example, the location code of the Chinese character "ah" is 1601, and the area code and bit code are expressed in hexadecimal respectively, that is, 1001H
The high-order byte of the internal code is B0H, the low-order byte is A1H, and the internal code is B0A1H.

(2) . lattice font structure

1. Dot matrix font storage

In the dot matrix font of Chinese characters, each bit of each byte represents a point of a Chinese character
Words are composed of a rectangular lattice. 0 represents no and 1 represents a little. Use 0 and 1 differently
When the color is drawn, a Chinese character is formed. The commonly used dot matrix includes 1212, 1414 and 16 * 16
Type library.
Word libraries are divided into horizontal matrix and vertical matrix according to the points represented by bytes. At present, most word libraries
Both are the storage methods of horizontal matrix (the most used should be the early UCDOS font), and vertical matrix I
Generally, because some liquid crystals use the longitudinal scanning display method, in order to improve the display speed, the font is used
The matrix is made vertical, which saves matrix conversion when displaying. What we describe next refers to the horizontal
Matrix font.

2. 16 * 16 dot matrix font library

For the 1616 matrix, the number of bits required is 1616 = 256 bits, each word
The section is 8 bits, so each Chinese character needs to be represented by 256 / 8 = 32 bytes.
That is, every two bytes represent 16 points in a line, and a total of 16 lines are required. When displaying Chinese characters, it only needs to be done once
Read 32 bytes and print every two bytes as a line to form a Chinese character.
The lattice structure is shown in the figure below:

3. 1414 and 1212 dot matrix font library

For 1414 and 1212 word libraries, theoretically, their required dot matrices are (14) respectively
14 / 8) = 25, (1212 / 8) = 18 bytes, but if stored in this way, then
When dot matrix and display, because each line of them is not an integer of 8, it will involve the calculation of dot matrix
To solve the problem will increase the complexity of the program and reduce the efficiency of the program.
In order to solve this problem, some dot matrix font libraries will press 1614 for 1414 and 1212
And 1612, that is, each line is still stored by two bytes, but the font of 1414 is stored by
The last two bits of two bytes are unused, 1212 bytes, and the last four bits of every two bytes are unused
This word library has different processing methods according to different word libraries, so you should pay attention to this when using the word library
Problems, especially the 14 * 14 font.

(3) Chinese character dot matrix acquisition

1. Use location code to obtain Chinese characters

Chinese character dot matrix font is stored according to the order of location code, so we can store it according to location
Get the lattice of a font, and its calculation formula is as follows:
Lattice start position = ((area code - 1) * 94 + (bit code - 1)) * number of Chinese character lattice bytes
After obtaining the starting position of the dot matrix, we can read and take out the dot matrix of a Chinese character from this position.

2. Obtain Chinese characters by using Chinese character internal code

As we have said earlier, the relationship between the location code of Chinese characters and the internal code is as follows:
High byte of internal code = area code + 20h + 80h (or area code + A0H)
Low byte of internal code = bit code + 20h + 80h (or bit code + AOH)
Conversely, we can also obtain the location code according to the internal code:
Area code = high byte of internal code - A0H
Bit code = low byte of internal code - AOH

3, Using C/C + + to call opencv library to program and display pictures under Ubuntu

1. Prepare the required documents


A picture to be displayed, 24 * 24 dot matrix. hz file, ASCII code. zf file, and text file to be displayed

When inputting the text you want to display in the logo.txt file, you need to write it in ANSI code, otherwise Chinese will be garbled

Then select Save as to select ANSI encoded:

2. Call opencv to print the logo content into the picture:

First, enter the folder I created in ubuntu:

cd dishizhou

Then write the code:

gedit test.cpp


code:

 1. #include<iostream>
    #include<opencv/cv.h>
    #include"opencv2/opencv.hpp"
    #include<opencv/cxcore.h>
    #include<opencv/highgui.h>
    #include<math.h>
    
    using namespace cv; using namespace std;
    
    void paint_chinese(Mat& image,int x_offset,int y_offset,unsigned
    long offset); void paint_ascii(Mat& image,int x_offset,int
    y_offset,unsigned long offset); void put_text_to_image(int
    x_offset,int y_offset,String image_path,char* logo_path);
    
    int main(){
        String image_path="beauty.jpg";//Name of picture
        char* logo_path="logo.txt";//Name of Chinese character file
        put_text_to_image(500,750,image_path,logo_path);//change txt place
        return 0; }
    
    void paint_ascii(Mat& image,int x_offset,int y_offset,unsigned long
    offset){
        //Coordinates of the starting point of the drawing 	 Point p;  	 p.x = x_offset;  	 p.y = y_offset;  	 // Storing ascii word film 	 char buff[16];             	// Open ascii font file 	 FILE *ASCII;
    
    	if ((ASCII = fopen("Asci0816.zf", "rb")) == NULL){ 		printf("Can't
    open ascii.zf,Please check the path!"); 		//getch(); 		exit(0); 	}
    
    	fseek(ASCII, offset, SEEK_SET); 	fread(buff, 16, 1, ASCII);
    
    	int i, j; 	Point p1 = p; 	for (i = 0; i<16; i++)                 
    //Sixteen char s 	 {  		 p.x = x_offset;  		 for (j = 0; j < 8; j++)            
    //One char and eight bit s 		 {  			 p1 = p;  			 if (buff[i] & (0x80 >> j))   
    /*Test whether the current bit is 1*/ 			{
    				/*
    					Because the original ascii word film was 8 * 16, it was not large enough,
    					So the original pixel is replaced by four pixels,
    					After replacement, there are 16 * 32 pixels
    					ps: I think it's unnecessary to write code like this, but I only think of this method for the time being
    				*/
    				circle(image, p1, 0, Scalar(0, 0, 255), -1);
    				p1.x++;
    				circle(image, p1, 0, Scalar(0, 0, 255), -1);
    				p1.y++;
    				circle(image, p1, 0, Scalar(0, 0, 255), -1);
    				p1.x--;
    			   circle(image, p1, 0, Scalar(0, 0, 255), -1); 			}						
                p.x+=2;            //One pixel becomes four, so x and y should both be + 2 		} 		 p.y+=2;  	} }  void paint_chinese(Mat& image,int x_offset,int
    y_offset,unsigned long offset){//Draw Chinese characters on the picture
        Point p;
        p.x=x_offset;
        p.y=y_offset;
        FILE *HZK;
        char buff[72];//72 bytes for storing Chinese characters
    
        if((HZK=fopen("HZKf2424.hz","rb"))==NULL){
            printf("Can't open HZKf2424.hz,Please check the path!");
            exit(0);//sign out
        }
        fseek(HZK, offset, SEEK_SET);/*Move the file pointer to the offset position*/
        fread(buff, 72, 1, HZK);/*Read 72 bytes from the offset position, and each Chinese character occupies 72 bytes*/
        bool mat[24][24];//Define a new matrix to store the transposed text film
        int i,j,k;
        for (i = 0; i<24; i++)                 /*24x24 Dot matrix Chinese characters, a total of 24 lines*/ 	{
            	for (j = 0; j<3; j++)                /*There are 3 bytes in the horizontal direction, and the value of each byte is determined by cycle*/ 			for (k = 0; k<8; k++)              /*Each byte has 8 bits, and the loop judges whether each byte is 1*/
    				if (buff[i * 3 + j] & (0x80 >> k))    /*Test whether the current bit is 1*/
    				{
    					mat[j * 8 + k][i] = true;          /*1 is stored in a new word film*/
    				}
    				else {
    					mat[j * 8 + k][i] = false;
    				} 	}
    	
        for (i = 0; i < 24; i++) 	{ 		p.x = x_offset; 		for (j = 0; j < 24; j++) 		{		 			if (mat[i][j])
    				circle(image, p, 1, Scalar(255, 0, 0), -1);		  //Write (replace) pixels 			 p.x + +; / / move one pixel to the right
    		} 		p.y++;                                                   
    //Move down one pixel 	} }
    
    void put_text_to_image(int x_offset,int y_offset,String
    image_path,char* logo_path){//Put the Chinese character on the picture / / x and y are the starting coordinates of the first word on the picture
        //Get pictures through picture path
        Mat image=imread(image_path);
        int length=19;//The length of characters to be printed (the length can be as many bytes as you print, which can be adjusted according to your own situation)
        unsigned char qh,wh;//Define area code and tag number
        unsigned long offset;//Offset
        unsigned char hexcode[30];//Hexadecimal used to store Notepad reading. Remember to use unsigned
        FILE* file_logo;
    
        if ((file_logo = fopen(logo_path, "rb")) == NULL){ 		printf("Can't open txtfile,Please check the path!"); 		//getch();
    		exit(0); 	}
    
        fseek(file_logo, 0, SEEK_SET);
        fread(hexcode, length, 1, file_logo);
        int x =x_offset,y = y_offset;//x. Y: the starting coordinate of the text drawn on the picture
    
        for(int m=0;m<length;){
            if(hexcode[m]==0x23){
                break;//It ends when the # number is read
            }
            else if(hexcode[m]>0xaf){
                qh=hexcode[m]-0xaf;//The font used starts with Chinese characters, not Chinese symbols
                wh=hexcode[m+1] - 0xa0;//Calculation bit code
                offset=(94*(qh-1)+(wh-1))*72L;
                paint_chinese(image,x,y,offset);
                /*
                Calculate the offset in the Chinese character library
                Each Chinese character is represented by a 24 * 24 dot matrix
                A line has three bytes, a total of 24 lines, so 72 bytes are required
                */
    
                m=m+2;//The internal code of a Chinese character occupies two bytes,
                x+=24;//A Chinese character has 24 * 24 pixels. Because it is placed horizontally, it moves 24 pixels to the right
            }
    
            else{
            //When the read character is ASCII
            wh=hexcode[m];
            offset=wh*16l;//Calculate the offset of English characters
            paint_ascii(image,x,y,offset);
            m++;//English characters only occupy one byte in the file, so just move back one bit
            x+=16;
            }
    
        }
    
        cv::imshow("image", image);
        cv::waitKey(); }

be careful:
First, you need to modify the name of the picture you want to print the logo;
Then you need to modify the location of the logo you promised;
Both are on lines 17 and 18 of the code
When you need to modify the number of bytes of your printed logo (two bytes for a Chinese character) in line 115 of the code;

Compile run:
Compile the saved test.cpp file; the instructions are as follows:

g++ test.cpp -o test pkg-config --cflags --libs opencv

If no error is reported, it can run:
./test

The results are as follows:

4, Summary

This experiment is not very difficult. We only need to be careful to complete it. If we encounter any problems, it may be that we modify our file path, or when printing the logo, our printing position is too large and not in the picture. We only need to understand the dot matrix of Chinese characters, and we can print the text or symbols we want to print On the picture.

5, Reference

https://blog.csdn.net/qq_46467126/article/details/121313820

Posted by ou812 on Fri, 19 Nov 2021 08:22:44 -0800