2024 MathorCupB 题 甲骨文智能识别中原始拓片单字自动分割与识别研究

news2025/2/5 8:46:58

一、问题重述

甲骨文是我国目前已知的最早成熟的文字系统,它是一种刻在龟甲或兽骨上的古老文字。甲骨文具有极其重要的研究价值,不仅对中国文明的起源具有重要意义,也对世界文明的研究有着深远影响。在我国政府的大力推动下,甲骨文研究已经进入一个全新的发展阶段。人工智能和大数据技术被应用于甲骨文全息性研究及数字化工程建设,成为甲骨文信息处理领域的研究热点。

甲骨文拓片图像分割是甲骨文数字化工程的基础问题,其目的是利用数字图像处理和计算机视觉技术,在甲骨文原始拓片图像的复杂背景中提取出特征分明且互不交叠的独立文字区域。它是甲骨文字修复、字形复原与建模、文字识别、拓片缀合等处理的技术基础[2]。然而,甲骨拓片图像分割往往受到点状噪声、人工纹理和固有纹理三类干扰元素的严重影响[3]。且甲骨文图像来源广泛,包括拓片、拍照、扫描、临摹等,不同的图像来源,其干扰元素的影响是不同的。由于缺乏对甲骨文字及其干扰元素的形态先验特征的特殊考量,通用的代表性图像分割方法目前尚不能对甲骨文原始拓片图像中的文字目标和点状噪声、人工纹理、固有纹理进行有效判别,其误分割率较高,在处理甲骨拓片图像时均有一定局限性。如何从干扰众多的复杂背景中准确地分割出独立文字区域,仍然是一个亟待解决的具有挑战性的问题。

图1为一张甲骨文原始拓片的图像分割示例,左图为一整张甲骨文原始拓片,右图即为利用图像分割算法[4]实现的拓片图像上甲骨文的单字分割。甲骨文的同一个字会有很多异体字,这无疑增加了 甲骨文识别的难度,图2展示了甲骨文中“人”字的不同异体字。

问题一

问题1:对于附件1(Pre test 文件夹)给定的三张甲骨文原始拓片图片进行图像预处理,提取图像特征,建立甲骨文图像预处理模型,实现对甲骨文图像千扰元素的初步判别和处理。

解决思路

针对问题一,我们对附件一的甲骨文图像数据进行数据预处理

包括但不限于:

尺寸调整:将图像调整为模型要求的输入尺寸,通常是正方形或者某个固定的长宽比。

归一化:将图像的像素值缩放到固定范围内,例如0,1或−1,1,以便于模型的训练。

数据增强:通过随机旋转、裁剪、翻转、变换亮度和对比度等方式来增加训练数据的多样性,从而提高模型的泛化能力。

图像增强:对图像进行增强操作,如调整亮度、对比度、锐度、颜色等,以增强图像的特征。

解题代码(python)

import cv2
import numpy as np
import torch
import matplotlib.image as mpimg
import matplotlib.pyplot as plt

# 读取图像
image_path1 = r'cup_data\1_Pre_test\h02060.jpg'
image_path2 = r'cup_data\1_Pre_test\w01637.jpg'
image_path3 = r'cup_data\1_Pre_test\w01870.jpg'
image1 = cv2.imread(image_path1)
image2 = cv2.imread(image_path2)
image3 = cv2.imread(image_path3)

# 定义目标尺寸
target_size = (416, 416)  # YOLOv5 推荐的尺寸

# 调整大小
resized_image1 = cv2.resize(image1, target_size)
resized_image2 = cv2.resize(image2, target_size)
resized_image3 = cv2.resize(image3, target_size)

# 将图像归一化为 [0, 1]
normalized_image = []
normalized_image.append(resized_image1.astype(np.float32) / 255.0)
normalized_image.append(resized_image2.astype(np.float32) / 255.0)
normalized_image.append(resized_image3.astype(np.float32) / 255.0)
# 如果需要旋转,可以在这里进行旋转操作

