Linux is based on OpenCv and built-in code to add text to the picture

1, Principle

1. 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, 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 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 + AOH)

Since the hexadecimal numbers in the value range of area code and bit code of Chinese characters are 01h ~ 5eh (i.e. 01 ~ 94 in decimal system), the value range of high-order byte and low-order byte of Chinese characters is a1h ~ FEH (i.e. 161 ~ 254 in decimal system).

2. 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. The location code of the Chinese character "mother" is 3624, indicating that it is 24 digits in area 36 of the square matrix. If the location code of the question mark "?" is 0331, it is 3l digits in area 03.

2, Realize

1. Preparation

  • One target picture in image.jpg format
  • Add the text to be displayed to the txt file in the format of name.txt
    The file code needs to be ASCII. If the code is wrong, it will be garbled. You can try to modify the file code directly or create a corresponding coded text under Windows and directly transmit it to Linux.
  • 24 * 24 dot matrix font library HZKf2424.hz
  • ascii font Asci0816.zf

2. Code

#include<iostream>
#include<opencv/cv.h>
#include"opencv2/opencv.hpp"
#include<opencv/cxcore.h>
#include<opencv/highgui.h>
#include<math.h>
#include<fstream>
#include<string>

using namespace cv;
using namespace std;

/*Draw text
	image:picture
	x_offset:Offset from picture
	y_offset: Offset from picture
	offset: Offset of Chinese characters in font library
*/
void PaintSChinese(Mat& image, int x_offset, int y_offset, unsigned long offset);
void PaintSAscii(Mat& image,int x_offset, int y_offset, unsigned long offset);//Draw character

/*Image preprocessing and saving
	x_offset:Offset from picture
	y_offset: Offset from picture
	imagePath: The image path type is cv String, or c++ string
	txtPath: The text path type can only be c++ string
*/
void putTextToImage(int x_offset,int y_offset,String imagePath ,string txtPath);

int main(){	
	//Text path
	string txtPath="name.txt";
	//Picture path	
	String imagePath="image.jpg";
	//To get the picture size
	Mat image = imread(imagePath);

	putTextToImage(image.cols-500.,image.rows-1000,imagePath,txtPath);
	return 0;
}

void putTextToImage(int x_offset,int y_offset,String imagePath ,string txtPath)
{
	//Get pictures through picture path
	Mat image = imread(imagePath);
	
	//Area code and bit code
	unsigned char qh, wh;
	//Offset
	unsigned long offset;	
	//Read the text file where the text is stored, coded as ISO-8859
	fstream file;
	//Open file stream, read-only
	file.open(txtPath,ios::in);
	//Cannot open
	if(!file){
		cout<<"Can't open txtfile,Please check the path!"<<endl;
		exit(1);
	
	}
	//Contents of stored documents
	string hexcode;
	//Contents of temporary documents
	string tmp;
	//Loop reading file contents
	while(file.peek()!=EOF){
		//Assign the read content to the temporary variable tmp
		file>>tmp;
		//Append the value of the temporary variable to hexcode
		hexcode.append(" ");
		hexcode.append(tmp);
		//Clear the value of tmp
		tmp.clear();
	}
	file.close();//Close file stream

	int x = x_offset, y = y_offset;//x. Y: coordinates of the beginning of the text drawn on the picture

	for (int m = 0; m < hexcode.size();)
		if (hexcode[m] == 0x23)                /* Ends when the '#' sign is read */
			break;
		//Judge whether the two high-order hexadecimal numbers are greater than or equal to b0 (the first Chinese character is b0a1), which should be found from the Chinese character library
		else if (hexcode[m] > 0xffffffaf)
		{
			qh = hexcode[m] - 0xaf;						/*Calculation area code*/
			wh = hexcode[m+1] - 0xa0;						/*Calculation bit code*/
			offset = (94 * (qh - 1) + (wh - 1)) * 72L;/*Calculate the offset of the Chinese character in the font*/
			PaintSChinese(image, x , y , offset);
			m = m + 2;                               //One Chinese character takes up two chars, so add 2                             						
			x += 24;      //A Chinese character occupies 24 pixels in the picture, so the horizontal coordinates are + 24 each time
		}
		else
		{
			wh = hexcode[m];
			offset = wh * 16L;                   //Calculate the offset of other English characters
			PaintSAscii(image, x, y, offset);
			m++;                                //A char
			//Originally, it should be 8 * 16, but it is a little smaller than 24 * 24, so it is changed to 16 * 32. The original pixel is now drawn with four pixels
			x += 16;
		}

		IplImage imagee1=(IplImage(image));//Type conversion
		IplImage *imagee=&imagee1;

		Mat results=cvarrToMat(imagee);
		cv::imwrite("results.jpg", results);//Save results as
		cv::waitKey();				
}


void PaintSChinese(Mat& image, int x_offset, int y_offset, unsigned long offset){
	//Coordinates of pixels actually drawn on the picture
	Point p;
	p.x = x_offset;
	p.y = y_offset;
	//Open hzk24 Chinese character library file
	FILE *HZK;
	char buff[72];            //Film for storing Chinese characters
	if ((HZK = fopen("HZKs2424.hz", "rb")) == NULL){
		printf("Can't open hzk24.hz,Please check the path!");
		//getch();
		exit(0);
	}
	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;
	//Transpose the Chinese character film matrix because the Chinese character film stores the data after the device (reverse)
	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 PaintSAscii(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;
	}
	
}

3, Results

Compile code

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

function

./main

1. Original drawing

2. Renderings

4, Summary

Master the internal code and learn to modify pictures through OpenCV

5, Reference

https://blog.csdn.net/weixin_56102526/article/details/121178128

Keywords: Linux Operation & Maintenance OpenCV

Added by khendar on Tue, 09 Nov 2021 20:56:08 +0200