IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 点阵汉字的字模读取与显示 -> 正文阅读

[嵌入式]点阵汉字的字模读取与显示

一、串口传输文件

1.串口连接

(1)首先下载串口调试助手:

链接:https://pan.baidu.com/s/1T-7cHCwenyQCfyJSyRusKg?
提取码:jack

(2)使用两台电脑连接:使用借助 usb转rs232 模块和杜邦线,建立起串口连接,连线为GND接GND,电源接电源,TDX和RDX反接

(3)传输:

?打开图中的第一个软件

在发送电脑里:选择你需要打开的文件,选择完毕之后,点击打开串口,以及调整波特率,然后直接点击发送文件即可

?在接受电脑:从接收完毕之后点击图中的保存数据,即可看到数据保存成功

?

我这里保存的文件打开之后是这样的

?

?3.预算文件大小、波特率和传输时间三者之间的关系,对比实际传输时间。

115200波特率下:

600000波特率下面

?可以看见在不同波特率下面传输时间是不同的,但这里实际传输速率要慢得多(忘记整秒表了,但是在软件下面在传输的时候是有时间的)

总结一下就是:理论来说,传输时间=文件大小/波特率,但这里要注意计算时文件大小的单位换算。同时当发送速率提升时,发送所需的时间也会缩短,但时间并不像理论那样缩短,是因为当速率上升时,丢包率也会上升,重传导致时间增加。总的来说还是原理还是比较了解了,但细致过程还没那么清晰。

二、在Ubuntu下用C/C++(或python) 调用opencv库编程显示一张图片,并打开一个名为"logo.txt"的文本文件

1、汉字点阵原理

所谓一个字的点阵. 其实就是指这个汉字用多少个象素点来描述. 每个象素点显示为什么颜色, 通常情况下, HZK16采用的是1616点阵, 即256个象素点描述一个汉字.
这些点的颜色分为两种, 一种是前景色, 一种是显示为背景色
1、汉字编码
①区位码:区位码的前两位是它的区号,后两位是它的位号。用区位码就可以唯一地确定一个汉字或符号。
②机内码:汉字的机内码是指在计算机中表示一个汉字的编码。
2、点阵字库结构
①点阵字库存储:字库根据字节所表示点的不同有分为横向矩阵和纵向矩阵,目前多数的字库都是横向矩阵的存储方式(用得最多的应该是早期 UCDOS 字库),纵向矩阵一般是因为有某些液晶是采用纵向扫描显示法,
②1616点阵字库:对于 1616 的矩阵来说,它所需要的位数共是 1616=256 个位,每个字
节为 8 位,因此,每个汉字都需要用 256/8=32 个字节来表示。
例如:
③1414和1212点阵字库:对于 1414 和 1212 的字库,理论上计算,它们所需要的点阵分别为(1414/8)=25, (1212/8)=18 个字节,由于它们每一行都不是 8 的整位数,所以有些点阵字库会将 1414 和 1212 的字库按 1614和 1612 来存储,即,每行还是按两个字节来存储。
3、汉字点阵获取
① 利用区位码:*点阵起始位置 = ((区码- 1)94 + (位码 – 1)) * 汉字点阵字节数
②利用机内码:
机内码高位字节 = 区码 + 20H + 80H(或区码 + A0H)
机内码低位字节 = 位码 + 20H + 80H(或位码 + AOH)
区码 = 机内码高位字节 - A0H
位码 = 机内码低位字节 - AOH
?

2.使用opcv让汉字点阵呈现在图片上

1.首先得在同一目录下准备几个文件:在下面标识出来了,一个是图片:1.png,一个是需要输入的汉字(自己找一个文本写就行),另外两个我放一个链接下载就行:链接:https://pan.baidu.com/s/1pxprO_PD3y0b-6g9P2bqzA?
提取码:jack

?

?2.打开终端进入你保存文件的位置(cd 路径名),编写程序(gedit 文件名.cpp),代码如下:记得改图片和文件的路径就行

#include<iostream>

#include<opencv/cv.h>

#include"opencv2/opencv.hpp"

#include<opencv/cxcore.h>

#include<opencv/highgui.h>

