一、功能介绍
支持对二代居民身份证正反面所有8个字段进行结构化识别,包括姓名、性别、民族、出生日期、住址、身份证号、签发机关、有效期限,识别准确率超过99%。
二、应用场景
远程身份认证
使用身份证识别和人脸识别技术,实现对用户身份信息的结构化识别和录入,可应用于金融、保险、电商、O2O、直播等场景,满足对用户、商家、主播等进行实名认证的需求,有效降低用户输入成本,控制业务风险。
三、使用攻略
说明:本文采用C# 语言,开发环境为.Net Core 2.1,采用在线API接口方式实现。
(1)平台接入
登陆 百度智能云-管理中心 创建 “文字识别”应用,获取 “API Key ”和 “Secret Key”:https://console.bce.baidu.com/ai/?_=1568700058540&fromai=1#/ai/ocr/overview/index
(2)接口文档
文档地址:https://ai.baidu.com/docs#/OCR-API/7e4792c7
接口描述:支持对大陆居民二代身份证正反面的所有字段进行结构化识别,包括姓名、性别、民族、出生日期、住址、身份证号、签发机关、有效期限;同时,支持对用户上传的身份证图片进行图像风险和质量检测,可识别图片是否为复印件或临时身份证,是否被翻拍或编辑,是否存在正反颠倒、模糊、欠曝、过曝等质量问题。
请求说明
HTTP方法:POST
请求URL:https://aip.baidubce.com/rest/2.0/ocr/v1/idcard
URL参数:
Header如下:
Body中放置请求参数,参数详情如下:
请求参数
返回说明
返回参数
返回示例:
{
"log_id": 2648325511,
"direction": 0,
"image_status": "normal",
"idcard_type": "normal",
"edit_tool": "Adobe Photoshop CS3 Windows",
"words_result": {
"住址": {
"location": {
"left": 267,
"top": 453,
"width": 459,
"height": 99
},
"words": "南京市江宁区弘景大道3889号"
},
"公民身份号码": {
"location": {
"left": 443,
"top": 681,
"width": 589,
"height": 45
},
"words": "330881199904173914"
},
"出生": {
"location": {
"left": 270,
"top": 355,
"width": 357,
"height": 45
},
"words": "19990417"
},
"姓名": {
"location": {
"left": 267,
"top": 176,
"width": 152,
"height": 50
},
"words": "伍云龙"
},
"性别": {
"location": {
"left": 269,
"top": 262,
"width": 33,
"height": 52
},
"words": "男"
},
"民族": {
"location": {
"left": 492,
"top": 279,
"width": 30,
"height": 37
},
"words": "汉"
}
},
"words_result_num": 6
}
(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 = HostingEnvironment.WebRootPath;//wwwroot目录
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(webRootPath, "Uploads", "BaiduAIs")),
RequestPath = "/BaiduAIs"
});
(3-2-2-1)前台代码:
由于html代码无法原生显示,只能简单说明一下:
主要是一个form表单,需要设置属性enctype="multipart/form-data",否则无法上传图片;
form表单里面有两个控件:
一个Input:type="file",asp-for="FileUpload" ,上传图片;
一个Input:type="submit",asp-page-handler="IDCard" ,提交识别。
一个img:src="@Model.curPath",显示需要识别的图片。
最后显示后台 msg 字符串列表信息,如果需要输出原始Html代码,则需要使用@Html.Raw()函数。
(3-2-2-2) 后台代码:
[BindProperty]
public IFormFile FileUpload { get; set; }
[BindProperty]
public string ImageUrl { get; set; }
private readonly IHostingEnvironment HostingEnvironment;
public List msg = new List();
public string curPath { get; set; }
public OCRSearchModel(IHostingEnvironment hostingEnvironment)
{
HostingEnvironment = hostingEnvironment;
}
string BaiduAI_OCRPath="Uploads//BaiduAIs//";
string BaiduAI_OCRUrl="/BaiduAIs/";
string OCR_API_KEY="你的API KEY";
string OCR_SECRET_KEY="你的SECRET KEY";
public async Task OnPostIDCardAsync()
{
if (FileUpload is null)
{
ModelState.AddModelError(string.Empty, " 请先选择本地图片!");
}
if (!ModelState.IsValid)
{
return Page();
}
msg = new List();
string webRootPath = HostingEnvironment.WebRootPath;//wwwroot目录
string fileDir = Path.Combine(webRootPath, BaiduAI_OCRPath);
string 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, "front", "true");
DateTime endTime = DateTime.Now;
TimeSpan ts = endTime - startTime;
JObject jo = (JObject)JsonConvert.DeserializeObject(result);
try
{
msg.Add("身份证识别结果(耗时" + ts.TotalSeconds + "秒):\n");
string imageStatus = jo["image_status"].ToString();
msg.Add("状态:" + GetIDCardStatus(imageStatus));
if (imageStatus.Equals("normal"))
{
msg.Add("类型:" + GetIDCardRiskType(jo["risk_type"].ToString()));
if (jo["edit_tool"] != null)
{
msg.Add("是否被编辑:" + jo["edit_tool"].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());
}
}
catch (Exception e)
{
msg.Add(result);
}
return Page();
}
///
/// 上传文件,返回文件名
///
/// 文件上传控件
/// 文件绝对路径
///
public static async Task UploadFile(IFormFile formFile, string fileDir)
{
if (!Directory.Exists(fileDir))
{
Directory.CreateDirectory(fileDir);
}
string extension = Path.GetExtension(formFile.FileName);
string imgName = Guid.NewGuid().ToString("N") + extension;
var filePath = Path.Combine(fileDir, imgName);
using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
await formFile.CopyToAsync(fileStream);
}
return imgName;
}
///
/// 返回图片的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字符串
///
/// 图片base64编码
/// API Key
/// Secret Key
/// 身份证证面(front:含照片的一面;back:带国徽的一面)
/// 是否开启身份证风险类型(身份证复印件、临时身份证、身份证翻拍、修改过的身份证)功能,默认不开启,即:false。可选值:true-开启;false-不开启
///
public static string GetOCRJson( string strbaser64, string clientId, string clientSecret, string idCardSide = null, string detectRisk = null)
{
string token = GetAccessToken(clientId, clientSecret);
string host = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?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(strbaser64);
if (!string.IsNullOrEmpty(idCardSide))
{
str += "&id_card_side=" + idCardSide;
}
if (!string.IsNullOrEmpty(detectRisk))
{
str += "&detect_risk=" + detectRisk;
}
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;
}
///
/// 返回身份证识别结果
///
/// 身份证识别结果值
///
public static string GetIDCardStatus(string key)
{
Dictionary GestureDic = new Dictionary();
GestureDic.Add("normal", "正常");
GestureDic.Add("reversed_side", "身份证正反面颠倒");
GestureDic.Add("non_idcard", "上传的图片中不包含身份证");
GestureDic.Add("blurred", "身份证模糊");
GestureDic.Add("other_type_card", "其他类型证照");
GestureDic.Add("over_exposure", "身份证关键字段反光或过曝");
GestureDic.Add("over_dark", "身份证欠曝(亮度过低)");
GestureDic.Add("unknown", "未知状态");
if (GestureDic.ContainsKey(key))
{
return GestureDic[key];
}
else
{
return key;
}
}
///
/// 返回身份证识别类型
///
/// 身份证识别类型值
///
public static string GetIDCardRiskType(string key)
{
Dictionary GestureDic = new Dictionary();
GestureDic.Add("normal", "正常");
GestureDic.Add("copy", "复印件");
GestureDic.Add("temporary", "临时身份证");
GestureDic.Add("screen", "翻拍");
GestureDic.Add("unknown", "其他未知情况");
if (GestureDic.ContainsKey(key))
{
return GestureDic[key];
}
else
{
return key;
}
}
四、效果测试
1、页面:
2、识别结果:
五、测试结果及建议
从测试结果可知,百度的身份证识别结果相当准确,并能够识别出是否是复印件、翻拍等类型,识别速度也很快,基本上可以在1秒左右识别好。
如果能够根据图片自动识别出是身份证正面还是身份证反面,并识别出相应的字段就更加好了。
再进一步,一张图片,同时含有身份证的正反面,能一次识别出正反面的字段,或一张图片,包含多张身份证正反面,一次识别出所有身份证的信息,使用起来就更加方便。
此外,如果能够根据识别的身份证号码,结合公安信息系统,识别出该身份证的真伪、识别出该身份证用户是否被列入失信名单、黑名单等,就更有实际使用价值了。
身份证使用的场景还是很多的,去银行办理业务、去公司应聘、去有实名认证的要求的网站注册账户等,都会需要输入身份证信息,采用身份证识别技术,简单一拍身份证,就能输入完成,可以大大降低业务员/用户的输入操作,提高办公效率。
感谢您的反馈和建议!
您提到的自动识别身份证正反面以及同一页多张身份证的识别能力,目前正在开发中,希望可以在第4季度上线供大家使用。
根据身份证号码进行公安校验,目前可通过“公安验证”接口判断证件号码与名称是否匹配,单失信名单、黑名单等信息暂时未开放,因此无法提供相关功能。