# 将图像转换为 PyTorch 的 Tensor 格式,并添加批次维度
tensor_image = torch.tensor(normalized_image[0]).permute(2, 0, 1).unsqueeze(0)

# 现在 tensor_image 就是你所需的输入数据,准备用于 YOLOv5 模型
plt.imshow(image1)
plt.axis('off')
plt.show()

问题二

 解题思路

针对问题二,基于yolov5模型,利用附件2中的数据对模型进行微调,使其具备单字检测分割的能力。我们将部分分割结果可视化,验证模型分割能力。

解题代码

# yolov5 训练代码
def main(opt, callbacks=Callbacks()):
    """Runs training or hyperparameter evolution with specified options and optional callbacks."""
    if RANK in {-1, 0}:
        print_args(vars(opt))
        check_git_status()
        check_requirements(ROOT / "requirements.txt")

    # Resume (from specified or most recent last.pt)
    if opt.resume and not check_comet_resume(opt) and not opt.evolve:
        last = Path(check_file(opt.resume) if isinstance(opt.resume, str) else get_latest_run())
        opt_yaml = last.parent.parent / "opt.yaml"  # train options yaml
        opt_data = opt.data  # original dataset
        if opt_yaml.is_file():
            with open(opt_yaml, errors="ignore") as f:
                d = yaml.safe_load(f)
        else:
            d = torch.load(last, map_location="cpu")["opt"]
        opt = argparse.Namespace(**d)  # replace
        opt.cfg, opt.weights, opt.resume = "", str(last), True  # reinstate
        if is_url(opt_data):
            opt.data = check_file(opt_data)  # avoid HUB resume auth timeout
    else:
        opt.data, opt.cfg, opt.hyp, opt.weights, opt.project = (
            check_file(opt.data),
            check_yaml(opt.cfg),
            check_yaml(opt.hyp),
            str(opt.weights),
            str(opt.project),
        )  # checks
        assert len(opt.cfg) or len(opt.weights), "either --cfg or --weights must be specified"
        if opt.evolve:
            if opt.project == str(ROOT / "runs/train"):  # if default project name, rename to runs/evolve
                opt.project = str(ROOT / "runs/evolve")
            opt.exist_ok, opt.resume = opt.resume, False  # pass resume to exist_ok and disable resume
        if opt.name == "cfg":
            opt.name = Path(opt.cfg).stem  # use model.yaml as name
        opt.save_dir = str(increment_path(Path(opt.project) / opt.name, exist_ok=opt.exist_ok))
# 训练结果可视化,我们微调的模型在训练集上识别准确率如下图所示:(我们提供了三张训练集上的识别准确率图像)
import matplotlib.pyplot as plt
import cv2

# 读取图像
image_path1 = "jupyter_need/test_datasets0.jpg"
image_path2 = "jupyter_need/test_datasets1.jpg"
image_path3 = "jupyter_need/test_datasets2.jpg"

image1 = cv2.imread(image_path1)
image2 = cv2.imread(image_path2)
image3 = cv2.imread(image_path3)

# 创建一个具有三个子图的图形
plt.figure(figsize=(15, 5))

# 在第一个子图中显示第一张图片
plt.subplot(1, 3, 1)
plt.imshow(cv2.cvtColor(image1, cv2.COLOR_BGR2RGB))
plt.axis('off')

# 在第二个子图中显示第二张图片
plt.subplot(1, 3, 2)
plt.imshow(cv2.cvtColor(image2, cv2.COLOR_BGR2RGB))
plt.axis('off')

# 在第三个子图中显示第三张图片
plt.subplot(1, 3, 3)
plt.imshow(cv2.cvtColor(image3, cv2.COLOR_BGR2RGB))
plt.axis('off')

# 展示图片
plt.show()

模型评估

