课程实验:编程读汉字点阵字库,把自己的名字和学号叠加到图片的右下位置。

主要步骤分为三部分

第一部分:读取图片(文件读取)

第二部分:读取文字并从字库中提取相应的编码(字库的存储原理)

第三部分:将相应的编码映射到图片的相应位置实现文字“写在图片上”(提取编码的转换映射)

 

第一部分:读取图片(文件读取)

可以利用opencv提供的函数cvLoadImage().(这里的将字库一并导入)

 /******************************************************
函数名称: openfile
函数功能: 打开字库和图片
传入参数:
返 回 值:
建立时间: 2018-05-07
修改时间:
建 立 人: 重交亲爸爸
修 改 人:
其它说明:
******************************************************/
void ShowName::openfile(){
char pbuf[];
_getcwd(pbuf, );
strcat(pbuf, "/HZKf2424.hz");
char pbufASC[];
_getcwd(pbufASC, );
strcat(pbufASC, "/Asci0816.zf");
// 读取图片
if ((img = cvLoadImage("test.png")) == NULL)exit();
// 打开字体文件
if ((HZK24 = fopen(pbuf, "rb")) == NULL)exit();
//打开asci8*16文件
if ((ASI816 = fopen(pbufASC, "rb")) == NULL)exit();
}

这里提醒各位记得要将这些字库关闭。养成好的习惯

 /******************************************************
函数名称: ~ShowName
函数功能: 释放空间
传入参数:
返 回 值:
建立时间: 2018-05-07
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
ShowName::~ShowName(){
cvReleaseImage(&img);
fclose(HZK24);
fclose(ASI816);
if (CONTERNER!=NULL)
fclose(CONTERNER);
img = NULL;
HZK24 = NULL;
ASI816 = NULL;
CONTERNER = NULL;
}

第二部分:读取文字并从字库中提取相应的编码(字库的存储原理)

这里先介绍下字库的存储方式:以下为引用的资料:

汉字点阵获取

1. 利用区位码获取汉字
汉字点阵字库是根据区位码的顺序进行存储的,因此,我们可以根据区位来
获取一个字库的点阵,它的计算公式如下:

点阵起始位置 = ((区码- 1)*94 + (位码 – 1)) * 汉字点阵字节数

获取点阵起始位置后,我们就可以从这个位置开始,读取出一个汉字的点阵。
2利用汉字机内码获取汉字
前面我们己经讲过,汉字的区位码和机内码的关系如下:

机内码高位字节 = 区码 + 20H + 80H(或区码 + A0H)
机内码低位字节 = 位码 + 20H + 80H(或位码 + AOH)
反过来说,我们也可以根据机内码来获得区位码:
区码 = 机内码高位字节 - A0H
位码 = 机内码低位字节 - AOH
将这个公式与获取汉字点阵的公式进行合并计就可以得到汉字的点阵位置。

3.以下为汉字的存储原理:

对于 24*24的点阵字库,存放格式如下: 纵向存放 3 个字节(24 位),横向存放24 个字节,每个字模占 72 个字节 字符排列顺序如下:

1 4 7 10 ......

2 5 8 11 ......

3 6 9 12 ......

对于 16*16 的点阵字库,存放格式如下: 横向存放 2 个字节(16 位),其中第二个字节没有多余的数据 纵向存放 16个字节,

每个字模占 32 个字节 字符排列顺序如下:

1 2

3 4

5 6

......

对于 14*14 的点阵字库,存放格式如下: 横向存放 2 个字节(16 位),其中第二个字节的后 2 位是多余的数据 纵向存放 14个字节,每个字模占 28 个字节

字符排列顺序如下:

1 2

3 4

5 6

......

对于 12*12 的点阵字库,存放格式如下: 横向存放 2 个字节(16 位),其中第二个字节的后 4 位是多余的数据 纵向存放 12个字节,每个字模占 24 个字节 字符排列顺序如下:

1 2

3 4

5 6 ......

******************************************************/资料到此

这个资料有点抽象,不过没关系。我们使用实例图片进行说话。

这个是8*16点阵的ASCII码字库

这个是16*16点阵汉字库的字

这个是24*24点阵字库的字

非常明显的看出8*16和16*16是正放的,而24*24的是侧着,而且是反过来的字体。

对于数字和英文来说,有ASCII作为背景,就比较简单。

其中数字的

