百度的护照识别技术支持对中国大陆护照个人资料页所有15个字段进行结构化识别,包括国家码、护照号、姓名、姓名拼音、性别、出生地点、出生日期、签发地点、签发日期、有效期、签发机关、护照类型、国籍、MRZCode1、MRZCode2。
本文就如何调用护照识别技术做个简单的教程。
一、使用攻略
说明:本文采用C# 语言,开发环境为.Net Core 3.1,采用在线API接口方式实现。
(1)平台接入
登陆 百度智能云-管理中心 创建 “文字识别”应用,获取 “API Key ”和 “Secret Key”:https://console.bce.baidu.com/ai/?_=1603112205388&fromai=1#/ai/ocr/overview/index
(2)接口文档
文档地址:https://ai.baidu.com/ai-doc/OCR/Wk3h7y1gi
接口描述:
支持对中国大陆护照个人资料页所有15个字段进行结构化识别,包括国家码、护照号、姓名、姓名拼音、性别、出生地点、出生日期、签发地点、签发日期、有效期、签发机关、护照类型、国籍、MRZCode1、MRZCode2。
请求说明
HTTP方法:POST
请求URL:https://aip.baidubce.com/rest/2.0/ocr/v1/passport
URL参数:
Header如下:
Body中放置请求参数,参数详情如下:
请求参数
返回说明
返回参数
返回示例:
护照OCR:
耗时:00:00:00.7168000:
{
"log_id": 7377468409496932872,
"words_result_num": 14,
"words_result": {
"国家码": {
"location": {
"width": 59,
"top": 200,
"left": 762,
"height": 26
},
"words": "CHN"
},
"护照签发地点": {
"location": {
"width": 236,
"top": 505,
"left": 558,
"height": 43
},
"words": "山东/SHANDONG"
},
"MRZCode2": {
"location": {
"width": 1252,
"top": 797,
"left": 145,
"height": 88
},
"words": "E898657303CHNSDMO7O2<<<<<<<<<<<<<"
},
"有效期至": {
"location": {
"width": 287,
"top": 528,
"left": 955,
"height": 46
},
"words": "20261004"
},
"签发机关": {
"location": {
"width": 271,
"top": 583,
"left": 552,
"height": 42
},
"words": "公安部出入境管理局"
},
"MRZCode1": {
"location": {
"width": 1201,
"top": 781,
"left": 162,
"height": 45
},
"words": "PONSUN<
(3)源码共享
(3-1)根据 API Key 和 Secret Key 获取 AccessToken
///
/// 获取百度access_token
///
/// API Key
/// Secret Key
///
public static string GetAccessToken(string clientId, string clientSecret)
{
string authHost = "https://aip.baidubce.com/oauth/2.0/token";
HttpClient client = new HttpClient();
List> paraList = new List>();
paraList.Add(new KeyValuePair("grant_type", "client_credentials"));
paraList.Add(new KeyValuePair("client_id", clientId));
paraList.Add(new KeyValuePair("client_secret", clientSecret));
HttpResponseMessage response = client.PostAsync(authHost, new FormUrlEncodedContent(paraList)).Result;
string result = response.Content.ReadAsStringAsync().Result;
JObject jo = (JObject)JsonConvert.DeserializeObject(result);
string token = jo["access_token"].ToString();
return token;
}
(3-2)调用API接口获取识别结果
(3-2-1)在Startup.cs 文件 的 Configure(IApplicationBuilder app, IHostingEnvironment env) 方法中开启虚拟目录映射功能:
string webRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");//wwwroot目录
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(webRootPath, "Uploads", "BaiduAIs")),
RequestPath = "/BaiduAIs"
});
(3-2-2) 建立Index.cshtml文件
(3-2-2-1)前台代码:
由于html代码无法原生显示,只能简单说明一下:
主要是一个form表单,需要设置属性enctype="multipart/form-data",否则无法上传图片;
form表单里面有几个控件:
一个Input:type="file",asp-for="FileUpload" ,上传图片;
一个Input:type="submit",asp-page-handler="Passport" ,提交请求。
一个img:src="@Model.curPath",显示需要识别的护照图片。
最后显示后台 msg 字符串列表信息,如果需要输出原始Html代码,则需要使用@Html.Raw()函数。
注意:由于返回结果中含有特殊字符 <,所以需要对返回的字符串进行特殊字符替换处理,即将 < 替换为 < 。
(3-2-2-2) 后台代码:
主程序代码:
[BindProperty]
public IFormFile FileUpload { get; set; }
[BindProperty]
public string ImageUrl { get; set; }
public string curPath { get; set; }
string webRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
string BaiduAI_OCRPath="Uploads//BaiduAIs//";
string BaiduAI_OCRUrl="/BaiduAIs/";
string OCR_API_KEY="你的API KEY";
string OCR_SECRET_KEY="你的SECRET KEY";
public async Task OnPostPassportAsync()
{
if (FileUpload is null)
{
ModelState.AddModelError(string.Empty, "请先选择需要识别的图片!");
}
if (!ModelState.IsValid)
{
return Page();
}
msg = new List();
string fileDir = Path.Combine(webRootPath, BaiduAI_OCRPath);
string imgName = GetRandomName();
imgName = await UploadFile(FileUpload, fileDir);
string fileName = Path.Combine(fileDir, imgName);
string imgBase64 = GetFileBase64(fileName);
curPath = Path.Combine(BaiduAI_OCRUrl, imgName);
DateTime startTime = DateTime.Now;
string result = GetOCRJson(imgBase64, OCR_API_KEY, OCR_SECRET_KEY);
result = result.Replace("<", "<");
DateTime endTime = DateTime.Now;
TimeSpan ts = endTime - startTime;
JObject jo = (JObject)JsonStringToObj(result);
try
{
if (jo["error_code"] != null)
{
msg.Add("调用失败:" + jo["error_code"].ToString() + "-" + jo["error_msg"].ToString());
}
else
{
msg.Add("护照识别结果(耗时" + ts.TotalSeconds + "秒):\n");
msg.Add("识别结果数:" + jo["words_result_num"].ToString() + " ");
msg.Add("国家码:" + jo["words_result"]["国家码"]["words"].ToString());
msg.Add("护照号码:" + jo["words_result"]["护照号码"]["words"].ToString());
msg.Add("护照类型:" + jo["words_result"]["护照类型"]["words"].ToString());
msg.Add("姓名:" + jo["words_result"]["姓名"]["words"].ToString());
msg.Add("姓名拼音:" + jo["words_result"]["姓名拼音"]["words"].ToString());
msg.Add("性别:" + jo["words_result"]["性别"]["words"].ToString());
msg.Add("国籍:" + jo["words_result"]["国籍"]["words"].ToString());
msg.Add("生日:" + jo["words_result"]["生日"]["words"].ToString());
msg.Add("出生地点:" + jo["words_result"]["出生地点"]["words"].ToString());
msg.Add("签发日期:" + jo["words_result"]["签发日期"]["words"].ToString());
msg.Add("签发地点:" + jo["words_result"]["护照签发地点"]["words"].ToString());
msg.Add("有效期至:" + jo["words_result"]["有效期至"]["words"].ToString());
msg.Add("签发机关:" + jo["words_result"]["签发机关"]["words"].ToString());
msg.Add("MRZCode1:" + jo["words_result"]["MRZCode1"]["words"].ToString());
msg.Add("MRZCode2:" + jo["words_result"]["MRZCode2"]["words"].ToString());
}
}
catch (Exception e)
{
msg.Add("发生异常:");
msg.Add(result);
msg.Add(e.Message);
}
return Page();
}
其他相关函数:
///
/// 文字识别Json字符串
///
/// 图片base64编码
/// API Key
/// Secret Key
///
public static string GetOCRJson( string imgbase64, string clientId, string clientSecret)
{
string token = GetAccessToken(clientId, clientSecret);
string host = "https://aip.baidubce.com/rest/2.0/ocr/v1/passport?access_token=" + token;
Encoding encoding = Encoding.Default;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
request.Method = "post";
request.ContentType = "application/x-www-form-urlencoded";
request.KeepAlive = true;
string str = "image=" + HttpUtility.UrlEncode(imgbase64);
byte[] buffer = encoding.GetBytes(str);
request.ContentLength = buffer.Length;
request.GetRequestStream().Write(buffer, 0, buffer.Length);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
string result = reader.ReadToEnd();
return result;
}
///
/// 获取百度access_token
///
/// API Key
/// Secret Key
///
public static string GetAccessToken(string clientId, string clientSecret)
{
string authHost = "https://aip.baidubce.com/oauth/2.0/token";
HttpClient client = new HttpClient();
List> paraList = new List>();
paraList.Add(new KeyValuePair("grant_type", "client_credentials"));
paraList.Add(new KeyValuePair("client_id", clientId));
paraList.Add(new KeyValuePair("client_secret", clientSecret));
HttpResponseMessage response = client.PostAsync(authHost, new FormUrlEncodedContent(paraList)).Result;
string result = response.Content.ReadAsStringAsync().Result;
JObject jo = (JObject)JsonConvert.DeserializeObject(result);
string token = jo["access_token"].ToString();
return token;
}
///
/// 生成一个随机唯一文件名(Guid)
///
///
public static string GetRandomName()
{
return Guid.NewGuid().ToString("N");
}
///
/// 返回文件的base64编码
///
/// 文件绝对路径名称
///
public static String GetFileBase64(string fileName)
{
FileStream filestream = new FileStream(fileName, FileMode.Open);
byte[] arr = new byte[filestream.Length];
filestream.Read(arr, 0, (int)filestream.Length);
string baser64 = Convert.ToBase64String(arr);
filestream.Close();
return baser64;
}
///
/// json转为对象
///
/// Json字符串
///
public static Object JsonStringToObj(string jsonString)
{
Object s = JsonConvert.DeserializeObject(jsonString);
return s;
}
///
/// 上传文件,返回文件名
///
/// 文件上传控件
/// 文件绝对路径
///
public static async Task UploadFile(IFormFile formFile, string fileDir)
{
if (!DirectoryExists(fileDir))
{
Directory.CreateDirectory(fileDir);
}
string extension = GetExtension(formFile);
string imgName = GetRandomName() + extension;
var filePath = Path.Combine(fileDir, imgName);
using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
await formFile.CopyToAsync(fileStream);
}
return imgName;
}
二、效果测试
1、页面:
2、识别结果:
2.1
2.2
2.3
三、测试结果及建议
从上面的测试结果可以看到,百度护照识别技术相当准确,可以大大提升护照信息的录入效率。
百度护照识别技术对于中国大陆护照基本上都能准确识别出国家码、护照号、姓名、性别、出生地点、出生日期、签发地点、签发日期、有效期、签发机关、护照类型、国籍等关键信息,不过对于MRZCode1、MRZCode2 这两个字段可能识别的不太准确,比如图2.1和图2.2,对于图2.1,MRZCode1的中间字段 YANGBEN ,只识别出了YANGB(姓名拼音也一样),MRZCode2 则少了开头的E;对于图2.2,MRZCode2 少了最后的一个数字4。
C#的大佬。。。
赞