# 为了评估我们模型的性能,我们计算了在训练集上50个epoch的F1_CURVE、P_CURVE、R_CURVE和PR_CURVE
# F1 曲线是用于评估二元分类器性能的一种图形化指标。它显示了在不同阈值下的 F1 分数随着真阳性率(召回率)的变化情况。
# F1 分数是精确度(Precision)和召回率(Recall)的调和平均值,它可以帮助我们在精确度和召回率之间找到一个平衡点。
# "P curve" 通常指代 "Precision-Recall curve",即精确度-召回率曲线。它是用于评估分类模型性能的一种常见工具,特别是在处理不平衡数据集时。
# Precision-Recall 曲线显示了在不同阈值下的精确度和召回率之间的关系。精确度(Precision)是被正确分类的正例占所有被分类为正例的样本的比例,
# 召回率(Recall)是被正确分类的正例占所有实际正例的样本的比例。
# 绘制 P-R 曲线的过程类似于绘制 ROC 曲线,只是在 P-R 曲线中,横轴通常是召回率,纵轴是精确度。在绘制过程中,
# 可以通过在模型输出的概率或得分上变化阈值,计算不同阈值下的精确度和召回率,并绘制曲线。
# P-R 曲线对于不平衡数据集的分类器评估尤为重要,因为它可以更清晰地显示出分类器在不同类别之间的性能差异。
# 通常情况下,当类别不平衡时,使用 P-R 曲线比 ROC 曲线更能展现出分类器的优势和缺陷。

# 以下是这些指标的具体结果图:
import matplotlib.pyplot as plt
import cv2

# 读取图像
image_path1 = "jupyter_need/F1_curve.png"
image_path2 = "jupyter_need/P_curve.png"
image_path3 = "jupyter_need/PR_curve.png"

image1 = cv2.imread(image_path1)
image2 = cv2.imread(image_path2)
image3 = cv2.imread(image_path3)

# 创建一个具有三个子图的图形
plt.figure(figsize=(15, 5))

# 在第一个子图中显示第一张图片
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image1, cv2.COLOR_BGR2RGB))
plt.axis('off')

# 在第二个子图中显示第二张图片
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(image2, cv2.COLOR_BGR2RGB))
plt.axis('off')

# 展示图片
plt.show()

问题三

解题思路

针对问题三,利用第二问得到的检测分割模型,在附件三测试集上对测试数据进行检测分割,并保存结果到附件Test_results.xlsx

解题代码

# 利用第二问(前面)微调好的yolo,我们在对附件三中的200张甲骨文原始图像进行自动单字分割,分割结果保存在Test_results.xlsx文件中
#自动分割代码如下:
def main(opt):
    """Executes YOLOv5 tasks including training, validation, testing, speed, and study with configurable options."""
    check_requirements(ROOT / "requirements.txt", exclude=("tensorboard", "thop"))

    if opt.task in ("train", "val", "test"):  # run normally
        if opt.conf_thres > 0.001:  # https://github.com/ultralytics/yolov5/issues/1466
            LOGGER.warning(f"WARNING ⚠️ confidence threshold {opt.conf_thres} > 0.001 produces invalid results")
        if opt.save_hybrid:
            LOGGER.warning("WARNING ⚠️ --save-hybrid returns high mAP from hybrid labels, not from predictions alone")
        run(**vars(opt))

    else:
        weights = opt.weights if isinstance(opt.weights, list) else [opt.weights]
        opt.half = torch.cuda.is_available() and opt.device != "cpu"  # FP16 for fastest results
        if opt.task == "speed":  # speed benchmarks
            # python val.py --task speed --data coco.yaml --batch 1 --weights yolov5n.pt yolov5s.pt...
            opt.conf_thres, opt.iou_thres, opt.save_json = 0.25, 0.45, False
            for opt.weights in weights:
                run(**vars(opt), plots=False)

问题四

解题思路

针对问题四,附件四给出部分甲骨文图像及其对应的简体中文,我们建立inception_v3分类模型,通过训练数据对模型进行微调。将得到的在甲骨文文字识别任务上微调后的inception_v3模型对测试集数据进行文字识别。将识别结果保存,写入论文。

解题代码

# inception model 训练代码:
import json
import os

