效果图
一、什么是OCR
OCR,即光学字符识别(Optical Character Recognition),通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程,是一种能够将图像文件中的文字资料转化为电子文本的技术。它广泛应用于数字化文档管理、自动化数据录入、智能识别等多个领域,涉及的主要技术包括图像预处理、特征提取、文本识别等
处理过程
-
文字检测:解决的问题是哪里有文字,文字的范围有多少
-
文字识别:对定位好的文字区域进行识别,主要解决的问题是每个文字是什么,将图像中的文字区域进转化为字符信息。
二、百度AI平台搭建
百度智能云千帆大模型平台网址:百度智能云千帆大模型平台
(一)登录百度智能云平台
(二)获取API Key、Sectet Key
搜索“文字识别”进入到文字识别的控制台
第一步:领取资源,单击“去领取”,领取免费资源;
单击“卡证OCR”选择“身份证识别”,领取相应资源
第二步:创建应用
进入到创建页面,按一下步骤创建应用,其中应用名称和描述按自己的写,单击创建即可
进入到应用详情,即可查看当前创建的应用,重点关注API Key 和Sectet Key两个值,后续需要根据这两个值来鉴权,获取Access_token(Access_token是用户的访问令牌)
如有其他问题,查看相应技术文档,具体位置以表明
三、idae代码布局
Base64Util:Base64 工具类 用于实现Base64编码和解码操作
FileUtil:文件读取工具类 提供了一系列方便操作文件的方法,如读取文件内容、写入文件、删除文件、复制文件等
GsonUtils:Json工具类 提供JSON对象与Java对象之间的相互转换功能。
Httputill:http 工具类 用于发送HTTP请求和处理响应结果的工具类。它可以简化网络请求的编写
Sample:获取access token令牌
其中Base64Util、FileUtil、GsonUtils、Httputill四个文件是根据网址自己下载的
重要提示代码中所需工具类FileUtil,Base64Util,HttpUtil,GsonUtils请从 https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72 https://ai.baidu.com/file/C8D81F3301E24D2892968F09AE1AD6E2 https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3 https://ai.baidu.com/file/470B3ACCA3FE43788B5A963BF0B625F3 下载
(一)添加依赖
<!-- 百度AI SDK -->
<dependency>
<groupId>com.baidu.aip</groupId>
<artifactId>java-sdk</artifactId>
<version>4.15.7</version>
</dependency>
<!-- FastJSON 用于解析返回的 JSON 数据 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
</dependency>
<!-- OkHttp 用于 HTTP 请求 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>
<!-- GSON 用于 JSON 解析(如果需要) -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
(二)鉴权:Sample.java
以上已经获得了API Key和Secret Key的值,要想令牌获得需要带着参数请求百度AI给的授权服务地址来获得access token
请求URL数据格式
向授权服务地址
https://aip.baidubce.com/oauth/2.0/token
发送请求(推荐使用POST),并在URL中带上以下参数:
grant_type: 必须参数,固定为
client_credentials
;client_id: 必须参数,应用的
API Key
;client_secret: 必须参数,应用的
Secret Key
;
public class Sample {
public static final String API_KEY = "自己的API_KEY值";//填写自己应用对应API_KEY的值
public static final String SECRET_KEY = "自己的SECRET_KEY值";//填写自己应用对应SECRET_KEY的值
static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build();
/**
* 从用户的AK,SK生成鉴权签名(Access Token)
*
* @return 鉴权签名(Access Token)
* @throws IOException IO异常
*/
public static String getAccessToken() throws IOException {
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 = HTTP_CLIENT.newCall(request).execute();
return new JSONObject(response.body().string()).getString("access_token");
}
}
(三)控制器:BaiDuAI.java
BaiDuAI.java是用来解析身份证图片
package com.hz.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hz.until.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
@RestController
@RequestMapping("/baidu")
public class BaiDuAI {
@PostMapping("/idcard")
public String getIdcardInfo(@RequestPart("file") MultipartFile file) {
// 请求url
String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard";
try {
//将上传的文件转换为字节数组
byte[] imgData = file.getBytes();
//使用Base64编码将字节数组转换为字符串。
String imgStr = Base64Util.encode(imgData);
//对Base64编码后的字符串进行URL编码,以确保其可以在HTTP请求中安全传输。
String imgParam = URLEncoder.encode(imgStr, "UTF-8");
//构建请求参数字符串,指定需要识别的是身份证正面(id_card_side=front)并附上图片数据。
String param = "id_card_side=front&image=" + imgParam;
//获取实时令牌
String accessToken = Sample.getAccessToken();
//向百度AI平台发送POST请求
String result = HttpUtil.post(url, accessToken, param);
//解析返回的结果为JSON对象
JSONObject jsonObject = JSON.parseObject(result);
JSONObject wordsResult = jsonObject.getJSONObject("words_result");
JSONObject responseJson = new JSONObject();
if (wordsResult != null) {
String nameInf = wordsResult.getJSONObject("姓名").getString("words");
//提取出的姓名添加到 responseJson 对象中
responseJson.put("姓名", nameInf);
String nationalityInf = wordsResult.getJSONObject("民族").getString("words");
responseJson.put("民族", nationalityInf);
String genderInf = wordsResult.getJSONObject("性别").getString("words");
responseJson.put("性别", genderInf);
String idNumberInf = wordsResult.getJSONObject("公民身份号码").getString("words");
responseJson.put("公民身份号码", idNumberInf);
//Map<String,String> map = CardUtil.getBirthdayAgeSex(idNumberInf);
//responseJson.put("年龄",map.get("age"));
} else {
responseJson.put("error", "未找到 words_result 字段");
}
System.out.println(responseJson.toJSONString());
return responseJson.toJSONString();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "{\"error\": \"请求失败,编码错误\"}";
} catch (IOException e) {
e.printStackTrace();
return "{\"error\": \"请求失败,读取文件错误\"}";
} catch (Exception e) {
e.printStackTrace();
return "{\"error\": \"请求失败,未知错误\"}";
}
}
}
控制台运行结果
(四)前端:index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>身份证识别</title>
<link rel="stylesheet" href="/css/index.css">
</head>
<body>
<div class="container">
<h1>身份证识别</h1>
<form id="InputFile" enctype="multipart/form-data" th:action="@{/baidu/idcard}" method="post">
<div class="form-group">
<label for="file">上传身份证照片</label>
<input type="file" id="file" name="file" accept="image/*">
</div>
<button type="button" onclick="uploadFile()">上传并识别</button>
</form>
<div class="IdcardInfo">
<div class="form-group">
<label for="name">姓名</label>
<input type="text" id="name" name="name" readonly>
</div>
<div class="form-group">
<label for="nationality">民族</label>
<input type="text" id="nationality" name="nationality" readonly>
</div>
<div class="form-group">
<label for="gender">性别</label>
<input type="text" id="gender" name="gender" readonly>
</div>
<div class="form-group">
<label for="id-number">身份证号码</label>
<input type="text" id="id-number" name="id-number" readonly>
</div>
</div>
</div>
<script src="/js/jquery-3.7.1.min.js"></script>
<script>
function uploadFile() {
const fileInput = $('#file')[0];
const file = fileInput.files[0];
if (!file) {
alert('请选择一个文件');
return;
}
const formData = new FormData();
formData.append('file', file);
$.ajax({
url: '/baidu/idcard',
type: 'POST',
data: formData,
contentType: false,
processData: false,
success: function(data) {
console.log('Response:', data); // 添加调试信息
fillFormFields(data);
},
error: function(xhr, status, error) {
console.error('Error:', xhr.responseText); // 添加调试信息
alert('上传失败,请重试');
}
});
}
function fillFormFields(data) {
// 输出完整的 data 对象以进行调试
console.log('Full Response:', data);
// 确保 data 是一个 JSON 对象
if (typeof data === 'string') {
try {
data = JSON.parse(data);
} catch (e) {
console.error('Failed to parse JSON:', e);
alert('请求失败,解析 JSON 错误');
return;
}
}
$('#name').val(data.姓名);
$('#nationality').val(data.民族);
$('#gender').val(data.性别);
$('#id-number').val(data.公民身份号码);
}
</script>
</body>
</html>