Using Opencv to print Chinese characters on pictures on Ubuntu

catalogue

1, Principle of Chinese character lattice font

1. Location code

2. National Standard Code

3. Internal code

4. Lattice font structure

  5. Chinese character dot matrix acquisition  

2, Calling Opencv library programming under Ubuntu to display pictures and student number names

3, Summary

4, References

1, Principle of Chinese character lattice font

 

1. Location code

The whole GB2312 character set is divided into 94 areas, each area has 94 bits, and there is only one character in each location, that is, each area contains 94 Chinese characters or symbols. The characters are encoded with the area and bits (actually character number and code point number), so it is called location code (or "location number" is more appropriate).

In other words, GB2312 compiles all characters, including Chinese characters, into a 94 * 94 two-dimensional table. The row is "area" and the column is "bit". Each character is uniquely located by area and bit, and its corresponding area and bit number combination is location code. For example, the word "ten thousand" is 82 bits in area 45, so the location code of the word "ten thousand" is: 45 82 (note that the GB Chinese character code is double byte code, so 45 is equivalent to high byte and 82 is equivalent to low byte).

2. National Standard Code

In order to avoid the non displayable characters 0000 ~ 0001 1111 (hexadecimal 0 ~ 1F, decimal 0 ~ 31) and space characters 0010 0000 (hexadecimal 20, decimal 32) (as for why to avoid and why only avoid the non displayable characters and space characters 0 ~ 32 in ASCII, it will be explained later), national standard code (also known as interchange code) It is specified that the range of Chinese characters is (0010 00010010 0001) ~ (0111 11100111 1110), hexadecimal is (21,21) ~ (7E, 7E), decimal is (33,33) ~ (126126) (note that GB Chinese characters are encoded in double byte code).

Therefore, the "area code" and "bit code" must be added with 32 (hexadecimal 20H, suffix H represents hexadecimal) respectively as the national standard code. In other words, the national standard code is equivalent to offsetting the location code backward by 32, so as to avoid conflict with the non displayable characters 0 ~ 32 and space characters in ASCII characters.

3. Internal code

However, the national standard code can not be used directly on the computer, because it will still conflict with the already common ASCII code (leading to garbled code).

For example, the high byte 77 in the "ten thousand" national standard code conflicts with the "M" of ASCII, and the low byte 114 conflicts with the "r" of ASCII. Therefore, in order to avoid conflict with ASCII code, it is stipulated that the highest bit of each byte in the national standard code is changed from 0 to 1, which is equivalent to adding 128 to each byte (hexadecimal 80, i.e. 80H; binary 10 million), so as to obtain the "internal code" representation of the national standard code, referred to as "internal code".

2.

Because the ASCII code only uses the lower 7 bits in a byte, the "1" on the first (highest) bit can be used as a sign to identify the Chinese character code. When the computer processes the code with the first "1", it will be understood as a Chinese character, and when it processes the code with the first "0", it will be understood as an ASCII character.

For example:

77 + 128 = 205 (binary 1100 1101, hexadecimal CD)

114 + 128 = 242 (binary 1111 0010, hexadecimal F2)

4. Lattice font structure

In the Chinese character dot matrix font, each bit of each byte represents a point of a Chinese character. Each Chinese character is composed of a rectangular dot matrix. 0 represents no and 1 represents a point. Draw 0 and 1 in different colors to form a Chinese character. The commonly used dot matrix has three font matrices: 12 * 12, 14 * 14 and 16 * 16.

The font can be divided into horizontal matrix and vertical matrix according to the different points represented by bytes. At present, most font libraries are stored in horizontal matrix (the most used should be the early UCDOS font library). The vertical matrix is generally because some LCD adopts the vertical scanning display method. In order to improve the display speed, the font matrix is made into vertical matrix, Save matrix conversion when displaying. What we describe next refers to the horizontal matrix font.

For a 16 * 16 matrix, the number of bits required is 16 * 16 = 256 bits, and each byte is 8 bits. Therefore, 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, you only need to read 32 bytes at one time and print every two bytes as a line to form a Chinese character.

The lattice structure is shown in the figure below:

  5. Chinese character dot matrix acquisition  

  Using location code to obtain Chinese characters

The Chinese character dot matrix font is stored according to the sequence of location codes. Therefore, we can obtain the dot matrix of a font according to location. 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.

  Acquiring 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

By combining this formula with the formula for obtaining the Chinese character dot matrix, the position of the Chinese character dot matrix can be obtained.

2, Calling Opencv library programming under Ubuntu to display pictures and student number names

1. Open the Ubuntu system, create a new folder, and put the following files in this folder

The contents of the document are as follows  

HZ file of 24 dot matrix

The file opens as follows

 

zf file of Classl code

The file opens as follows

 

  A picture of you

  txt file of the content you want to display on the picture

 

When the above documents are ready, start using the code

Note: Opencv needs to be installed to run this program

Open the terminal under this folder and enter the following code

gedit main.cpp

  Then you can get the following interface and write code under this interface

  The code is as follows

#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="1.jpg";
    char* logo_path=(char*)"logo1.txt";
    put_text_to_image(20,300,image_path,logo_path);
    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++;                                                //Shift right one pixel
		}
		p.y++;                                                    //Move down one pixel
	}
}

void put_text_to_image(int x_offset,int y_offset,String image_path,char* logo_path){//Put Chinese characters 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=15;//Length of characters to print
    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();
}

Enter the following code to compile the above code

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

 

Then get the following file named test

  After you get the above file, you can run it. Enter the following code

./test

  The results are as follows

 

3, Summary

In this experiment, we learned the principle of Chinese character dot matrix and the relationship between the internal code, national standard code and location code. How to display your name and student number with Chinese character dot matrix under ubuntu system

4, References

Principle of Chinese character lattice font_ YesKing_new column - CSDN blog

Print Chinese characters on the picture (C + +, OPENCV + font library)_ junseven164 blog - CSDN blog

Tags: Javascript html5 html

Posted on Wed, 17 Nov 2021 10:46:20 -0500 by cubik