PaddleOCR服务部署-并通过Java进行调用

news2024/9/29 13:40:35

上一篇讲了PaddleOCR的简单使用,但是最终的目的肯定是要将它进行服务部署方便我们调用的,这里介绍一下他的服务部署方式

选择部署方式

官方推荐有以下几种:
Python 推理
C++ 推理
Serving 服务化部署(Python/C++)
Paddle-Lite 端侧部署(ARM CPU/OpenCL ARM GPU)
Paddle.js 部署

各个方式优缺点如下
在这里插入图片描述

由于我本身是做Java开发,不会Python,所以采用Serving 服务化部署
PaddleOCR提供2种服务部署方式:

基于PaddleHub Serving的部署;
基于PaddleServing的部署

我选择的是通过PaddleHub Serving进行部署

安装Hub Serving

准备环境

pip install paddlehub -i https://mirror.baidu.com/pypi/simple

安装好之后查看一下
在这里插入图片描述

下载推理模型

PaddleOCR下新建‘inference’文件夹,准备推理模型并放到‘inference’文件夹里面,默认使用的是v1.1版的超轻量模型
在这里插入图片描述

https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_ch/quickstart.md

默认模型路径为:
检测模型:./inference/ch_ppocr_mobile_v1.1_det_infer/
识别模型:./inference/ch_ppocr_mobile_v1.1_rec_infer/
方向分类器:./inference/ch_ppocr_mobile_v1.1_cls_infer/
模型路径可在params.py中查看和修改。 更多模型可以从PaddleOCR提供的模型库下载,也可以替换成自己训练转换好的模型。

安装服务模块

#在Linux环境下,安装示例如下:
# 安装检测服务模块:  
hub install deploy/hubserving/ocr_det/

# 或,安装识别服务模块:  
hub install deploy/hubserving/ocr_rec/

# 或,安装检测+识别串联服务模块:  
hub install deploy/hubserving/ocr_system/
#在Windows环境下(文件夹的分隔符为\),安装示例如下:
# 安装检测服务模块:  
hub install deploy\hubserving\ocr_det\

# 或,安装识别服务模块:  
hub install deploy\hubserving\ocr_rec\

# 或,安装检测+识别串联服务模块:
hub install deploy\hubserving\ocr_system\

这里最好把这几个模块都安装上,不然启动的时候会报错

启动服务

启动方式分两种,一种是全局启动,一种是指定到路径启动

#全局启动
hub serving start -m ocr_system

我这里采用的是指定路径启动,需要切换到hubserving目录下通过命令

hub serving start -c deploy\hubserving\ocr_system\config.json

启动的其他参数参照官方文档说明

**注意:**如果启动报错xxx路径找不到,去PaddleOCR\deploy\hubserving下的ocr_system、ocr_det、ocr_rec的params.py文件,将所有的model_dir
替换为符合win格式的绝对路径即可;

这样就完成了一个服务化API的部署,使用默认端口号8868。
访问示例:
python tools/test_hubserving.py --server_url=http://127.0.0.1:8868/predict/ocr_system --image_dir=img/22.jpg
输出结果:
在这里插入图片描述

Java调取

我们可以通过Java代码进行服务的调取,代码如下:

/**
 * @author: fueen
 * @createTime: 2022/11/28 10:01
 */
@RestController
@RequestMapping("/paddleocr")
public class PaddleOCRController {

