【人像特效】护照识别
让天涯 发布于2020-10 浏览:4951 回复:2
1
收藏

百度的护照识别技术支持对中国大陆护照个人资料页所有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。

收藏
点赞
1
个赞
共2条回复 最后由用户已被禁言回复于2022-04
#3鹿鼎记肯定回复于2020-11

C#的大佬。。。

0
#2七年期限回复于2020-11

0
TOP
切换版块