【SpringBoot】整合百度文字识别

流程图

一、前期准备

1.1 打开百度智能云官网找到管理中心创建应用

全选文字识别

1.2 保存好AppId、API Key和Secret Key

1.3 找到通用场景文字识别,立即使用

1.4 根据自己需要,选择要开通的项目

二、代码编写

以通用文字识别(高精度版)为例

2.1 加依赖(pom.xml)

    <dependencies>

        <!-- 引入Spring Boot的web starter依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 引入Lombok依赖 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- 引入Spring Boot的测试依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 百度人工智能依赖 -->
        <dependency>
            <groupId>com.baidu.aip</groupId>
            <artifactId>java-sdk</artifactId>
            <version>4.11.3</version>
        </dependency>

        <!-- okhttp -->
        <!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.12.0</version>
        </dependency>

        <!-- 对象转换成json -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>

        <!-- thymeleaf模板引擎 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>

2.2 编写yml文件

# 这是一个配置块,用于设置百度OCR服务的认证信息。
baidu:
  ocr: # OCR服务的配置项
    appId:  # 百度OCR服务的应用ID
    apiKey:  # 百度OCR服务的API密钥
    secretKey:  # 百度OCR服务的密钥

spring:
  thymeleaf:
    cache: false

2.3 工具类

package com.baiduocr.util;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
 * 这个类定义了全局的异常处理器。
 */
public class GlobalExceptionHandler {
    /**
     * 处理所有类型的异常。
     *
     * @param e 异常对象,捕获到的异常会作为参数传入。
     * @return 返回一个包含异常信息的ResponseEntity对象,状态码为500(内部服务器错误)。
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleException(Exception e) {
        // 构造并返回一个包含异常信息的ResponseEntity对象
        return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }

}
package com.baiduocr.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.Map;

/**
 * JsonChange 类提供了将 JSON 字符串转换为 Map 对象的静态方法。
 */
public class JsonChange {

    /**
     * 将JSON字符串解析为Map对象。
     * @param jsonString 待转换的JSON字符串。
     * @return 返回一个包含JSON数据的Map对象。
     * @throws Exception 如果转换过程中发生错误,则抛出异常。
     */
    public static Map<Object, Object> json2map(String jsonString) throws Exception {
        // 创建 ObjectMapper 实例用于处理 JSON 字符串
        ObjectMapper mapper = new ObjectMapper();
        // 设置序列化选项,仅包含非空值
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 将 JSON 字符串解析为 Map 对象并返回
        return mapper.readValue(jsonString, Map.class);
    }

}

2.4 Service层

package com.baiduocr.service;

import okhttp3.*;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;

@Service
public class OcrService {
    @Value("${baidu.ocr.appId}")
    private String appId;

    @Value("${baidu.ocr.apiKey}")
    private String apiKey;

    @Value("${baidu.ocr.secretKey}")
    private String secretKey;

    // accessToken
    private String accessToken;

    // HTTP客户端
    static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build();

    /**
     * 调用百度高精度版OCR接口进行文字识别。
     *
     * @param imageBytes 待识别的图片字节数组
     * @return OCR识别结果
     * @throws IOException IO异常
     */
    public String performOcr(byte[] imageBytes) throws IOException {
        // 设置请求体
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "detect_direction=false&paragraph=false&probability=true");
        // 创建请求
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/accurate?access_token=" + accessToken)
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build();
        // 发送请求并获取响应
        Response response = HTTP_CLIENT.newCall(request).execute();
        // 返回响应内容
        return response.body().string();
    }

    /**
     * 获取百度的Access Token。
     *
     * @return 百度的Access Token
     * @throws IOException IO异常
     */
    private String getAccessToken() throws IOException {
        // 设置请求体
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "grant_type=client_credentials&client_id=" + apiKey
                + "&client_secret=" + secretKey);
        // 创建请求
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/oauth/2.0/token")
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();
        // 发送请求并获取响应
        Response response = HTTP_CLIENT.newCall(request).execute();
        // 解析响应内容获取Access Token
        return new JSONObject(response.body().string()).getString("access_token");
    }

}

2.5 eneity层

package com.baiduocr.entity;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * BaiduOcrProperties类用于配置百度OCR服务的相关属性。
 * 该类通过@ConfigurationProperties注解与配置文件中的baidu.ocr前缀绑定,
 * 使得我们可以从配置文件中动态读取appId, apiKey和secretKey等属性值。
 *
 * @Configuration 表示这是一个配置类,可以被Spring作为配置源。
 * @ConfigurationProperties(prefix = "baidu.ocr") 将该类的属性与配置文件中的baidu.ocr前缀绑定。
 * @Data 提供了基于Lombok的自动getter/setter等代码生成,方便属性的访问和设置。
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "baidu.ocr")
public class BaiduOcrProperties {
    // 百度OCR的App ID
    private String appId;
    // 百度OCR的API Key
    private String apiKey;
    // 百度OCR的Secret Key
    private String secretKey;
}

