Serial transmission and Ubuntu use C to call opencv library to add Chinese characters and numbers to photos

1, Serial communication between PC s to transfer files

1. Experimental equipment

Two laptops, two USB to TTL modules, two DuPont lines, stopwatch.

2. Operation and effect

The RX and TX of the two USB are cross connected and plugged into the USB ports of the two computers respectively
Open serial port assistant
The settings are as follows: open the file and send the file,


The receiving effect is as follows:

Theoretical transfer time = (file size) × 8) / baud rate,
As the baud rate increases, the time decreases,
Here, the result time is greater than the theoretical time. Packet loss and retransmission occur in the transmission process. Sometimes the receiver will accept pause, which may be due to the unstable connection of DuPont line.

2, Under Ubuntu, call opencv library with C to add Chinese characters and numbers to photos

1. Principle of Chinese character dot matrix font library

Location code
It is stipulated in the national standard GD2312-80 that all national standard Chinese characters and symbols are allocated in a square matrix with 94 rows and 94 columns. Each row of the square matrix is called an "area", numbered from 01 to 94, and each column is called a "bit", numbered from 01 to 94, The area code and tag number of each Chinese character and symbol in the square array are combined to form four Arabic numerals, which are their "location code". The first two digits of the location code are its area code and the last two digits are its bit code. A Chinese character or symbol can be uniquely determined by location code. Conversely, any Chinese character or symbol also corresponds to a unique location code.

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. If the location code is directly used as the internal code, it will be confused with the basic ASCII code. In order to avoid the conflict between the internal code and the basic ASCII code, it is necessary to avoid the control code (00H~1FH) in the basic ASCII code and distinguish it from the characters in the basic ASCII code. In order to achieve these two points, 20H can be added to the area code and bit code respectively, and 80h can be added on this basis (here "H" means that the first two digits are hexadecimal numbers). After these processes, it takes two bytes to represent a Chinese character with internal code, which are called high byte and low byte respectively. 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 + A0H)

Lattice font storage
In the dot matrix font of Chinese characters, 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. There are three commonly used dot matrix font types: 1212, 1414 and 16 * 16.

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:
Dot matrix start position = ((area code - 1) 94 + (bit code - 1)) * number of Chinese dot matrix 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
We can obtain the location code according to the internal code:

Area code = high byte of internal code - A0H
Bit code = low byte of internal code - A0H
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. Add numbers and Chinese characters to the picture

cd enters the file directory

Add pictures, text files and font files to this directory

Input instruction add program:
gedit test.cpp

The program 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="/home/cm/picture/IMG_20210210_200659.jpg";
    char* logo_path=(char*)"/home/cm/picture/logo.txt";
    put_text_to_image(125,520,image_path,logo_path);//Arrange the text to be displayed from the picture pixel coordinates (125520)
    return 0;
}
//Coordinates of the starting point of the text drawn on the picture
void paint_ascii(Mat& image,int x_offset,int y_offset,unsigned long offset){
	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("/home/cm/picture/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;
	}
}
//Replace pixels in picture
void paint_chinese(Mat& image,int x_offset,int y_offset,unsigned long offset){
    Point p;
    p.x=x_offset;
    p.y=y_offset;
    FILE *HZK;
    char buff[72];//72 bytes for storing Chinese characters
   if((HZK=fopen("/home/cm/picture/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
	}
}
//Put Chinese characters on the picture
void put_text_to_image(int x_offset,int y_offset,String image_path,char* logo_path){
//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=22;//Length of characters to print (bytes)
    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);//display picture
    cv::waitKey();
}

Compile and enter the following instructions:

result:

3, Summary

Through the two small experiments, on the one hand, I learned how to use the serial port for simple communication on the two computers, and the communication time with the serial port is still relatively long, because of delay, packet loss, poor contact and other reasons. On the other hand, I learned the coding rules and storage rules of Chinese characters, and learned how to add words and numbers to pictures, It's easy to be careful in the whole process.

4, References

https://blog.csdn.net/m0_58414679/article/details/121313982

Keywords: C OpenCV

Added by ody on Fri, 19 Nov 2021 22:28:26 +0200