OCR文字识别—基于PP-OCR模型实现ONNX C++推理部署

概述

PaddleOCR 是一款基于 PaddlePaddle 深度学习平台的开源 OCR 工具。PP-OCR是PaddleOCR自研的实用的超轻量OCR系统。它是一个两阶段的OCR系统,其中文本检测算法选用DB,文本识别算法选用CRNN,并在检测和识别模块之间添加文本方向分类器,以应对不同方向的文本识别。

PP-OCRv4 在速度可比的情况下,中文场景端到端 hmean 指标相比于 PP-OCRv3 提升 4.25%。英文数字场景,相比于 PP-OCRv3 英文模型提升 6%。在有评估集的四种语系识别准确率平均提升 5% 以上。对已支持的 80 余种语言识别模型进行了升级更新,优化了多语言场景下的识别效果,平均准确率提升超 8%。
在这里插入图片描述
官方代码:https://github.com/PaddlePaddle/PaddleOCR

模型下载

模型地址:https://paddlepaddle.github.io/PaddleOCR/latest/ppocr/model_list.html
PP-OCRv4提供了版面分析、表格识别、文本检测模型、文本方向分类器、文本识别等模型。在这里,笔者只下载检测、方向、识别三种轻量版本的推理模型。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
下载完成后,解压文件。
在这里插入图片描述
在这里插入图片描述
inference.pdparams:模型的参数文件,存储了模型的权重和偏置等信息,用于推理时加载模型的权重。
inference.pdmodel:模型的结构文件,存储了神经网络的架构信息(例如层的定义和计算方式),推理时通过此文件定义模型结构。

模型转换

首先将下载的 paddle 模型转换为 onnx模型。可以从这个地址https://github.com/paddlepaddle/paddle2onnx下载源码进行编译转换。
或者直接安装环境去转换:

conda create -n paddle2onnx python=3.8
activate paddle2onnx
pip install PaddlePaddle==2.6.0
pip install onnxruntime>=1.10.0
pip install paddle2onnx
paddle2onnx --model_dir ch_PP-OCRv4_det_infer --model_filename inference.pdmodel
--params_filename inference.pdiparams --save_file ch_PP-OCRv4_det_infer.onnx

在这里插入图片描述

模型部署

#include<iostream>
#include <io.h>
#include <fcntl.h>
#include<opencv2/opencv.hpp>
#include<onnxruntime_cxx_api.h>
#include"text_det.h"
#include"text_angle_cls.h"
#include"text_rec.h"
#include "utils.h"

