在Ubuntu下调用opencv库编程显示一张图片并显示字符数据

2023-12-13 01:08

本文主要是介绍在Ubuntu下调用opencv库编程显示一张图片并显示字符数据,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 汉字点阵字库原理
    • 汉字编码
      • 1、区位码
      • 2、机内码
    • 点阵字库结构
    • 汉字点阵获取
      • 1、利用区位码获取汉字
      • 2、利用汉字机内码获取汉字
  • Ubuntu 下调用 opencv 在图片显示字符数据
    • 1、创建文件夹
    • 2、放入文件
    • 3、编写代码
    • 4、运行结果
  • 参考资料

汉字点阵字库原理

汉字编码

1、区位码

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

2、机内码

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

由于汉字的区码与位码的取值范围的十六进制数均为 01H-5EH(即十进制的 01-94),所以汉字的高位字节与低位字节的取值范围则为 A1H~FEH(即十进制的 161-254)。
例如,汉字“啊”的区位码为 1601,区码和位码分别用十六进制表示即为 1001H,它的机内码的高位字节为 B0H,低位字节为 A1H,机内码就是 B0A1H。

点阵字库结构

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

汉字点阵获取

1、利用区位码获取汉字

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

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

前面我们己经讲过,汉字的区位码和机内码的关系如下:
机内码高位字节 = 区码 + 20H + 80H(或区码 + A0H)
机内码低位字节 = 位码 + 20H + 80H(或位码 + AOH)

反过来说,我们也可以根据机内码来获得区位码:
区码 = 机内码高位字节 - A0H
位码 = 机内码低位字节 - AOH

将这个公式与获取汉字点阵的公式进行合并计就可以得到汉字的点阵位置。

Ubuntu 下调用 opencv 在图片显示字符数据

1、创建文件夹

在虚拟机中调取终端,输入指令:mkdir word 创建一个名为word的文件夹;
输入指令:cd word,进入该文件夹;
在这里插入图片描述

2、放入文件

将需要的项目文件放入该文件夹中,其中包括24 点阵汉字库(宽度 x 高度 = 24x24)、16 点阵 ASCII 字库(宽度 x 高度 = 8x16)以及需要显示的字符数据的文本文件和需要显示的图片。
在这里插入图片描述

3、编写代码

输入指令:gedit test.cpp,创建一个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;
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="IMG_20211104_134252.jpg";//图片的名字char* logo_path="logo.txt";//汉字文件的名字put_text_to_image(700,700,image_path,logo_path);//change txt placereturn 0;
}void paint_ascii(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 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++)                  //十六个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;}
}
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个字节,用来存放汉字的if((HZK=fopen("HZKf2424.hz","rb"))==NULL){printf("Can't open HZKf2424.hz,Please check the path!");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 put_text_to_image(int x_offset,int y_offset,String image_path,char* logo_path){//将汉字弄上图片
//x和y就是第一个字在图片上的起始坐标//通过图片路径获取图片Mat image=imread(image_path);int length=19;//要打印的字符长度(打印多少字节长度就为多少,根据自己的情况调整)unsigned char qh,wh;//定义区号,位号unsigned long offset;//偏移量unsigned char hexcode[30];//用于存放记事本读取的十六进制,记得要用无符号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:在图片上绘制文字的起始坐标for(int m=0;m<length;){if(hexcode[m]==0x23){break;//读到#号时结束}else if(hexcode[m]>0xaf){qh=hexcode[m]-0xaf;//使用的字库里是以汉字啊开头,而不是以汉字符号开头wh=hexcode[m+1] - 0xa0;//计算位码offset=(94*(qh-1)+(wh-1))*72L;paint_chinese(image,x,y,offset);/*计算在汉字库中的偏移量对于每个汉字,使用24*24的点阵来表示的一行有三个字节,一共24行,所以需要72个字节来表示*/m=m+2;//一个汉字的机内码占两个字节,x+=24;//一个汉字为24*24个像素点,由于是水平放置,所以是向右移动24个像素点}else{//当读取的字符为ASCII码时wh=hexcode[m];offset=wh*16l;//计算英文字符的偏移量paint_ascii(image,x,y,offset);m++;//英文字符在文件里表示只占一个字节,所以往后移一位就行了x+=16;}}cv::imshow("image", image);cv::waitKey();
}

注:图片名称需要根据自己的图片名称进行更改。文字所显示的坐标也可以自己更改。

在这里插入图片描述

4、运行结果

输入指令:g++ test.cpp -o test `pkg-config --cflags --libs opencv``;编译刚刚写好的代码:
在这里插入图片描述
再输入指令:./test,就可以看到运行后的图像和文字了。
在这里插入图片描述

参考资料

汉字点阵字库资料

这篇关于在Ubuntu下调用opencv库编程显示一张图片并显示字符数据的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/486617

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca