一、 点阵字库的原理

一、 汉字编码

1. 区位码

在国标 GD2312—80 中规定,所有的国标汉字及符号分配在一个 94 行、94 列的阵中,方阵的每一行称为一个“区”,编号为 01 区到 94 区,每一列称为一个“位”,编号01 位到 94 位,方阵中的每一个汉字和符号所在的区号和位号组合在一起形成的四个阿伯数字就是它们的“区位码”。区位码的前两位是它的区号,后两位是它的位号。用区位码可以唯一地确定一个汉字或符号,反过来说,任何一个汉字或符号也都对应着一个唯一区位码。汉字“母”字的区位码是 3624,表明它在方阵的 36 区 24 位,问号“?”的区位码0331,则它在 03 区 3l 位。

2. 机内码

汉字的机内码是指在计算机中表示一个汉字的编码。机内码与区位码稍有区别。如上述,汉字区位码的区码和位码的取值均在 1~94 之间,如直接用区位码作为机内码,就与基本 ASCII 码混淆。为了避免机内码与基本 ASCII 码的冲突,需要避开基本 ASCII 码
中的控制码(00H~1FH),还需与基本 ASCII 码中的字符相区别。为了实现这两点,可先在区码和位码分别加上 20H,在此基础上再加 80H(此处“H”表示前两位数字为十六进数)。经过这些处理,用机内码表示一个汉字需要占两个字节,分别 称为高位字节和低位字
节,这两位字节的机内码按如下规则表示:

高位字节 = 区码 + 20H + 80H(或区码 + A0H)

低位字节 = 位码 + 20H + 80H(或位码 + AOH)
由于汉字的区码与位码的取值范围的十六进制数均为 01H~5EH(即十进制的 01~4),所以汉字的高位字节与低位字节的取值范围则为 A1H~FEH(即十进制的 161~254)。

例如,汉字“啊”的区位码为 1601,区码和位码分别用十六进制表示即为 1001H,的机内码的高位字节为 B0H,低位字节为 A1H,机内码就是 B0A1H。

二、 点阵字库结构

1. 点阵字库存储

在汉字的点阵字库中,每个字节的每个位都代表一个汉字的一个点,每个汉 字都是由一个矩形的点阵组成,0 代表没有,1 代表有点,将 0 和 1 分别用不同 颜色画出,就形成了一个汉字,常用的点阵矩阵有 1212, 1414, 16*16 种字库。
字库根据字节所表示点的不同有分为横向矩阵和纵向矩阵,目前多数的字库 都是横向矩阵的存储方式(用得最多的应该是早期UCDOS 字库),纵向矩阵般是因为有某些液晶是采用纵向扫描显示法,为了提高显示速度,于是便把字矩阵做成纵向,省得在显示时还要做矩阵转换。我们接下去所描述的都是指横矩阵字库。

2. 16*16 点阵字库

1616 点阵字库 对于 1616 的矩阵来说,它所需要的位数共是 16*16=256 个位,每个字 节为 8 位,因此,每个汉字都需要用 256/8=32 个字节来表示。 即每两个字节代表一行的 16 个点,共需要 16行,显示汉字时,只需一次 性读取 32 个字节,并将每两个字节为一行打印出来,即可形成一个汉字。

点阵结构如下图所示:

3 1414 与 1212 点阵字库

对于 1414 和 1212 的字库,理论上计算,它们所需要的点阵分别为(14 14/8)=25, (1212/8)=18 个字节,但是,如果按这种方式来存储,那么取 点阵和显示时,由于它们每一行都不是 8 的整位数,因此,就会涉到点阵的算处理问题,会增加程序的复杂度,降低程序的效率。 为了解决这个问题,有些点阵字库会将 1414 和 1212 的字库按 1614 和 1612 来存储,即,每行还是按两个字节来存储,但是 1414 的字库,每 两个字节的最后两位是没有使用,1212 的字节,每两字节的最后 4 位是没使用,这个根据不同的字库会有不同的处理方式,所以在使用字库时要注意这个 问题,特别是 14*14 的字库。

三、 汉字点阵获取

1. 利用区位码获取汉字

汉字点阵字库是根据区位码的顺序进行存储的,因此,我们可以根据区位获取一个字库的点阵,它的计算公式如下: 点阵起始位置 = ((区码- 1)*94 + (位码 – 1)) * 汉字点阵字节数获取点阵起始位置后,我们就可以从这个位置开始,读取出一个汉字的点阵。

2. 利用汉字机内码获取汉字

前面我们己经讲过,汉字的区位码和机内码的关系如下:
机内码高位字节 = 区码 + 20H + 80H(或区码 + A0H)
机内码低位字节 = 位码 + 20H + 80H(或位码 + AOH)
反过来说,我们也可以根据机内码来获得区位码:
区码 = 机内码高位字节 - A0H
位码 = 机内码低位字节 - AOH
将这个公式与获取汉字点阵的公式进行合并计就可以得到汉字的点阵位置。
我们可以使用软件ultraedit配合字库查看工具来查看每一个文字在字库中的位置。

