CASIA数据集转png HWDB2.0-2.2
https://nlpr.ia.ac.cn/databases/handwriting/Home.html
CASIA在线和离线中文手写数据库
https://nlpr.ia.ac.cn/databases/handwriting/Offline_database.html
CASIA-HWDB2.0-2.2
离线文本数据库是由孤立字符数据集的作者制作的。每人撰写了五页给定文本。由于数据丢失,缺少一位作者(编号 371)和四页内容。每一页都存储在以作者索引和页码命名的 *.dgrl 文件中。除灰度图像外,数据文件还包括文本行分割的基本事实和字符类别标签(GB 码)。(训练集和测试集的作者是互斥的)
Dataset | #writers | #pages | #lines | #character/#class | #out-of-class sample |
---|---|---|---|---|---|
HWDB2.0 | 419 | 2,092 | 20,495 | 538,868/1,222 | 1,106 |
HWDB2.1 | 300 | 1,500 | 17,292 | 429,553/2,310 | 172 |
HWDB2.2 | 300 | 1,499 | 14,443 | 380,993/1,331 | 581 |
Total | 1,019 | 5,091 | 52,230 | 1,349,414/2,703 | 1,859 |
截图(使用https://nlpr.ia.ac.cn/databases/Download/DGRLView.exe查看)
使用准备
把原训练集和测试集的数据合并到一个文件夹里,再根据作者重新分配训练集和测试集,确保训练集中存在每一个作者的笔迹.还要把dgrl 转成 png.
使用dgrl 查看002-P18.dgrl 是正常的(不会出现上下行重叠)
使用代码导出 png 时,发生了重叠(每行的坐标和长宽使用的是文件里面解析的结果)
软件应该是进行了渲染的处理,比如正片叠底
这里使用简单的方法处理,记录每行添加进大图后的最下边的 y 值,这样虽然上下距离变远了但不影响使用.
007-P19
这里的白边切不掉
修改后的代码(参考https://blog.csdn.net/DaGongJiGuoMaLu09/article/details/107050519)
import os
import struct
from pathlib import Pathimport cv2 as cv
import numpy as np
from tqdm import tqdm#切割白边
def remove_white(image):# 将图像反相inverted_image = cv.bitwise_not(image)# 计算上下左右投影horizontal_projection = np.sum(inverted_image, axis=1)vertical_projection = np.sum(inverted_image, axis=0)# 找到非零元素的索引范围non_zero_horizontal = np.where(horizontal_projection > 0)non_zero_vertical = np.where(vertical_projection > 0)# 获取边界top = non_zero_horizontal[0][0]bottom = non_zero_horizontal[0][-1]left = non_zero_vertical[0][0]right = non_zero_vertical[0][-1]# 切割图像并返回cropped_image = image[top:bottom, left:right]return cropped_imagedef read_from_dgrl(dgrl):if not os.path.exists(dgrl):print("DGRL not exists!")return# if(os.path.basename(dgrl)!="385-P20.dgrl"):# returngray_output_dir = "Y:/RawData/CASIA-HWDB2-png/gray/test"binary_output_dir = "Y:/RawData/CASIA-HWDB2-png/binary/test"with open(dgrl, "rb") as f:# 读取表头尺寸header_size = np.fromfile(f, dtype="uint8", count=4)header_size = sum([j << (i * 8) for i, j in enumerate(header_size)])# print(header_size)# 读取表头剩下内容,提取 code_lengthheader = np.fromfile(f, dtype="uint8", count=header_size - 4)code_length = sum([j << (i * 8) for i, j in enumerate(header[-4:-2])])# print(code_length)# 读取图像尺寸信息,提取图像中行数量image_record = np.fromfile(f, dtype="uint8", count=12)height = sum([j << (i * 8) for i, j in enumerate(image_record[:4])])width = sum([j << (i * 8) for i, j in enumerate(image_record[4:8])])line_num = sum([j << (i * 8) for i, j in enumerate(image_record[8:])])# print("图像尺寸:")# print(height, width, line_num)# 创建一个空白图像来存储所有行的图像big_image = np.zeros((height+3000, 9000), dtype=np.uint8)big_image.fill(255)now_x=0now_y=0# 读取每一行的信息for k in range(line_num):# print(k + 1)# 读取该行的字符数量char_num = np.fromfile(f, dtype="uint8", count=4)char_num = sum([j << (i * 8) for i, j in enumerate(char_num)])# print("字符数量:", char_num)# 读取该行的标注信息label = np.fromfile(f, dtype="uint8", count=code_length * char_num)label = [label[i] << (8 * (i % code_length))for i in range(code_length * char_num)]label = [sum(label[i * code_length : (i + 1) * code_length])for i in range(char_num)]label = [struct.pack("I", i).decode("gbk", "ignore")[0] for i in label]# print("合并前:", label)label = "".join(label)# 去掉不可见字符 \x00,这一步不加的话后面保存的内容会出现看不见的问题label = "".join(label.split(b"\x00".decode()))# print("合并后:", label)# 读取该行的位置和尺寸pos_size = np.fromfile(f, dtype="uint8", count=16)y = sum([j << (i * 8) for i, j in enumerate(pos_size[:4])])x = sum([j << (i * 8) for i, j in enumerate(pos_size[4:8])])h = sum([j << (i * 8) for i, j in enumerate(pos_size[8:12])])w = sum([j << (i * 8) for i, j in enumerate(pos_size[12:])])# print(x, y, w, h)# 读取该行的图片bitmap = np.fromfile(f, dtype="uint8", count=h * w)bitmap = np.array(bitmap).reshape(h, w)base_name = os.path.basename(dgrl)filename, _ = os.path.splitext(base_name)# 保存图片(每行的图片)bitmap=remove_white(bitmap)# image_file = os.path.join(gray_output_dir, filename + "_"+str(k)+".png")# cv.imwrite(image_file, bitmap)h, w = bitmap.shape[0], bitmap.shape[1]# if np.all(bitmap == 0) or np.all(bitmap == 255):# pass# 将该行图像放入大图中的相应位置if(k==0):big_image[y : y + h, x : x + w] = bitmap[:h, :w]now_y=y+helse:# print(x+w)# print(big_image.shape[:2])# print(big_image[now_y : now_y + h, x : x + w].shape[:2])if(x<0):x=abs(x)big_image[now_y : now_y + h, x : x + w] = bitmap[:h, :w]now_y=now_y + hcropped_image=remove_white(big_image)cropped_image_file = os.path.join(gray_output_dir, filename + ".png")cv.imwrite(cropped_image_file, cropped_image)# 使用大津法进行二值化处理_, binaryx_image =cv.threshold(cropped_image, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)# 将二值图像保存到文件中cv.imwrite(os.path.join(binary_output_dir, filename + ".png"), binaryx_image)if __name__ == "__main__":dgrl_paths = Path("Y:/RawData/CASIA-HWDB2/test").iterdir()dgrl_paths = list(dgrl_paths)la=Falsefor dgrl_path in tqdm(dgrl_paths):print(dgrl_path)# if(os.path.basename(dgrl_path)=="385-P20.dgrl"):# la=True# if(la):# read_from_dgrl(dgrl_path)read_from_dgrl(dgrl_path)
提取结果(保存灰度图和二值图)
相关文章:

CASIA数据集转png HWDB2.0-2.2
https://nlpr.ia.ac.cn/databases/handwriting/Home.html CASIA在线和离线中文手写数据库 https://nlpr.ia.ac.cn/databases/handwriting/Offline_database.html CASIA-HWDB2.0-2.2 离线文本数据库是由孤立字符数据集的作者制作的。每人撰写了五页给定文本。由于数据丢失&a…...

学习或复习电路的game推荐:nandgame(NAND与非门游戏)、Turing_Complete(图灵完备)
https://www.nandgame.com/ 免费 https://store.steampowered.com/app/1444480/Turing_Complete/ 收费,70元。据说可以导出 Verilog !...
前端面试题《react》
说说React render方法的原理?在什么时候会被触发? render函数里面可以编写JSX,转化成createElement这种形式,用于生成虚拟DOM,最终转化成真实DOM 在 React 中,类组件只要执行了 setState 方法,…...
快速入门Kotlin③类与对象
类 构造函数 主构造函数:主构造函数是类头的一部分,它跟在类名后面。主构造函数没有函数体,它可以包含初始化代码和属性声明。初始化块:init关键字修饰,它直接写在类体中。它的执行顺序与它们在类体中的出现顺序一致。 次构造函数:次要构造函数是可选的,用于提供额外…...
RUST:Arc (Atomic Reference Counted) 原子引用计数
在Rust编程语言中,Arc 是一个智能指针类型,全称为 "Atomic Reference Counted"(原子引用计数)。它的主要作用是提供线程安全的共享所有权机制,使得多个线程可以同时持有同一个数据结构的访问权,并…...

从0写一个问卷调查APP的第13天-1
1.今日任务 我也只是一个大学生,有什么思路不对的地方给我指出来哟! 分析:上次我们实现了任务调查的插入。但是我们插入的问卷调查只有它的标题,也就是这个问卷调查是什么我们告诉数据库了,但是现在我们还没有给它添加任何问题&…...
20.Python从入门到精通—参数 位置参数 关键字参数 默认参数 匿名函数 return 语句 强制位置参数
20.从入门到精通:参数 位置参数 关键字参数 默认参数 匿名函数 return 语句 强制位置参数 参数位置参数关键字参数默认参数 匿名函数return 语句强制位置参数 参数 在Python中,函数可以接受任意数量的参数,包括位置参数、关键字参数和默认参数。以下是这…...
Python爬虫之requests库
1、准备工作 pip install requests 2、实例 urllib库中的urlopen方法实际上就是以GET方式请求网页,requests库中相应的方法就是get方法。 import requestsr requests.get(https://www.baidu.com/) print(type(r)) # <class requests.models.Response> 响…...
鱼塘钓鱼(多路归并)
有 N 个鱼塘排成一排,每个鱼塘中有一定数量的鱼,例如:N5 时,如下表: 鱼塘编号12345第1分钟能钓到的鱼的数量 (1…1000)101420169每钓鱼1分钟钓鱼数的减少量(1…100)24653当前鱼塘到…...

java每日一题——买啤酒(递归经典问题)
前言: 非常喜欢的一道题,经典中的经典。打好基础,daydayup!!!啤酒问题:一瓶啤酒2元,4个盖子可以换一瓶,2个空瓶可以换一瓶,请问10元可以喝几瓶 题目如下: 啤酒问题:一瓶…...
最近接到一个大项目,给公司设计抢商品代金劵业务
我们公司是做汽车金融方面的工作,在业内还挺大。目前单量来源于2,3线城市,随着大环境越老越差位了吸引他们, 公司决定给全国的客户,销售等发一些商品 1.总体学习了京东开源秒杀系统设计思路和方案。 我们公司决定进行…...
防火墙(讲解)
目录 1.防火墙是什么? 2.防火墙设备 3.防火墙功能 1)出色的控制能力,过滤掉不安全服务 2)过滤非法用户和访问特殊站点 3)它能够对网络存取和访问进行监控审计 4.防火墙的局限 (1)防火墙有可能是可以绕过的 (2)防火墙不能防止内部出卖性攻击或者内部误操作…...
Python之装饰器-带参装饰器
Python之装饰器-带参装饰器 带参装饰器 之后不是一个单独的标识符,是一个函数调用函数调用的返回值又是一个函数,此函数是一个无参装饰器带参装饰器,可以有任意个参数 func()func(1)func(1, 2) def add(x, y):"""函数说明&…...

抖音IP属地怎么更改
抖音是一个非常受欢迎的短视频平台,吸引了无数用户在上面分享自己的生活和才艺。然而,随着快手的火爆,一些用户开始担心自己的IP地址会被他人获取,引起个人隐私风险。那么,抖音用户又该如何更改到别的地方呢࿱…...

Flutter 全局控制底部导航栏和自定义导航栏的方法
1. 介绍 导航栏在移动应用中扮演着至关重要的角色,它是用户与应用之间进行导航和交互的核心组件之一。无论是简单的页面切换,还是复杂的应用导航,导航栏都能够帮助用户快速找到所需内容,提升用户体验和应用的易用性。 在移动应用…...

检索增强生成(RAG)技术:实现流程、作用及应用案例
一. RAG简介 在自然语言处理(NLP)领域中,检索增强生成(Retrieval-Augmented Generation, RAG)技术巧妙地结合了信息检索与神经网络生成模型的力量,通过在生成过程中引入相关的外部信息,实现了在…...

Ubuntu安装和使用
Ubuntu 安装和配置 修改下载源 打开软件与更新, 选择其它站点, 选择中国, 选择阿里云源 谷歌中文输入法配置 Ctrl Alt T打开终端, 执行下述命令下fcitx框架 输入密码进行安装 sudo apt-get install -y fcitx-googlepinyinWin呼出菜单, 选择语言支持, 第一次打开会显示语言…...
【Unity】Stream最好用的Selfhost开源轻量服务
【背景】 有好几种场景的投屏或者远控应用希望实现,无论用哪种方式,都绕不开如何构建服务这一关。 【分析】 外网有很多直接付费使用的信令传输类型或是提供流服务的服务器,但我的目标场景是断绝外网的局域网,而且付费也总觉得…...
Web 常见的攻击方式有哪些?
常见的 Web 攻击方式有以下几种: 跨站脚本攻击(XSS 攻击) 跨站请求伪造(XSRF 攻击) SQL 注入 XSS 攻击 MDN 定义如下: 跨站脚本攻击(Cross-site scripting,XSS)是一…...
Rancher(v2.6.3)——Rancher部署Redis(单机版)
Rancher部署Redis详细说明文档]:https://gitee.com/WilliamWangmy/snail-knowledge/blob/master/Rancher/Rancher%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#6rancher%E9%83%A8%E7%BD%B2redis ps:如果觉得作者写的还行,能够满足您的需求&#…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...