点阵起始位置offset=incode[0]*16L(获取的ASCII码*16L就直接转换了)

 /******************************************************
函数名称: getasi
函数功能: 获取asci码
传入参数:
返 回 值:
建立时间: 2018-05-08
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
void ShowName::getasi(char incode[]){
unsigned char qh, wh;
unsigned long offset;
offset = incode[]*16L;
fseek(ASI816, offset, SEEK_SET);
fread(num_mat, , , ASI816);
}

但是对于24*24点阵字库的话,以上的原理就不适用了

对于区码位码的话有所改变:

区码 = 机内码高位字节 - AFH 
位码 = 机内码低位字节 - AOH

对于寻找字库起始位置:

offset=offset = (94 * (qh - 1) + (wh - 1)) * 72L(72是怎么来的?24*24/8)

 /******************************************************
函数名称: get_mat
函数功能: 通过汉字的区码和位码进行写到mat中
传入参数: qh, wh
返 回 值:
建立时间: 2018-05-07
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
void ShowName::get_mat(unsigned char qh, unsigned char wh){
long offset;
offset = ( * (qh - ) + (wh - )) * 72L;
// 读取数据存入数组
fseek(HZK24, offset, SEEK_SET);
fread(mat, , , HZK24);
}

第三部分:将相应的编码映射到图片的相应位置实现文字“写在图片上”(提取编码的转换映射)

将数字进行映射

 /******************************************************
函数名称: draw_code
函数功能: 绘制学号
传入参数:
返 回 值:
建立时间: 2018-05-08
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
void ShowName::draw_code(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 = MAPSIZE; //+INTERSIZE;
//int numsize = 8;
start_x = width - sum_word * size;//开始位置一定要找好,确认开始位置
start_y = height - - INTERSIZE;
// 开始绘制 CvScalar cs;
for (int i = ; i < ; ++i)
for (int k = ; k < ; k++)
if ((num_mat[i]&(0x80>>k)) != NULL)
{
current_start_x = k + start_x + size * num;
current_start_y = start_y + i;
cs = cvGet2D(img, current_start_y, current_start_x);//获取图像相对位置的RGB的值
cs.val[] = ;//变黑
cs.val[] = ;//这里可以改成你喜欢的颜色
cs.val[] = ;
cvSet2D(img, current_start_y, current_start_x, cs);//重新设值
} }

对汉字进行映射:这里需要在映射的时候翻个身子

 /******************************************************
函数名称: draw_name
函数功能: 通过汉字的区码和位码进行写到mat中
传入参数: qh, wh
返 回 值:
建立时间: 2018-05-07
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
void ShowName::draw_name(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 = MAPSIZE;// +INTERSIZE;
start_x = width - sum_word * size;
start_y = height - MAPSIZE - INTERSIZE;
// 开始绘制 CvScalar cs; for (int i = ; i < ; ++i)
for (int j = ; j < ; ++j)
for (int k = ; k < ; k++)
if (((mat[i* + j] >> ( - k)) & 0x1) != NULL)
{
// 绘点
current_start_x = start_x + i + size * num;//24*24的是纵向排列的i对应的是x
current_start_y = start_y + j * + k;
cs = cvGet2D(img, current_start_y, current_start_x);
cs.val[] = ;
cs.val[] = ;
cs.val[] = ;
cvSet2D(img, current_start_y, current_start_x, cs);
}
}

最后进行重新显示绘制好的图片

 /******************************************************
函数名称: Runtodraw
函数功能: 启动绘制
传入参数:
返 回 值:
建立时间: 2018-05-07
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/ void ShowName::Runtodraw(){
unsigned char mask = 0x80;
char tmpcode[] = { };
while (*Name!=NULL)//汉字转换过程
{
tmpcode[] = *Name;
tmpcode[] = *(Name + );
if (tmpcode[] & mask){
unsigned char qh, wh;
qh = tmpcode[] - 0xaf; //求区码
wh = tmpcode[] - 0xa0;//求位码
get_mat(qh,wh);
draw_name(current_num++);//画字
Name += ;
}
}
while (*code!=NULL)
{
tmpcode[] = *code;
if (tmpcode[])
{
getasi(code);
draw_code(current_num++);
code++;
}
}
cvShowImage("bt", img);
cvWaitKey();
}

结果:

ps:本文这里采用的是c++的面向对象的方式进行写的。

如需要源码请转移至码云:https://gitee.com/cjqbaba/MediaTest/tree/textimage进行源码克隆下载

如有问题请留言评论。转载请注明出处,谢谢。

使用opencv调用24*24点阵字库和8*16ASCII字库在图片显示文字数字的更多相关文章

  1. Android 调用系统的分享[完美实现同一时候分享图片和文字]

    android 系统的分享功能 private void share(String content, Uri uri){ Intent shareIntent = new Intent(Intent. ...

  2. Opencv调用深度学习模型

    https://blog.csdn.net/lovelyaiq/article/details/79929393 https://blog.csdn.net/qq_29462849/article/d ...

  3. 【opencv】Java实现opencv 调用本地摄像头,实现人脸识别、人形识别、人眼识别

    本博客为老魏原创,如需转载请留言咨询. 效果预览:(没办法,为了效果只能上像了,丑别介意.哈哈..) 上代码: 1 package com.lw.test; 2 3 import java.awt.G ...

  4. 树莓派:使用OpenCV调用自带的摄像头.

    总所周知,树莓派上,调用摄像头的指令有raspistill和raspivid.若要使用opencv对摄像头进行调用,不少人会出现 cvCaptureFromCAM(0)函数无法找到Pi Cam的错误情 ...

  5. openCV 调用摄像头

    OpenCV调用摄像头 环境 python:python3.6 摄像头:网络摄像头 Python库:openCV # -*- coding: utf-8 -*- # @author leone # @ ...

  6. 调试opencv调用摄像头程序时碰到的问题

    昨天晚上想把opencv学习笔记整理一下,当跑opencv调用摄像头的程序的时候老是出现Assertion failed (size.width>0 && size.height ...

  7. 利用face_recognition,dlib与OpenCV调用摄像头进行人脸识别

    用已经搭建好 face_recognition,dlib 环境来进行人脸识别 未搭建好环境请参考:https://www.cnblogs.com/guihua-pingting/p/12201077. ...

  8. OpenCV【2】---读取png图片显示到QT label上的问题

    问题一:   操作图片test.png是一个365x365的PNG图片   通过OpenCV自带的GUI显示出来图像是没问题的,例如以下操作代码所看到的: QStringfileName=QFileD ...

  9. OpenCV入门:(七:OpenCV取随机数以及显示文字)

    1.随机颜色 OpenCV中自带了取随机数的方法,使用步骤: RNG rng( 0xFFFFFFFF ); 随机数 = rng.uniform( 下限,上限 ); 2.显示文字 , , bool bo ...

随机推荐

  1. 精通mysql之精通EXPLAIN

    EXPLAIN列的解释: table:显示这一行的数据是关于哪张表的 type:这是重要的列,显示连接使用了何种类型.从最好到最差的连接类型为const.eq_reg.ref.range.indexh ...

  2. Chipmunk僵尸物理对象的出现和解决(四)

    接上一篇,我们看看五角星和反弹棒碰撞时的代码: -(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair star:(CCNode * ...

  3. 【leetcode79】Single Number III

    题目描述: 给定一个数组,里面只有两个数组,只是出现一次,其余的数字都是出现两次,找出这个两个数字,数组形式输出 原文描述: Given an array of numbers nums, in wh ...

  4. 如何让你的web具备权限认证

    大多数Web系统都有权限需求,前面已经了解了它的整个认证过程的原理,这节将讲述如何在Tomcat中配置web资源的权限.先以Tomcat默认的认证模式Basic和默认的域UserDatabaseRea ...

  5. 敦泰FT6X06单层自容调屏

    总的概括来说,自电容调屏在配置好通道个数和顺序后,只需调整AFE相关的设置参数使各通道的Raw Data和CI值符合定义的标准即可.– AFE是模拟前端的缩写-Analog Front End• Ra ...

  6. Asp.Net中使用JQueryEasyUI--善良公社项目

    jQuery UI 是以 jQuery 为基础的开源 JavaScript 网页用户界面代码库.包含底层用户交互.动画.特效和可更换主题的可视控件.我们可以直接用它来构建具有很好交互性的web应用程序 ...

  7. 【Android 应用开发】Android屏幕适配解析 - 详解像素,设备独立像素,归一化密度,精确密度及各种资源对应的尺寸密度分辨率适配问题

    . 作者 :万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/19698511 . 最近遇到了一系列的屏幕适配问题, 以及 ...

  8. Spring揭秘 读书笔记 三 bean的scope与FactoryBean

    本书可作为王富强所著<<Spring揭秘>>一书的读书笔记  第四章 BeanFactory的xml之旅 bean的scope scope有时被翻译为"作用域&quo ...

  9. 原生CSS动画回调事件

    原文链接: Detecting CSS Animation Completion with JavaScript 原文日期: 2014年02月20日 翻译日期: 2014年02月21日 翻译人员: 铁 ...

  10. 苹果新的编程语言 Swift 语言进阶(八)--属性

    属性是特定类.结构或枚举的相关值,属性根据作用域不同分为实例属性与类型属性,还可以根据是否存储分为存储属性和计算属性. 1.1 实例属性 为一个类.结构或枚举定义的属性默认属于实例属性,即该属性属于为 ...