int main()
{
	std::string img_path = "images/1.jpg";
	cv::Mat src_img = cv::imread(img_path);
	cv::rotate(src_img, src_img, 1);

	const std::string det_model = "model/ch_PP-OCRv4_det_infer.onnx";
	const std::string cls_model = "model/ch_ppocr_mobile_v2.0_cls_infer.onnx";
	const std::string rec_model = "model/ch_PP-OCRv4_rec_infer.onnx";
	bool isGPU = true;

	TextDetector text_det(det_model, isGPU);
	TextClassifier text_cls(cls_model, isGPU);
	TextRecognizer text_rec(rec_model, isGPU);

	std::vector<std::vector<cv::Point2f>> results = text_det.detect(src_img);
	std::sort(results.begin(), results.end(), utils::compareBoxes);

	cv::Mat det_img = src_img.clone();
	for (const auto& polygon : results) {
		std::vector<cv::Point> intPolygon;
		for (const auto& point : polygon) {
			intPolygon.emplace_back(cv::Point(static_cast<int>(point.x), static_cast<int>(point.y)));
		}
		cv::polylines(det_img, intPolygon, true, cv::Scalar(0, 0, 255), 1);
	}

	//text_det.draw_pred(src_img, results);
	cv::imshow("Detected Text Boxes", det_img);
	cv::waitKey(0);

	for (size_t i = 0; i < results.size(); i++) 
	{
		cv::Mat textimg = text_det.get_rotate_crop_image(src_img, results[i]);
		cv::imshow("single_text_box", textimg);
		cv::waitKey(0);
		
		if (text_cls.predict(textimg) == 1) {
			cv::rotate(textimg, textimg, 1); 
		}
		cv::imshow("single_text_rotate", textimg);
		cv::waitKey(0);

		int textWidth = textimg.cols;
		std::string full_text = "";
		if (textWidth < 250) 
		{
			
			std::string text = text_rec.predict_text(textimg);
			full_text = text;
		}
		else 
		{
			int segmentWidth = 250; 
			int numSegments = std::ceil((float)textWidth / segmentWidth); 
			for (int seg = 0; seg < numSegments; ++seg) {
				int startX = seg * segmentWidth;
				int endX = std::min(startX + segmentWidth, textWidth); 
				cv::Rect roi(startX, 0, endX - startX, textimg.rows);
				cv::Mat segment = textimg(roi);
				std::string segment_text = text_rec.predict_text(segment);
				full_text += segment_text;
			}
		}
		_setmode(_fileno(stdout), _O_U8TEXT);
		std::wstring w_text = utils::charToWstring(full_text.c_str());
		std::wcout << w_text << std::endl;
	}
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

webpack03

什么是source-map 将代码编译压缩之后&#xff0c;&#xff0c;可以通过source-map映射会原来的代码&#xff0c;&#xff0c;&#xff0c;在调试的时候可以准确找到原代码报错位置&#xff0c;&#xff0c;&#xff0c;进行修改 source-map有很多值&#xff1a; eval &#…

H266/VVC 帧内预测中 ISP 技术

帧内子划分 ISP ISP 技术是在 JVET-2002-v3 提案中详细介绍其原理&#xff0c;在 VTM8 中完整展示算法。ISP是线基内预测&#xff08;LIP&#xff09;模式的更新版本&#xff0c;它改善了原始方法在编码增益和复杂度之间的权衡&#xff0c;ISP 算法的核心原理就是利用较近的像…

day05_Spark SQL

文章目录 day05_Spark SQL课程笔记一、今日课程内容二、Spark SQL 基本介绍&#xff08;了解&#xff09;1、什么是Spark SQL**为什么 Spark SQL 是“SQL与大数据之间的桥梁”&#xff1f;****实际意义**为什么要学习Spark SQL呢?**为什么 Spark SQL 像“瑞士军刀”&#xff1…

Win11+WLS Ubuntu 鸿蒙开发环境搭建(二)

参考文章 penHarmony南向开发笔记&#xff08;一&#xff09;开发环境搭建 OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——标准系统移植指南&#xff08;一&#xff09; OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——小型系统芯片移植指南&#xff08;二&…

【杂谈】-50+个生成式人工智能面试问题(四)

7、生成式AI面试问题与微调相关 Q23. LLMs中的微调是什么&#xff1f; 答案&#xff1a;虽然预训练语言模型非常强大&#xff0c;但它们并不是任何特定任务的专家。它们可能对语言有惊人的理解能力&#xff0c;但仍需要一些LLMs微调过程&#xff0c;开发者通过这个过程提升它…

【深度学习】数据预处理

为了能用深度学习来解决现实世界的问题&#xff0c;我们经常从预处理原始数据开始&#xff0c; 而不是从那些准备好的张量格式数据开始。 在Python中常用的数据分析工具中&#xff0c;我们通常使用pandas软件包。 像庞大的Python生态系统中的许多其他扩展包一样&#xff0c;pan…

赛灵思(Xilinx)公司Artix-7系列FPGA

苦难从不值得歌颂&#xff0c;在苦难中萃取的坚韧才值得珍视&#xff1b; 痛苦同样不必美化&#xff0c;从痛苦中开掘出希望才是壮举。 没有人是绝对意义的主角&#xff0c; 但每个人又都是自己生活剧本里的英雄。滑雪&#xff0c;是姿态优雅的“贴地飞行”&#xff0c;也有着成…

城市生命线安全综合监管平台

【落地产品&#xff0c;有需要可留言联系&#xff0c;支持项目合作或源码合作】 一、建设背景 以关于城市安全的重要论述为建设纲要&#xff0c;聚焦城市安全重点领域&#xff0c;围绕燃气爆炸、城市内涝、地下管线交互风险、第三方施工破坏、供水爆管、桥梁坍塌、道路塌陷七…

请求方式(基于注解实现)

1.编写web.xml文件配置启动信息 <!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app><display-name>Archetype Created Web Application</di…

WMS仓库管理系统,Vue前端开发,Java后端技术源码(源码学习)

一、项目背景和建设目标 随着企业业务的不断扩展&#xff0c;仓库管理成为影响生产效率、成本控制及客户满意度的重要环节。为了提升仓库作业的透明度、准确性和效率&#xff0c;本方案旨在构建一套全面、高效、易用的仓库管理系统&#xff08;WMS&#xff09;。该系统将涵盖库…

Pathview包:整合表达谱数据可视化KEGG通路

Pathview是一个用于整合表达谱数据并用于可视化KEGG通路的一个R包&#xff0c;其会先下载KEGG官网上的通路图&#xff0c;然后整合输入数据对通路图进行再次渲染&#xff0c;从而对KEGG通路图进行一定程度上的个性化处理&#xff0c;并且丰富其信息展示。&#xff08;KEGG在线数…

数据结构:DisjointSet

Disjoint Sets意思是一系列没有重复元素的集合。一种常见的实现叫做&#xff0c;Disjoint-set Forest可以以接近常数的时间复杂度查询元素所属集合&#xff0c;用来确定两个元素是否同属一个集合等&#xff0c;是效率最高的常见数据结构之一。 Wiki链接&#xff1a;https://en…

更好的世界:用定制托管对象上下文(NSManagedObjectContext)防止产生“空白”托管对象(下)

概述 用 SwiftUI CoreData 这对“双剑合璧”的强力开发组合&#xff0c;我们可以事倍功半、非常 easy 的开发出界面元素丰富且背后拥有持久数据库支持的 App。 不过&#xff0c;在某些情况下它们被误用或错用也可能带来一些“藏形匿影”的顽疾。 在本篇博文中&#xff0c;您…

个人在技术领导力方面的自我反思与提升

大家好&#xff01;我是 [数擎 AI]&#xff0c;一位热爱探索新技术的前端开发者&#xff0c;在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情&#xff0c;欢迎关注我的文章&#xff0c;我们一起成长、进步&#xff01; 开发领域&#xff1a;前端开发 | A…

Win10本地部署大语言模型ChatGLM2-6B

鸣谢《ChatGLM2-6B&#xff5c;开源本地化语言模型》作者PhiltreX 作者显卡为英伟达4060 安装程序 打开CMD命令行&#xff0c;在D盘新建目录openai.wiki if not exist D:\openai.wiki mkdir D:\openai.wiki 强制切换工作路径为D盘的openai.wiki文件夹。 cd /d D:\openai.wik…

排列高手

这篇主要是求再排位为 {1&#xff0c;3&#xff0c;4&#xff0c;....&#xff0c;n&#xff0c;2}的最优顺序下求mex。 但不知道为什么这样是最优 子数列的个数公式&#xff1a; 对于一个长度为N的数组&#xff0c; #include <bits/stdc.h> using namespace std; lon…

公众号如何通过openid获取unionid

通过接口 https://api.weixin.qq.com/cgi-bin/user/info?access_tokenxxxxxxx&langzh_CN 返回的数据如下&#xff1a; 前提是必须绑定 微信开放平台 token如何获取呢 代码如下&#xff1a; String tokenUrl "https://api.weixin.qq.com/cgi-bin/token"; …

软件测试预备知识④—NTFS权限管理、磁盘配额与文件共享

在软件测试的实际环境搭建与管理过程中&#xff0c;了解和掌握NTFS权限管理、磁盘配额以及文件共享等知识至关重要。这些功能不仅影响系统的安全性和稳定性&#xff0c;还对测试数据的存储、访问以及多用户协作测试有着深远的影响。 一、NTFS权限管理 1.1 NTFS简介 NTFS&am…

类结构——构造方法

类结构——构造方法 构造方法的基本特性默认构造方法构造方法重载使用this关键字私有构造方法总结 构造方法&#xff08;Constructor&#xff09;是Java编程语言中的一个重要概念&#xff0c;用于初始化新创建的对象。在对象实例化时被调用&#xff0c;并负责设置对象的初始状态…

【linux系统之redis6】redis的安装与初始化

下载redis的linux对应的安装包&#xff0c;并上传到linux虚拟机里面 解压压缩包 tar -zxzf redis-6.2.6.tar.gz解压后&#xff0c;进入redis文件 cd redis-6.2.6执行编译 make && make install看到下图&#xff0c;就说明redis安装成功了 默认的安装路径&#xff0c…