    @PostMapping("/upload")
    public String fileUpload(@RequestParam("file") MultipartFile file, HttpServletRequest req, Model model){
        try {
            //接收上传文件
            //Receiving uploaded files
            String fileName = System.currentTimeMillis()+file.getOriginalFilename();
            String destFileName=req.getServletContext().getRealPath("")+"uploaded"+ File.separator+fileName;
            File destFile = new File(destFileName);
            destFile.getParentFile().mkdirs();
            System.out.println(destFile);
            file.transferTo(destFile);
            //向前端模板引擎传入上传文件的地址
            //The address of the uploaded file is passed in to the front-end template engine
            model.addAttribute("fileName","uploaded\\"+fileName);
            model.addAttribute("path",destFile);
            //开始准备请求API
            //Start preparing the request API
            //创建请求头
            //Create request header
            HttpHeaders headers = new HttpHeaders();
            //设置请求头格式
            //Set the request header format
            headers.setContentType(MediaType.APPLICATION_JSON);
            //构建请求参数
            //Build request parameters
            MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
            //读入静态资源文件
            //Read the static resource file
            InputStream imagePath = new FileInputStream(destFile);
            //添加请求参数images,并将Base64编码的图片传入
            //Add the request parameter Images and pass in the Base64 encoded image
            map.add("images", ImageToBase64(imagePath));
            //构建请求
            //Build request
            HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
            RestTemplate restTemplate = new RestTemplate();
            //发送请求
            //Send the request
            Map json = restTemplate.postForEntity("http://127.0.0.1:8868/predict/ocr_system", request, Map.class).getBody();
            System.out.println(json);
            //解析Json返回值
            //Parse the Json return value
            List<List<Map>> json1 = (List<List<Map>>) json.get("results");
            //获取文件目录为后面画图做准备
            //Get the file directory to prepare for later drawing
            String tarImgPath = destFile.toString();
            File srcImgFile = new File(tarImgPath);
            System.out.println(srcImgFile);
            //文件流转化为图片
            //The file flows into images
            Image srcImg = ImageIO.read(srcImgFile);
            if (null == srcImg){
                return "什么也没有,结束!";
            }
            //获取图片的宽
            //Gets the width of the image
            int srcImgWidth = srcImg.getWidth(null);
            //获取图片的高
            //Get the height of the image
            int srcImgHeight = srcImg.getHeight(null);
            //开始绘图主流程,创建画板设置画笔颜色等
            //Start drawing main flow, create artboard, set brush color, etc
            BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bufImg.createGraphics();
            g.setColor(Color.red);
            g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
            //循环遍历出所有内容
            //Loop through everything
            for (int i = 0; i < json1.get(0).size(); i++) {
                System.out.println("当前的文字是:" + json1.get(0).get(i).get("text"));
                System.out.println("可能的概率为:" + json1.get(0).get(i).get("confidence"));
                List<List<Integer>> json2 = (List<List<Integer>>) json1.get(0).get(i).get("text_region");
                System.out.println("文字的坐标" + json2);
                int x = json2.get(0).get(0);
                int y = json2.get(0).get(1);
                int w = json2.get(1).get(0)-json2.get(0).get(0);
                int h = json2.get(2).get(1)-json2.get(0).get(1);
                g.drawRect(x,y,w,h);  //画出水印   Draw the watermark
            }
            //将内容提交到前端模板引擎
            //Submit the content to the front-end template engine
            model.addAttribute("z",json1.get(0));
            g.dispose();
            // 输出图片
            //The output image
            FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
            ImageIO.write(bufImg, "png", outImgStream);
            System.out.println("画图完毕");
            outImgStream.flush();
            outImgStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return "上传失败," + e.getMessage();
        } catch (IOException e) {
            e.printStackTrace();
            return "上传失败," + e.getMessage();
        }
        return "OK";
    }
    private String ImageToBase64(InputStream imgPath) {
        byte[] data = null;
        // 读取图片字节数组
        //Read the image byte array
        try {
            InputStream in = imgPath;
            System.out.println(imgPath);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        //Base64 encoding of byte array
        BASE64Encoder encoder = new BASE64Encoder();
        // 返回Base64编码过的字节数组字符串
        //Returns a Base64 encoded byte array string
        //System.out.println("图片转换Base64:" + encoder.encode(Objects.requireNonNull(data)));
        return encoder.encode(Objects.requireNonNull(data));
    }

}

然后运行,通过postman调取接口进行测试
在这里插入图片描述

控制台输出结果
在这里插入图片描述
完成!后面可以根据自己的业务需求来进行不同的处理修改

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

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

相关文章

电影寒冬之下,票房靠“主旋律”能撑住场吗?《扫黑行动》仍在重播

春节将近&#xff0c;各大院线陆陆续续公布了春节档将要上映的影片档期&#xff0c;小伙伴们是不是也对近期热门的影片有了兴趣&#xff0c;想要一饱眼福了呢。下面是小编根据网络公布的数据进行报表数据处理分析后得到的数据可视化图&#xff0c;展示了近期一些热门影片的情况…

数据库专辑--WITH CHECK OPTION的用法

系列文章 C#底层库–数据库访问帮助类&#xff08;MySQL版&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/126886379 文章目录系列文章前言一、概念介绍二、测试用例2.1 数据准备2.2 数据查询2.3 修改视图&#xff0c;加上WITH CHECK O…

IDEA 优质 插件 Translation 跟随 IDEA 2022.3 版 更新翻译引擎啦

IDEA 优质 插件 Translation 跟随 IDEA 2022.3 版 更新翻译引擎啦 文章目录IDEA 优质 插件 Translation 跟随 IDEA 2022.3 版 更新翻译引擎啦特征安装使用 IDE 内置插件系统安装&#xff1a;手动安装&#xff1a;使用1. 注册翻译服务&#xff08;可选&#xff09;2. 开始翻译3.…

BGP学习笔记

概念 动态路由协议按照按照工作范围可以分为IGP和EGP&#xff0c;IGP工作在一个AS之内&#xff0c;主要用来发现和计算路由&#xff0c;常见的IGP包括OSPF&#xff0c;RIP&#xff0c;ISIS等。EGP工作在AS与AS之间&#xff0c;在AS之间提供无环路的路由信息交换。BGP&#xff…

[附源码]Python计算机毕业设计Django基于Web的软考题库平台

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

ActiveMQ window安装、修改密码、启动一闪而过、设置8161端口仅本地访问

目录 1.ActiveMQ下载 2.ActiveMQ目录说明 3.启动activemq 4.修改activemq默认密码 5.设置8161端口仅本地访问。 1.ActiveMQ下载 官网下载ActiveMQhttps://activemq.apache.org/ window版本直接解压就可以。 2.ActiveMQ目录说明 apache-activemq-5.16.5 activemq目录结构…

这几款文档笔记工具,你习惯用哪个?

前言 俗话说的好&#xff1a;“好记性不如烂笔头”&#xff0c;平时工作记录笔记的确是一个良好的习惯&#xff0c;做文档笔记可以在我们遗忘时进行回看&#xff0c;方便查找&#xff0c;代替人的大脑。有时程序写多了&#xff0c;很不愿意去强制记忆一些东西&#xff0c;那么…

【高度预估】基于matlab卡尔曼滤波和粒子滤波无人机离地高度估计【含Matlab源码 2255期】

⛄一、卡尔曼滤波和粒子滤波无人机离地高度估计 1 无人机离地高度估计算法 1.1 离地高度估计基本方案 无人机安装两路距离测量传感器, 传感器能在小型无人机飞行的一般高度正常工作, 且两个传感器的安装位置保证它们能够测量相同的离地高度信息。 两路距离测量传感器以1s的频…

单源最短路径(贪心算法)

最近在研究算法设计与分析&#xff0c;看到了单源最短路劲&#xff0c;特发文一篇。 下面代码就是实现这个有向联通图 废话不说直接上代码 #include<stdio.h> #define m 5000 int c[5][5] {m,10,m,30,100,m,m,50,m,m,m,m,m,m,10,m,m,20,m,60,m,m,m,m,m, }; int dist[5]…

现在市面跑步耳机哪款好用、分享五款适合跑步用的耳机推荐

近这两年来&#xff0c;运动健身风潮一直都非常火&#xff0c;但是一个人运动健身&#xff0c;难免无聊&#xff0c;如果有音乐的陪伴&#xff0c;时间都能过得快很多&#xff0c;这时候就需要一款运动蓝牙耳机了。不过购买运动蓝牙耳机&#xff0c;比挑选普通的耳机还更需要花…

[附源码]Python计算机毕业设计Django架构的博客平台设计

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

节约软件开发成本,关键在这儿。

​1、节省软件开发成本的核心在减少返工&#xff01; 软件企业利润 销售额 - 成本。企业的利润少&#xff0c;可能是销售额太少&#xff0c;也可能是成本太高。而增加销售额&#xff0c;取决于销售人员、客户、市场、产品等众多不可控因素&#xff0c;可遇而不可求。相反&…

RabbitMQ-死信交换机

文章目录1 死信交换机1.1.什么是死信交换机1.2 利用死信交换机接收死信1.3 总结2 TTL2.1 接收超时死信的死信交换机2.2 声明一个队列&#xff0c;并且指定TTL2.3 发送消息时&#xff0c;设定TTL2.4.总结3 延迟队列3.1 DelayExchange原理3.2 使用DelayExchange3.3 总结1 死信交换…

智云通CRM:如何判断客户忠诚度的高低?

客户忠诚度是一个相对概念&#xff0c;说明了客户在购买同类产品或服务时对某一企业或品牌光顾比重的高低。注意&#xff0c;不能跨产品或服务进行客户忠诚度比较&#xff0c;因为这样比较是没有意义的。客户忠诚度可以通过以下指标来衡量。 一、 客户重复购买的次数 客户重复…

【LeetCode每日一题:1769. 移动所有球到每个盒子所需的最小操作数~~~双重循环遍历模拟】

题目描述 有 n 个盒子。给你一个长度为 n 的二进制字符串 boxes &#xff0c;其中 boxes[i] 的值为 ‘0’ 表示第 i 个盒子是 空 的&#xff0c;而 boxes[i] 的值为 ‘1’ 表示盒子里有 一个 小球。 在一步操作中&#xff0c;你可以将 一个 小球从某个盒子移动到一个与之相邻…

区块链共识机制 (Consensus)(PoW,PoS,PAXOS,RAFT,PBFT)

文章目录ConsensusProof of Work&#xff08;PoW)Proof of Stake&#xff08;PoS&#xff09;PAXOSPhases in PAXOSPrepare PhaseAccept PhaseReplicated And Fault Tolerant&#xff08;RAFT&#xff09;Leader ElectionLog ReplicationPractical Byzantine Fault Tolerance (…

Ubuntu18.04开机自动启动终端并运行脚本

目录 1.创建测试脚本文件 2.添加到开机自启动 1.创建测试脚本文件 CtrlAltT打开终端在终端中输入以下指令&#xff0c;创建.sh文件。 touch “文件名”.sh 双击打开test.sh文件&#xff0c;输入以下测试代码&#xff0c;并保存 #!/bin/bash source /opt/ros/melodic/setu…

用于Python降维的线性判别分析

减少预测模型的输入变量数称为降维。 较少的输入变量可以产生更简单的预测模型&#xff0c;该模型在对新数据进行预测时可能具有更好的性能。 线性判别分析&#xff08;简称LDA&#xff09;是一种用于多类分类的预测建模算法。它还可以用作降维技术&#xff0c;提供训练数据集…

Unity 3D 导航系统||Unity 3D 障碍物

Unity 3D 导航系统 过去&#xff0c;游戏开发者必须自己打造寻路系统&#xff0c;特别是在基于节点的寻路系统中&#xff0c;必须手动地在 AI 使用的点之间进行导航&#xff0c;因此基于节点系统的寻路非常烦琐。 Unity 3D 不仅具有导航功能&#xff0c;还使用了导航网格&…

牛客练习赛106 药丸

牛客练习赛106 药丸 2022.12.02 与舍友四排玩了团体对抗的模式&#xff0c;练习赛就只有40分钟的剩余时间了。 题目描述 来源&#xff1a;牛客网 牛牛有 nnn 个属性&#xff0c;第 iii 个属性的初始值为 aia_iai​ &#xff0c;牛牛想把第 iii 个属性的值变为目标值 bib_ib…