使用教程:

先创建了一个文本文件并添加了我自己的名字,并以ANSI的编码格式保存。

然后用UltraEdit使用十六进制模式编辑这个文本文件,就会得到每个字体在字库中的位置。

接着打开我们下载的字库查看工具,打开字库后依次查找每一个汉字。

以上图片中的汉字代码和UltraEdit中使用16进制查看文字得到的代码一致,因此验证成功。

二、代码


#include <unistd.h>
#include <stdio.h>
#include <opencv/cxcore.h>
#include <sys/types.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;
const int CC_SIZE = 16;
const int SAFE_WIDTH = 10;
const int CC_NUMBER = 15;
// 姓名
unsigned char name[7] ="王尉铭";
unsigned int name_code[3][2];// 学号
unsigned int id_code[12][2] = { { 0xa3, 0xb6 },{ 0xa3, 0xb3 },{ 0xa3, 0xb1 },{ 0xa3, 0xb6 },{ 0xa3, 0xb0 },{ 0xa3, 0xb7 },{ 0xa3, 0xb0 },{ 0xa3, 0xb4 },{ 0xa3, 0xb0 },{ 0xa3, 0xb3 },{ 0xa3, 0xb0 },{ 0xa3, 0xb5} };// 保存字节的数组
unsigned char mat[16][2];
FILE* HZK16;
IplImage* img;
void get_area_position_codes();
void get_mat(int a_code, int p_code);
void open_file();
void draw_one_cc(int num);
void release();
int main()
{open_file();get_area_position_codes();// 写名字int i, j;for (i = 0; i < 3; ++i){get_mat(name_code[i][0], name_code[i][1]);draw_one_cc(i);}// 写学号for (j = 0; j < 12; ++j){get_mat(id_code[j][0] - 0xa0, id_code[j][1] - 0xa0);draw_one_cc(i + j);}// 显示图片cvShowImage("IMAGE", img);cvWaitKey(0);release();return 0;
}void get_area_position_codes()
{for (int i = 0; i < 3; ++i)for (int j = 0; j < 2; ++j)name_code[i][j] = name[i * 2 + j] - 0xa0;
}void get_mat(int a_code, int p_code)
{long offset;offset = (94 * (a_code - 1) + (p_code - 1)) * 32L;// 读取数据存入数组fseek(HZK16, offset, SEEK_SET);fread(mat, 32, 1, HZK16);
}void open_file()
{char pbuf[100];getcwd(pbuf, 100);cout<<pbuf<<endl;strcat(pbuf, "/HZKf1616.hz");// 读取图片if ((img = cvLoadImage("test.jpg")) == NULL)exit(1);// 打开字体文件if ((HZK16 = fopen(pbuf, "rb")) == NULL)exit(1);
}void draw_one_cc(int num)
{// 图片的像素值int width, height;width = img->width;height = img->height;// 开始的x y像素点int start_x, start_y, size, current_start_x, current_start_y;size = CC_SIZE + SAFE_WIDTH;start_x = width - CC_NUMBER * size;start_y = height - CC_SIZE - SAFE_WIDTH;// 开始绘制CvScalar cs;for (int i = 0; i < 16; ++i)for (int j = 0; j < 2; ++j)for (int k = 0; k < 8; k++)if (mat[i][j] & (0x80 >> k)){cout << mat[i][j] << endl;// 绘点current_start_x = j * 8 + k + start_x + size * num;current_start_y = start_y + i;cs = cvGet2D(img, current_start_y, current_start_x);cs.val[0] = 0;cs.val[1] = 0;cs.val[2] = 0;cvSet2D(img, current_start_y, current_start_x, cs);}
}void release()
{cvReleaseImage(&img);fclose(HZK16);img = NULL;HZK16 = NULL;
}

这段代码中,我定义名字时:是在windows上写好了再传到树莓派上编译执行代码,因为在树莓派上直接输入名字或者使用vim定义名字都会出错:因为字符的编码格式的不同(windows下使用GBK或者utf_8显示中文,而树莓派使用的是ISO 8859-1拉丁语显示中文)

工具、字库和代码我都已经上传在我的github中,有兴趣的可以去下载使用:

(工具下载地址)https://github.com/Budexing/Tools/tree/master/ziku
(代码下载地址)
https://github.com/Budexing/Embeded-System/tree/master/opencv
而UltraEdit可以直接百度下载试用30天。

