所有文章 > 日积月累 > Java 调用 Paddlehub API 进行服务部署
Java 调用 Paddlehub API 进行服务部署

Java 调用 Paddlehub API 进行服务部署

PaddleOCR 在文本识别领域中的应用越来越广泛,而将其部署为服务可以极大地方便我们在实际项目中的调用。本文将详细介绍如何通过 PaddleHub Serving 部署 PaddleOCR 服务,并通过 Java 实现接口调用。

选择部署方式

PaddleOCR 提供了多种部署方式,官方推荐的有以下几种:

  • Python 推理
  • C++ 推理
  • Serving 服务化部署(Python/C++)
  • Paddle-Lite 端侧部署(ARM CPU/OpenCL ARM GPU)
  • Paddle.js 部署

部署方式对比

由于我本身是 Java 开发者,不擅长 Python,所以选择了 Serving 服务化部署。PaddleOCR 提供了两种服务部署方式:基于 PaddleHub Serving 的部署和基于 PaddleServing 的部署。我选择的是通过 PaddleHub Serving 进行部署。

安装 Hub Serving

准备环境

首先,我们需要安装 PaddleHub。可以通过以下命令安装:

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

安装完成后,可以通过命令行查看安装情况。

查看安装情况

下载推理模型

在 PaddleOCR 项目中,新建一个 inference 文件夹,并下载推理模型放入其中。默认使用的是 v1.1 版的超轻量模型。

下载推理模型

模型的默认路径为:

  • 检测模型:./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 deployhubservingocr_det

hub install deployhubservingocr_rec

hub install deployhubservingocr_system

建议将这三个模块都安装上,以避免启动时出现错误。

启动服务

服务启动方式分为全局启动和指定路径启动。

hub serving start -m ocr_system

我选择的是指定路径启动,需要切换到 hubserving 目录下并通过以下命令启动:

hub serving start -c deployhubservingocr_systemconfig.json

启动的其他参数可以参考官方文档。

注意: 如果启动报错路径找不到,需将 PaddleOCRdeployhubserving 下的 ocr_system、ocr_det、ocr_rec 的 params.py 文件中的所有 model_dir 替换为符合 Windows 格式的绝对路径。

这样就完成了一个服务化 API 的部署,使用默认端口号 8868。访问示例如下:

python tools/test_hubserving.py --server_url=http://127.0.0.1:8868/predict/ocr_system --image_dir=img/22.jpg

输出结果:

输出结果

Java 调用 PaddleOCR 服务

我们可以通过 Java 代码进行服务的调用,以下是一个简单的示例:

@RestController
@RequestMapping("/paddleocr")
public class PaddleOCRController {

    @PostMapping("/upload")
    public String fileUpload(@RequestParam("file") MultipartFile file, HttpServletRequest req, Model model) {
        try {
            String fileName = System.currentTimeMillis() + file.getOriginalFilename();
            String destFileName = req.getServletContext().getRealPath("") + "uploaded" + File.separator + fileName;
            File destFile = new File(destFileName);
            destFile.getParentFile().mkdirs();
            file.transferTo(destFile);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            MultiValueMap map = new LinkedMultiValueMap();

            InputStream imagePath = new FileInputStream(destFile);
            map.add("images", ImageToBase64(imagePath));

            HttpEntity<MultiValueMap> request = new HttpEntity(map, headers);
            RestTemplate restTemplate = new RestTemplate();
            Map json = restTemplate.postForEntity("http://127.0.0.1:8868/predict/ocr_system", request, Map.class).getBody();

            List<List> json1 = (List<List>) json.get("results");

            String tarImgPath = destFile.toString();
            File srcImgFile = new File(tarImgPath);
            Image srcImg = ImageIO.read(srcImgFile);

            if (srcImg == null) {
                return "什么也没有,结束!";
            }

            int srcImgWidth = srcImg.getWidth(null);
            int srcImgHeight = srcImg.getHeight(null);
            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);

            for (int i = 0; i < json1.get(0).size(); i++) {
                List<List> json2 = (List<List>) json1.get(0).get(i).get("text_region");
                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);
            }

            g.dispose();
            FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
            ImageIO.write(bufImg, "png", outImgStream);
            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;
        try {
            data = new byte[imgPath.available()];
            imgPath.read(data);
            imgPath.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(Objects.requireNonNull(data));
    }
}

然后运行,通过 postman 调取接口进行测试。

Java 调用测试

控制台输出结果:

控制台输出结果

完成后,可以根据自己的业务需求进行进一步的处理和修改。

FAQ

问:如何安装 PaddleHub?

答:可以通过 pip 命令 pip install paddlehub 进行安装,建议使用国内镜像以提高安装速度。

问:PaddleOCR 支持哪些语言的识别?

答:PaddleOCR 支持多种语言的识别,包括中文、英文以及其他 80 多种语言。

问:如何修改模型路径?

答:可以在 params.py 文件中查看和修改模型路径,或者使用 PaddleOCR 提供的模型库下载其他模型。

问:Java 如何调用 PaddleOCR 服务?

答:可以通过 Java 的 HTTP 客户端(如 RestTemplate)发送请求到 PaddleOCR 部署的 API 服务。

问:如何提高识别准确率?

答:可以选择更高精度的模型,或者通过数据增强、模型微调等方法提升模型的识别准确率。

#你可能也喜欢这些API文章!