#include<math.h>
using namespace cv;

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);
void putTextToImage(int x_offset,int y_offset,String imagePath ,char* txtPath);
int main(){

    String image_path="1.png";

    char* logo_path=(char*)"logo.txt";

    putTextToImage(20,300,image_path,logo_path);

    return 0;

}
void putTextToImage(int x_offset,int y_offset,String imagePath ,char* txtPath)
{
	//通过图片路径获取图片
	Mat img = imread(imagePath);
	unsigned char qh, wh;
	unsigned long offset;	
	//用于存放从记事本读取的十六进制		
	char hexcode[30];          
	//打开包含名字的txt文件,转为十六进制,存入hexcode中
	FILE* filetxt;
	if ((filetxt = fopen(txtPath, "rb")) == NULL){
		printf("Can't open txtfile,Please check the path!");
		//getch();
		exit(0);
	}
	fseek(filetxt, 0, SEEK_SET);			 /*将文件指针移动到偏移量的位置*/
	fread(hexcode, 19, 1, filetxt);
	int x = x_offset, y = y_offset;//x,y:在图片上绘文字的起始的坐标
	for (int m = 0; m < 19; )
		if (hexcode[m] == 0x23)                /* 当读取到‘#’号时结束 */
			break;
		//判断高阶两个十六进制数,大于或等于b0(汉字第一个是b0a1)的都应该从汉字字库中找
		else if (hexcode[m] > 0xffffffaf)
		{
			qh = hexcode[m] - 0xaf;						/*计算区码*/
			wh = hexcode[m+1] - 0xa0;						/*计算位码*/
			offset = (94 * (qh - 1) + (wh - 1)) * 72L;/*计算该汉字在字库中偏移量*/
			PaintSChinese(img, x , y , offset);
			m = m + 2;                               //一个汉字占两个char,所以加2                             						
			x += 24;      //一个汉字在图片上占24个像素点,所以水平坐标每次+24
		}
		else
		{
			wh = hexcode[m];
			offset = wh * 16L;                   //计算其他英文字符的偏移量
			PaintSAscii(img, x, y, offset);
			m++;                                //一个char
			//原本应该8*16,但是和24*24比小了点,所以改为16*32,原本的一个像素点现在用四个像素点绘画
			x += 16;
		}
		cv::imshow("image", img);

    cv::waitKey();			
}
void PaintSChinese(Mat& image, int x_offset, int y_offset, unsigned long offset){
	//实际在图片上绘制的像素点坐标
	Point p;
	p.x = x_offset;
	p.y = y_offset;
	//打开DZKs1516汉字库文件
	FILE *HZK;
	char buff[72];            //存放汉字字膜
	if ((HZK = fopen("HZKf2424.hz", "rb")) == NULL){
		printf("Can't openHZKf2424.hz,Please check the path!");
		//getch();
		exit(0);
	}
	fseek(HZK, offset, SEEK_SET);			 /*将文件指针移动到偏移量的位置*/
	fread(buff, 72, 1, HZK);				 /*从偏移量的位置读取72个字节,每个汉字占72个字节*/
	bool mat[24][24];                        /*定义一个新的矩阵存放转置后的文字字膜 */
	int i, j, k;
	//转置汉字字膜矩阵,因为汉字字膜存储的是装置后的数据(反的)
	for (i = 0; i<24; i++)                 /*24x24点阵汉字,一共有24行*/
	{
		for (j = 0; j<3; j++)                /*横向有3个字节,循环判断每个字节的*/
			for (k = 0; k<8; k++)              /*每个字节有8位,循环判断每位是否为1*/
				if (buff[i * 3 + j] & (0x80 >> k))    /*测试当前位是否为1*/
				{
					mat[j * 8 + k][i] = true;          /*为1的存入新的字膜中*/
				}
				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);		  //写(替换)像素点
			p.x++;                                                //右移一个像素点
		}
		p.y++;                                                    //下移一个像素点
	}

}
void PaintSAscii(Mat& image, int x_offset, int y_offset, unsigned long offset){
	//绘制的起点坐标
	Point p;
	p.x = x_offset;
	p.y = y_offset;
	 //存放ascii字膜
	char buff[16];           
	//打开ascii字库文件
	FILE *ASCII;
	if ((ASCII = fopen("Asci0816.zf", "rb")) == NULL){
		printf("Can't open Asci0816.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++)                  //十六个char
	{
		p.x = x_offset;
		for (j = 0; j < 8; j++)              //一个char八个bit
		{
			p1 = p;
			if (buff[i] & (0x80 >> j))    /*测试当前位是否为1*/
			{
				/*
					由于原本ascii字膜是8*16的,不够大,
					所以原本的一个像素点用4个像素点替换,
					替换后就有16*32个像素点
					ps:感觉这样写代码多余了,但目前暂时只想到了这种方法
				*/
				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;            //原来的一个像素点变为四个像素点,所以x和y都应该+2
		}
		p.y+=2;
	}
	
}

3.再次打开终端:进入刚刚你保存文件的路径,输入命令g++ lan.cpp` pkg-config --cflags --libs?opencv?-o main`(记得改自己刚刚编写的程序名),最后编译./文件名?

4.成果展示

三、实验总结

主要借鉴了很多大佬的知识,所以显得很简单?

四、参考资料

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-20 18:33:24  更:2021-11-20 18:35:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:44:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码