面向小学生的智能题目生成系统开发(四)

一、OCR的最终敲定

        在上一次的开发中已经完成了图片预处理,单图、多图和pdf识别,在探索更多文件格式识别后,发现Tessertact OCR的能力确实有限,在进行很多处理时需要引入很多其他的库,增加了应用的负担,并且依赖与依赖间不好管理,所以我们决定采用百度的解决方案。

二、百度云的创建

        打开百度智能云-云智一体深入产业,注册登录后打开用户中心。

在用户中心中搜索OCR:

点击进入文字识别,打开应用列表:

创建应用,勾选需要的领域:

创建成功后打开文字识别-百度智能云

三、准备调用

        先安装所需的依赖。

        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20240205</version>
        </dependency>

        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.12.0</version>
        </dependency>

        写一个Utils类来专门服务百度的OCR,按照文档的指示,写一个从用户的AK,SK生成鉴权签名(Access Token)的函数,方便后续调用。(API_KEY和SECRET_KEY自行填写)

    public static final String API_KEY = "6gLVxxxxxxxxxxxxxhNYPTj";
    public static final String SECRET_KEY = "V7FPoxxxxxxxxxxxxxxxxWwyv1OiO";

    public static final OkHttpClient HTTP_CLIENT = new  OkHttpClient().newBuilder().readTimeout(300, TimeUnit.SECONDS).build();

    /**
     * 从用户的AK,SK生成鉴权签名(Access Token)
     *
     * @return 鉴权签名(Access Token)
     * @throws IOException IO异常
     */
    public static String getAccessToken() {
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "grant_type=client_credentials&client_id=" + API_KEY
                + "&client_secret=" + SECRET_KEY);
        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 = null;
        try {
            response = HTTP_CLIENT.newCall(request).execute();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        try {
            return new JSONObject(response.body().string()).getString("access_token");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

        拿到 Access Token后来写一个函数,试一下最简单的图片识别。

public static String getImgResponse(String imgBase64) throws IOException{
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        String bodystr ="image=" + imgBase64 + "&detect_direction=false&paragraph=false&probability=false&multidirectional_recognize=false";
        RequestBody body = RequestBody.create(mediaType, bodystr);
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token=" + getAccessToken())
                .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();
    }

        接下来写一个新的Service类来做调用,按照文档,图片需要转成base64编码进行传输,并且将字符串中的分别转换为为%2F,%3D,%2B,以符合百度的要求,所以要在工具类中写一个处理base64编码的函数。

package com.dpsk.dpsk_quiz_sys_java.service;
import com.dpsk.dpsk_quiz_sys_java.utils.BaiduUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Base64;
@Service
public class BaiduOcrService {

    public String recognizeImg(MultipartFile image) throws IOException {
        // 将图片文件转换为Base64字符串
        byte[] imageBytes = image.getBytes();
        String base64Image = Base64.getEncoder().encodeToString(imageBytes);
        //将字符串中的/,=,+
        //分别转换为为%2F,%3D,%2B
        //符合百度的要求
        base64Image = BaiduUtils.replaceSpecialCharacters(base64Image);

        return BaiduUtils.getImgResponse(base64Image);
    }
}

 工具类 

//将字符串中的/=+,分别转换为为%2F,%3D,%2B
    public static String replaceSpecialCharacters(String str) {
        // 使用StringBuilder来构建新的字符串
        StringBuilder sb = new StringBuilder();
        // 遍历字符串的每个字符
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            switch (c) {
                case '/':
                    sb.append("%2F");
                    break;
                case '=':
                    sb.append("%3D");
                    break;
                case '+':
                    sb.append("%2B");
                    break;
                default:
                    sb.append(c);
            }
        }
        return sb.toString();
    }

         至此,可以来写Controller来和前端对接了。

package com.dpsk.dpsk_quiz_sys_java.controller;
import com.dpsk.dpsk_quiz_sys_java.pojo.ResponseMessage;
import com.dpsk.dpsk_quiz_sys_java.service.BaiduOcrService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("/baiduocr")
public class BaiduOcrController {
    @Autowired
    private BaiduOcrService ocrService;

    @PostMapping("/recognize")
    public ResponseMessage<String> recognizeImage(@RequestParam("image") MultipartFile image) {
        if (image == null || image.isEmpty()) {
            return ResponseMessage.error("照片为空");
        }

        try {
            // 调用OCR服务
            String ocrResult = ocrService.recognizeImg(image);

            // 返回成功结果
            return ResponseMessage.success(ocrResult);
        } catch (Exception e) {
            // 返回错误信息
            return ResponseMessage.error("Error occurred during OCR processing: " + e.getMessage());
        }
    }
}

四 、简单测试与效果展示

        使用postman,各项参数按照文档填写。

  1. 图片的base64编码是不包含图片头的,如(data:image/jpg;base64,)
  2. 使用 Postman 工具或 Python、PHP 等请求库会自动进行 urlencode,无需自行处理。

        (请求格式支持:PNG、JPG、JPEG、BMP、TIFF、PNM、WebP)

        可以看到整体是JSON格式,其中data是一个words数组,每个words是每一行的识别的内容,最后words_result_num为words数组的长度,需要后期整合为完整的一段话。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值