2.6 控制器

package com.baiduocr.controller;

import com.baidu.aip.ocr.AipOcr;
import com.baiduocr.entity.BaiduOcrProperties;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import okhttp3.*;

/**
 * OcrController类负责处理OCR相关的请求。
 * 它利用百度OCR服务对上传的文件或文本进行识别,并返回识别结果。
 */

@Controller
public class OcrController {
    // 创建一个日志记录器
    private static final Logger logger = LoggerFactory.getLogger(OcrController.class);
    // 注入BaiduOcrProperties对象
    private final BaiduOcrProperties baiduOcrProperties;
    // 创建一个OkHttpClient对象
    static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build();

    // 构造函数,注入BaiduOcrProperties对象
    @Autowired
    public OcrController(BaiduOcrProperties baiduOcrProperties) {
        this.baiduOcrProperties = baiduOcrProperties;
    }

    @RequestMapping(value = {"/", "/ocr"})
    public String index() {
        return "ocr";
    }
    /**
     * 处理OCR识别请求。
     *
     * @param file 用户上传的文件,将进行OCR识别。
     * @param model Spring模型,用于在识别后向视图传递数据。
     * @return 视图名称,根据识别结果决定是显示结果还是错误页面。
     */
    @RequestMapping(value = "/doOcr")
    public String ocr(MultipartFile file, Model model) {
        try {
            List<String> ocrResult = performOcr(file); // 执行OCR识别
            model.addAttribute("ocrResult", ocrResult); // 将识别结果添加到模型中
        } catch (Exception e) {
            logger.error("OCR识别失败", e);
            return "error"; // 识别失败,返回错误页面
        }
        return "ocr_result"; // 识别成功,返回结果页面
    }

    /**
     * 执行OCR识别操作。
     *
     * @param file 需要进行OCR识别的文件。
     * @return 识别到的文本列表。
     * @throws Exception 如果识别过程中出现错误,则抛出异常。
     */
    private List<String> performOcr(MultipartFile file) throws Exception {
        logger.info("Performing OCR on file: {}", file.getOriginalFilename()); // 记录日志,表示开始进行OCR识别

        AipOcr client = new AipOcr(baiduOcrProperties.getAppId(), baiduOcrProperties.getApiKey(), baiduOcrProperties.getSecretKey()); // 创建百度OCR客户端

        // 获取Access Token
        String accessToken = getAccessToken();

        // 在开发环境中记录Access Token(请在生产环境中移除或注释掉此行)
        //logger.debug("Access Token: {}", accessToken);

        HashMap<String, String> options = new HashMap<>(); // 设置OCR识别的选项
        options.put("language_type", "CHN_ENG");
        options.put("detect_direction", "true");
        options.put("detect_language", "true");
        options.put("probability", "true");

        byte[] buf = file.getBytes(); // 从文件中读取内容
        JSONObject res = client.basicAccurateGeneral(buf, options);  // 使用高精度接口进行通用文字识别

        List<String> wordsList = new ArrayList<>(); // 存储识别出的文本
        for (Object obj : res.getJSONArray("words_result")) { // 遍历识别结果,提取文本
            JSONObject jsonObj = (JSONObject) obj;
            wordsList.add(jsonObj.getString("words"));
        }
        return wordsList;
    }