import torch
import torch.nn as nn
import torchvision.models as models
from torchvision import transforms
from torch.utils.data import DataLoader, Dataset
from PIL import Image
from sklearn.metrics import f1_score
from torch.optim.lr_scheduler import StepLR
from tqdm import tqdm

# 检查CUDA是否可用,并设置设备
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')


# 构建自定义数据集
class CustomDataset(Dataset):
    def __init__(self, file_paths, labels, transform=None):
        self.file_paths = file_paths
        self.labels = labels
        self.transform = transform

    def __len__(self):
        return len(self.file_paths)

    def __getitem__(self, idx):
        image = Image.open(self.file_paths[idx]).convert('RGB')
        label = torch.tensor(self.labels[idx], dtype=torch.float32)

        if self.transform:
            image = self.transform(image)

        return image, label


# 超参数
batch_size = 32
num_epochs = 50
learning_rate = 0.001
num_classes = 76  # 假设有10个类别

# 转换图像
transform = transforms.Compose([
    transforms.Resize((299, 299)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

train_file_dir = "q4_data/train/image"
train_file_paths = os.listdir(train_file_dir)
# 给每个文件路径添加文件夹路径
train_file_paths = [os.path.join(train_file_dir, file_name) for file_name in train_file_paths]
# 从JSON文件中读取数据
with open("q4_train_inception.json", "r") as json_file:
    train_labels = json.load(json_file)
# 数据加载
train_dataset = CustomDataset(train_file_paths, train_labels, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)

# 加载预训练的InceptionV3模型
model = models.inception_v3(pretrained=True)
model.aux_logits = False  # 禁用辅助输出
# # 冻结模型参数
# for param in model.parameters():
#     param.requires_grad = False

# 修改最后一层全连接层以适应多标签分类任务
num_ftrs = model.fc.in_features
model.fc = nn.Sequential(
    nn.Linear(num_ftrs, 512),
    nn.ReLU(inplace=True),
    nn.Linear(512, num_classes),
    nn.Sigmoid()  # 多标签分类使用Sigmoid激活函数
)

model = model.to(device)
# 定义损失函数和优化器
criterion = nn.BCELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

# 学习率调度器
scheduler = StepLR(optimizer, step_size=5, gamma=0.5)

# 训练模型
total_step = len(train_loader)
for epoch in tqdm(range(num_epochs)):
    model.train()
    for i, (images, labels) in enumerate(tqdm(train_loader)):
        images = images.to(device)
        labels = labels.to(device)
        # 前向传播
        outputs = model(images)
        # 计算损失
        loss = criterion(outputs, labels)
        # 反向传播和优化
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if (i + 1) % 1000 == 0:
            print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'
                  .format(epoch + 1, num_epochs, i + 1, total_step, loss.item()))

    # 调整学习率
    scheduler.step()

    # 评估循环
    model.eval()
    with torch.no_grad():
        # 初始化预测和标签列表
        all_preds = []
        all_labels = []
        correct_predictions = 0
        total_predictions = 0
        for images, labels in tqdm(train_loader):
            images = images.to(device)
            labels = labels.to(device)
            # 前向传播
            outputs = model(images)
            predicted = outputs > 0.5
            # 计算准确率
            correct_predictions += (predicted == labels.byte()).all(1).sum().item()
            total_predictions += labels.size(0)
            # 收集预测和真实标签
            all_preds.extend(predicted.cpu().numpy())
            all_labels.extend(labels.cpu().numpy())
        accuracy = correct_predictions / total_predictions
        f1 = f1_score(all_labels, all_preds, average='micro')
        print('Epoch [{}/{}], Accuracy: {:.4f}, F1 Score: {:.4f}'.format(epoch + 1, num_epochs, accuracy, f1))

    # 保存模型
    torch.save(model.state_dict(), f'ckpt/inceptionv3_ft_{epoch}_f1_{f1:.4f}_acc_{accuracy:.4f}.pth')

利用我们预处理后的数据,在inception模型上训练11个epoch后,在训练集上,模型准确率达到99.4%,F1值达到99.6%
接下来,我们利用训练好的inception模型对附件四甲骨文原始图像进行文字自动识别

资料获取

提供2024MathorCupBC题的思路分析与代码,欢迎进群讨论:953799264

B题目思路代码获取:http://app.niucodata.com/mianbaoduo/recommend.php?id=59179

B题目成品论文获取:http://app.niucodata.com/mianbaoduo/recommend.php?id=59182

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1598987.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

格雷希尔G80L-T系列大口径快速连接器,在汽车膨胀水箱的气密性测试密封方案

副水箱也有人称作膨胀水箱,是汽车散热系统的一个重要组成部分,当水箱里面的温度过高的时候就会产生一定的压力,而副水箱可以根据热胀冷缩来帮助水箱和发动机排出去多余的水,起到一个调节的作用,副水箱由PP/PE塑料注塑而…

49.字母异位词分组(哈希字典)

《代码随想录》学习笔记,原链接:代码随想录 class Solution:def groupAnagrams(self, strs: List[str]) -> List[List[str]]:hash_table {} # 构建哈希字典result []for i in range(len(strs)): # 遍历字符串列表key "".join(s…

【攻防世界】ics-07

<?php session_start();if (!isset($_GET[page])) {show_source(__FILE__);die(); }if (isset($_GET[page]) && $_GET[page] ! index.php) {include(flag.php); }else {header(Location: ?pageflag.php); } <?phpif ($_SESSION[admin]) {$con $_POST[con];$…

Vue3——html-doc-js(html导出为word的js库)

一、下载 官方地址 html-doc-js - npm npm install html-doc-js 二、使用方法 // 使用页面中引入 import exportWord from html-doc-js// 配置项以及实现下载方法 const wrap document.getElementById(test)const config {document:document, //默认当前文档的document…

数字孪生技术在新能源行业的应用

数字孪生技术在新能源行业的应用主要体现在以下几个方面&#xff0c;数字孪生技术在新能源领域的应用有助于提高能源系统的效率和可靠性&#xff0c;推动可持续发展&#xff0c;并为新能源行业的转型升级提供坚实的技术支持。随着技术的进一步发展&#xff0c;数字孪生在新能源…

力扣 | 54. 螺旋矩阵

注意按照顺时针方向进行访问元素&#xff0c;以及每次触发的条件只会满足一个&#xff01; public List<Integer> spiralOrder(int [][] matrix){List<Integer> result new ArrayList<>();int m matrix.length;int n matrix[0].length;int row0,col 0;//…

Pytorch-张量形状操作

&#x1f606;&#x1f606;&#x1f606;感谢大家的观看&#x1f606;&#x1f606; &#x1f339; reshape 函数 transpose 和 permute 函数 view 和 contigous 函数 squeeze 和 unsqueeze 函数 在搭建网络模型时&#xff0c;掌握对张量形状的操作是非常重要的&#xff…

免费https证书申请指南——四步轻松完成

使用https协议对网站进行加密是保护网站安全的必要工作之一&#xff0c;一般情况下获取https证书&#xff0c;则需要支付费用给证书颁发机构&#xff08;CA&#xff09;。现在有一些可靠的服务提供免费的https证书&#xff0c;免费https证书遵循严格的行业标准进行颁发&#xf…

15 php学习:表单验证

表单验证 表单验证在网页和应用程序开发中起着至关重要的作用&#xff0c;其主要目的是确保用户输入的数据符合预期的格式和规则&#xff0c;以提升用户体验、数据准确性和系统安全性。以下是表单验证的主要作用&#xff1a; 数据准确性&#xff1a;通过表单验证&#xff0c;可…

C/C++ C/C++ 入门(6)模板初阶

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;C 多多指教&#xff01; 一、泛型编程 在之前&#xff0c;我们进行编程的时候&#xff0c;总是针对于某一个具体的问题。就比如说&#xff0c;如何实现一个int类型的swap函数呢&#xff1f;大家肯定会写。…

NLP基础—jieba分词

jieba分词 支持四种分词模式 精确模式 试图将句子最精确地切开,适合文本分析;全模式 把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义;搜索引擎模式 在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。paddle模式 利用Paddle…

渗透测试工作任务概述

一、渗透测试工作任务介绍 渗透测试工作任务不是随便用个工具就可以完成的&#xff0c;需要了解网站业务情况&#xff0c;还需要在测试结束后给出安全加固的解决方案&#xff1b; 渗透测试与入侵工具区别&#xff1a; 渗透测试&#xff1a;出于保护系统的目的&#xff0c;更全…

zehpyr环境搭建和demo的编译

qemu可执行固件编译的探索 环境demo的模拟SDK构建zephyr环境设置安装依赖项下载 Aspeed Zephyr 软件包 安装工具链配置 环境 ubuntu22.04、 qemu9.0.0-rc1、cmake 3.25.2、python 3.8.10、dtc 1.5.0、west 1.2.0、zephyr-sdk-0.16.1 demo的模拟 首先先尝试一个可以正常跑起来…

即插即用模块详解SCConv:用于特征冗余的空间和通道重构卷积

目录 一、摘要 二、创新点说明 2.1 Methodology 2.2SRU for Spatial Redundancy​编辑 2.3CRU for Channel Redundancy 三、实验 3.1基于CIFAR的图像分类 3.2基于ImageNet的图像分类 3.3对象检测 四、代码详解 五、总结 论文&#xff1a;https://openaccess.thecvf.c…

基于 Operator 部署 Prometheus 监控 k8s 集群

目录 一、环境准备 1.1 选择版本 1.2 过滤镜像 1.3 修改 yaml 镜像 1.4 移动 *networkPolicy*.yaml 1.5 修改 service 文件 1.6 提前下载镜像并推送到私有镜像仓库 1.7 修改镜像&#xff08;可选&#xff09; 二、执行创建 三、查看 pod 状态 四、访问 prometheus、…

【Spring】依赖注入(DI)时常用的注解@Autowired和@Value

目录 1、Autowired 自动装配 1.1、要实现自动装配不是一定要使用Autowired 1.2、Autowired的特性 &#xff08;1&#xff09;首先会根据类型去spring容器中找(bytype),如果有多个类型&#xff0c;会根据名字再去spring容器中找(byname) &#xff08;2&#xff09;如果根据名…

冯喜运:4.16中东对抗风暴下,黄金原油市场何去何从?

黄金行情走势分析&#xff1a;4小时图布林道开始收口&#xff0c;昨日下探至下轨附近&#xff0c;也是此前的起涨低点2320启稳上升&#xff0c;十字K线配合单阳拉起&#xff0c;重新去摸高上轨。目前4小时图处于摸高当中。周线和日线留意多空转换&#xff0c;摸高之后是强势延续…

使用Scrapy选择器提取豆瓣电影信息,并用正则表达式从介绍详情中获取指定信息

本文同步更新于博主个人博客&#xff1a;blog.buzzchat.top 一、Scrapy框架 1. 介绍 在当今数字化的时代&#xff0c;数据是一种宝贵的资源&#xff0c;而网络爬虫&#xff08;Web Scraping&#xff09;则是获取网络数据的重要工具之一。而在 Python 生态系统中&#xff0c;S…

03-echarts如何画立体柱状图

echarts如何画立体柱状图 一、创建盒子1、创建盒子2、初始化盒子&#xff08;先绘制一个基本的二维柱状图的样式&#xff09;1、创建一个初始化图表的方法2、在mounted中调用这个方法3、在方法中写options和绘制图形 二、画图前知识1、坐标2、柱状图图解分析 三、构建方法1、创…

第七周学习笔记DAY.1-封装

学完本次课程后&#xff0c;你能够&#xff1a; 理解封装的作用 会使用封装 会使用Java中的包组织类 掌握访问修饰符&#xff0c;理解访问权限 没有封装的话属性访问随意&#xff0c;赋值也可能不合理&#xff0c;为了解决这些代码设计缺陷&#xff0c;可以使用封装。 面向…