树莓派下利用opencv在图片上画汉字点阵(写一句话)相关推荐

  1. 基于Ubuntu系统调用opencv——在图片上显示汉字和数字

    文章目录 一. 认识汉字编码 (1)区位码 (2)机内码 (3)点阵字库结构 (4)汉字点阵获取 二. 实例--调用opencv在图片上显示文字 (1)准备工作 (2)撰写代码 (3)编译运行 三. ...

  2. Unity 利用像素点在图片上画线(RawImage)

    原理:创建透明度为0的Texture2D,利用改变像素点的颜色,实现画线功能. 创建图片 rawimage 的大小一定要与屏幕大小保持一致 代码部分: 完整代码:挂载RawImage上,对应组件拖进去 ...

  3. OpenCV在图片上画线和矩形

    今天讲一下通过opencv的Line函数,在图像中绘制一条我们想要的直线或者线段,以及使用Rectangle函数绘制矩形: CV_RGB 创建一个色彩值. #define CV_RGB( r, g, ...

  4. 利用OpenCV获取图片上某一点的颜色HSV值

    在进行图像处理时我们经常需要根据图像的颜色提取特定的区域处理,很多时候 RGB 是不适合的,我们需要知道感兴趣区域的区域HSV各分量的范围. RGB 颜色使用 QQ 截图工具或者 Windows 画图 ...

  5. Ubuntu下的opencv:在图片上加汉字和数字

    文章内容:本文主要介绍汉字的编码规则,并在ubuntu下调用opencv把汉字和数字叠加在图片上. 一.汉字编码 (一)区位码 在国标 GD2312-80 中规定,所有的国标汉字及符号分配在一个 94 ...

  6. 基于Ubuntu系统,调用opencv在图片上显示数字和汉字

    文章目录 一.汉字编码的介绍 1.汉字编码的发展过程 (1)汉字编码产生的原因 (2)常用的汉字编码 2.区位码 (1)产生原因 (2)概念简述 (3)区域分布情况 3.机内码 (1)基本概念 (2) ...

  7. 用python的opencv库在图片上画出蓝底黑字的文本框

    以下是使用Python的OpenCV库实现在图片上绘制的示例代码: import cv2# 读入图片 img = cv2.imread('example.jpg')# 在图片上绘制红色矩形框 cv2. ...

  8. 通过opencv在图片上加上文字_基于Ubuntu16

    本文主要介绍,如何通过**C++**语言在Ubuntu操作系统下的OpenCV中将一个图片叠加上文字 通过opencv在图片上叠加上文字 一.汉字点阵字库原理 1.汉字的三种编码 1.1区位码 1.2 ...

  9. opencv在图片上添加中文汉字(c++以及python)

    文章目录 一. 汉字点阵字库实现原理 1. 汉字编码 1.1 区位码 1.2 机内码 2. 点阵字库结构 2.1 点阵字库存储 2.2 16*16点阵字库 3. 汉字点阵获取 3.1 利用区位码获取汉 ...

最新文章

  1. 10年测试工程师首谈测试前景,如何25天进入滴滴大厂
  2. Vue开发跨端应用(七)添加生成二维码
  3. Excel,此文件中的某些文本格式可能已经更改,因为它已经超出最多允许的字体数。...
  4. 人工智能时代,为什么很多人都看好Python的发展?
  5. 自动化测试之iframe窗口的切换
  6. python绘制饼状图带圆心距_matplotlib可视化饼图
  7. 听小鹏讲废话之OSI
  8. 论述HTML5平台的若干重要特性
  9. ios 权限提示语_iOS工作室都在用按键v1.6.1(体验版)
  10. Vue-cli3配置教程入门
  11. Javascript 调用百度地图不显示
  12. MySQL单表删除重复列SQL语句
  13. 【bzoj2759】一个动态树好题
  14. python怎样装pandas_小白学python:坑一:如何安装pandas和numpy
  15. POJ 3311 Hie with the Pie(状压DP + Floyd)
  16. 换头软件测试,抖音女大十八变换脸测试
  17. ArcGIS土地利用重分类(一)简单的reclass by table方法
  18. VS2013 安装及问题解决
  19. js web端扫码枪对接
  20. android robotium教程,Robotium + Android studio

热门文章

  1. excel合并单元格为文本时,日期变成数字
  2. 【亲测有效】解决GitHub下载过慢和下载项目失败的问题
  3. hdu6112 今夕何夕
  4. android按钮中添加图标,android 控件 带图标的按钮(ImageButton)
  5. 提供羟基、羧基、醚基、酯基、氨基、磺酸基、烯基、苄基、腈基、胍类等功能性离子液体定制合成服务
  6. 对于初学者,本文为您提供了对机器视觉的全面理解
  7. MyBatis--总体框架设计
  8. t分布 u分布 卡方分布_f分布t分布与卡方分布
  9. 微信小程序消息推送、接收消息事件、发送客服消息
  10. tp5的ajax搜索后分页,修改TP5的分页类使之Ajax分页有效