    /**
     * 从百度OCR服务获取Access Token。
     *
     * @return Access Token,用于身份验证。
     * @throws IOException 如果在获取Access Token过程中出现IO错误。
     */
    private String getAccessToken() throws IOException {
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "grant_type=client_credentials&client_id=" + baiduOcrProperties.getApiKey()
                + "&client_secret=" + baiduOcrProperties.getSecretKey());
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/oauth/2.0/token")
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute(); // 发送请求,获取响应
        return new JSONObject(response.body().string()).getString("access_token"); // 从响应中提取Access Token
    }

    /**
     * 捕获并处理所有异常。
     *
     * @param e 异常对象。
     * @return 响应实体,包含异常信息。
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleException(Exception e) {
        return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); // 返回内部服务器错误信息
    }


}

2.6 前端页面(thymeleaf)

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>OCR识别</title>
</head>
<body>

<h1>上传图片进行OCR识别</h1>
<form th:action="@{/doOcr}" method="post" enctype="multipart/form-data">
    <input type="file" name="file" accept="image/*">
    <button type="submit">上传并识别</button>
</form>

</body>
<style>
    body {
        font-family: Arial, sans-serif;
        margin: 0;
        padding: 0;
        display: flex;
        flex-direction: column;
        align-items: center;
        background-color: #f8f9fa;
    }
    h1 {
        color: #343a40;
        margin-top: 20px;
    }
    form {
        margin: 20px 0;
        padding: 20px;
        border: 1px solid #dee2e6;
        border-radius: 5px;
        background-color: #fff;
        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
    }
    input[type="file"] {
        margin-bottom: 10px;
    }
    button {
        background-color: #007bff;
        color: white;
        padding: 10px 20px;
        border: none;
        border-radius: 5px;
        cursor: pointer;
    }
    button:hover {
        background-color: #0056b3;
    }
</style>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>OCR结果</title>
</head>
<body>

<h1>OCR识别结果</h1>
<div th:if="${ocrResult != null}">
    <ul>
        <li th:each="word : ${ocrResult}" th:text="${word}"></li>
    </ul>
</div>
<a href="/">返回首页</a>

</body>
<style>
    body {
        font-family: Arial, sans-serif;
        margin: 0;
        padding: 0;
        display: flex;
        flex-direction: column;
        align-items: center;
        background-color: #f8f9fa;
    }
    h1 {
        color: #343a40;
        margin-top: 20px;
    }
    div {
        margin: 20px 0;
        padding: 20px;
        border: 1px solid #dee2e6;
        border-radius: 5px;
        background-color: #fff;
        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
        width: 80%;
        max-width: 800px;
    }
    ul {
        list-style-type: none;
        padding: 0;
    }
    li {
        padding: 5px 0;
        border-bottom: 1px solid #dee2e6;
    }
    a {
        margin-top: 20px;
        color: #007bff;
        text-decoration: none;
    }
    a:hover {
        text-decoration: underline;
    }
</style>
</html>

三、效果展示

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

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

相关文章

2024-5-4-从0到1手写配置中心Config之基于h2的config-server

添加依赖 新建的web工程中添加h2的依赖 添加h2的配置 设置数据源和密码设置初始化sql语句打开h2的控制台 初始化语句创建一个config表&#xff0c;保存服务配置信息。 完成CRUD接口 controller类 mapper接口 测试 在web控制台可以看到sql已经初始化完成&#xff0c;crud接口…

如何*永久*禁用edge打开PDF文件?

要永久禁用Microsoft Edge打开PDF文件&#xff0c;您可以按照以下步骤进行操作&#xff1a; 打开文件资源管理器并找到任意一个PDF文件。 右键单击该文件并选择“属性”。 在“属性”对话框中&#xff0c;单击“更改”按钮旁边的“打开方式”。 在“打开方式”对话框中&…

Leetcode - 398周赛

目录 一&#xff0c;3151. 特殊数组 I 二&#xff0c;3152. 特殊数组 II 三&#xff0c;3153. 所有数对中数位不同之和 四&#xff0c;3154. 到达第 K 级台阶的方案数 一&#xff0c;3151. 特殊数组 I 本题就是判断一个数组是否是奇偶相间的&#xff0c;如果是&#xff0c;…

【Floodfill算法】dfs或者bfs解决floodfill算法

1.图像渲染 图像渲染 dfs解决代码&#xff1a; class Solution { public:int dx[4] {0, 0, -1, 1};int dy[4] {-1, 1, 0, 0};int m, n;int prev;vector<vector<int>> ret;vector<vector<int>> floodFill(vector<vector<int>>& ima…

Java并发: 锁和同步

在Java并发: 面临的挑战那一篇中我们提到锁和同步是实现并发安全(可见性/原子性)的方法之一。这一章我们来讲讲Java中的锁和同步的各种工具&#xff0c;包括: LockSupportAbstractQueuedSynchronizerJava内置的锁实现 1. LockSupport LockSupport是基于Unsafe的park/unpark实…

linux 查看java线程与linux线程关系

linux 查看占用cpu高的 java 线程 linux 排查cpu占用100%故障 ##java程序 import java.util.Scanner; public class JavaThreadIDName {public static void main(String[] args) {Thread t Thread.currentThread();t.setName("laoyoutiao");System.out.println(&…

golang创建式设计模式---工厂模式

创建式设计模式—工厂模式 目录导航 创建式设计模式---工厂模式1)什么是工厂模式2)使用场景3)实现方式4)实践案例5)优缺点分析 1)什么是工厂模式 工厂模式(Factory Method Pattern)是一种设计模式&#xff0c;旨在创建对象时&#xff0c;将对象的创建与使用进行分离。通过定义…

以太坊(2)——共识机制与挖矿算法

共识机制 ETH采用的是基于GHOST协议的共识机制 "GHOST"&#xff08;Greedy Heaviest-Observed Sub-Tree&#xff09;共识机制&#xff0c;它是以太坊使用的一种改进的区块链共识算法。GHOST共识机制旨在提高链的安全性和效率&#xff0c;通过考虑非主链区块的贡献&…

kubectl详解

文章目录 kubectl详解一、陈述式管理1、陈述式资源管理方法2、k8s相关信息查看2.1 查看版本信息2.1.1 查看资源对象简写2.1.2 查看集群信息2.1.3 配置kubectl自动补全2.1.4 查看日志 2.2 基本信息查看2.2.1 查看集群状态2.2.2 查看命名空间 2.3 命名空间操作2.3.1 查看default命…

CDN用户平台安装说明

CDN用户平台安装说明 登录管理员系统 在”系统设置” – “高级设置” – “用户节点”中点击”添加节点” 如果所示&#xff1a; 节点名称 - 可以任意填写 进程监听端口 - 启动用户节点后&#xff0c;进程所监听的端口&#xff0c;通常是HTTP 80或者HTTPS 443&#xff0c;…

html 段落与排版标记 Web前端开发技术、详细文章(例如)

段落与排版标记 网页的外观是否美观&#xff0c;很大程度上取决于其排版。在页面中出现大段的文字&#xff0c;通常采用分段进行规划&#xff0c;对换行也有极其严格的划分。本节从段落的细节设置入手&#xff0c;利用段落与排版标记自如地处理大段的文字。 段落p标记 在HTM…

Spring Cloud Gateway 网关

一. 什么是网关&#xff08;Gateway&#xff09; 网关就是一个网络连接到另一个网络的关口。 在同一个项目或某一层级中&#xff0c;存在相似或重复的东西&#xff0c;我们就可以将这些相似重复的内容统一提取出来&#xff0c;向前或向后抽象成单独的一层。这个抽象的过程就是…

Linux磁盘高级操作

RAID RAID存储系统是一种数据存储虚拟化技术&#xff0c;它将多个物理磁盘驱动器组合成一个或多个逻辑单元&#xff0c;以提供数据冗余和/或提高性能。 1. RAID 0 无奇偶校验与冗余&#xff08;磁盘容错&#xff09;的条带存储&#xff08;带区卷/条带卷&#xff09; 由两块…

Linux-文件或目录权限

在使用 ll 时&#xff0c;可以查看文件夹内容的详细信息&#xff0c;信息的第1位表示类型&#xff0c;具体信息如下&#xff1a; 类型说明-普通文件d文件夹b块设备文件c字符设备文件p管道文件s套接口文件 第2-10位表示权限&#xff0c; 举例&#xff1a;rwxr-xr-x 类型说明r…

简单快捷的图片格式转换工具:认识webp2jpg-online

经常写博客或记笔记的朋友们可能会碰到图床不支持的图片格式或图片太大需要压缩的情况。通常&#xff0c;我们会在浏览器中搜索在线图片格式转换器&#xff0c;但这些转换器往往伴有烦人的广告或要求登录&#xff0c;并且支持的转换格式有限。最近&#xff0c;我在浏览 GitHub …

java8总结

java8总结 java8新特性总结1. 行为参数化2. lambda表达式2.1 函数式接口2.2 函数描述符 3. Stream API3.1 付诸实践 java8新特性总结 行为参数化lambda表达式Stream Api 1. 行为参数化 定义&#xff1a;行为参数化&#xff0c;就是一个方法接受多个不同的行为作为参数&#x…

HiWoo Box边缘计算网关

​在数字化浪潮汹涌的今天&#xff0c;边缘计算网关成为了连接物理世界与数字世界的桥梁&#xff0c;其重要性日益凸显。HiWoo Box&#xff0c;作为一款功能强大的边缘计算网关&#xff0c;不仅具备了传统网关的基本功能&#xff0c;更在数据采集、处理、传输等方面展现出了卓越…

岛屿问题刷题

200. 岛屿数量 - 力扣&#xff08;LeetCode&#xff09; class Solution {public int numIslands(char[][] grid) {int n grid.length;//grid行数int m grid[0].length;//grid列数int res 0;for(int r 0;r<n;r){for(int c0;c<m;c){if(grid[r][c]1){dfs(grid,r,c);res…

Web Server项目实战3-Web服务器简介及HTTP协议

Web Server&#xff08;网页服务器&#xff09; 一个 Web Server 就是一个服务器软件&#xff08;程序&#xff09;&#xff0c;或者是运行这个服务器软件的硬件&#xff08;计算机&#xff09;。其主要功能是通过 HTTP 协议与客户端&#xff08;通常是浏览器&#xff08;Brow…

面试八股之MySQL篇5——主从同步原理篇

&#x1f308;hello&#xff0c;你好鸭&#xff0c;我是Ethan&#xff0c;一名不断学习的码农&#xff0c;很高兴你能来阅读。 ✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。 &#x1f3c3;人生之义&#xff0c;在于追求&#xff0c;不在成败&#xff0c;勤通…