功能介绍
支持对户口本内常住人口登记卡的全部 22 个字段进行结构化识别,包括户号、姓名、与户主关系、性别、出生地、民族、出生日期、身份证号、本市县其他住址、曾用名、籍贯、宗教信仰、身高、血型、文化程度、婚姻状况、兵役状况、服务处所、职业、何时由何地迁往本市、何时由何地迁往本址、登记日期
应用场景
- 身份信息登记:使用户口本识别技术,对户口本上的姓名、性别、出生地、出生日期、身份证号等信息进行识别,可应用于新生儿建档、户口迁移、个人信贷申请、社会救济金申请等政务办理场景,使政务部门能够快速提取申请人身份信息完成核验和登记,提升办事效率
- 亲属关系登记:使用户口本识别技术,对户口本上的姓名、与户主关系、身份证号等信息进行识别,可应用于婚姻登记、遗产继承、子女入学登记等需证明亲属关系的民政业务办理场景,使政务部门能够快速提取申请人身份信息及关系完成登记,提升办事效率
接口描述
支持对户口本内常住人口登记卡的全部 22 个字段进行结构化识别,包括户号、姓名、与户主关系、性别、出生地、民族、出生日期、身份证号、本市县其他住址、曾用名、籍贯、宗教信仰、身高、血型、文化程度、婚姻状况、兵役状况、服务处所、职业、何时由何地迁往本市、何时由何地迁往本址、登记日期
请求说明
- HTTP 方法: POST
- 请求 URL: https://aip.baidubce.com/rest/2.0/ocr/v1/household_register
- URL参数: access_token
- Header 参数: Content-Type = application/x-www-form-urlencoded
- Body 参数:见下表
返回说明
返回参数如下表:
返回示例如下:
{
"log_id": 1301870459,
"words_result": {
"BirthAddress": {
"words": "河南洛阳市郊区"
},
"Birthday": {
"words": "2016-07-28"
},
"CardNo": {
"words": "410311201607282825"
},
"Name": {
"words": "孙翌晨"
},
"Nation": {
"words": "汉族"
},
"Relationship": {
"words": "户主"
},
"Sex": {
"words": "男"
},
},
"words_result_num": 7
}
C++ 代码实现调用
这里假设前置准备已经做好了,如果没有,请阅读以下文章;如果有,则直接跳过;
(基础篇 01)在控制台创建对应的应用 https://yangshun.win/blogs/dea770b9/
(基础篇 02)Windows 下使用 Vcpkg 配置百度 AI 图像识别 C++开发环境(VS2017) https://yangshun.win/blogs/3b103680/
(基础篇 03)C++ 获取 access token https://yangshun.win/blogs/49f400d2/
(基础篇 04)C++ base64 编解码原理及实现 https://yangshun.win/blogs/3f2fcf2e/
下面的代码中部分函数定义在 util.h 和 util.cpp 中
screenshot/functions/util.h https://github.com/busyboxs/screenshot/blob/master/functions/util.h
screenshot/functions/util.cpp https://github.com/busyboxs/screenshot/blob/master/functions/util.cpp
为了方便,首先根据返回参数定义了一个结构体,该结构体包括了返回参数中的参数,如下:
struct HouseholdInfo
{
uint64_t logID{};
uint32_t resultNumber{};
std::map wordsResult{};
void print()
{
std::cout << "log id: " << logID << '\n';
std::cout << "words result number: " << resultNumber << '\n';
for (auto& [name, res] : wordsResult)
{
std::cout << "\t" << UTF8ToGB(name.c_str()) << ": ";
res.print();
}
}
};
然后定义了一个类来调用接口并获取结果
class Household
{
public:
Household();
~Household();
Json::Value request(std::string imgBase64, std::map& options);
void getResult(HouseholdInfo& result);
private:
Json::Value m_obj;
std::string m_url;
// file to save token key
std::string m_filename;
inline static std::map resultName
{
{"Name", u8"姓名"},
{"Relationship", u8"户主或与户主关系"},
{"Sex", u8"性别"},
{"BirthAddress", u8"出生地"},
{"Nation", u8"民族"},
{"Birthday", u8"生日"},
{"CardNo", u8"身份证号"},
{"HouseholdNum", u8"户号"},
{"FormerName", u8"曾用名"},
{"Hometown", u8"籍贯"},
{"OtherAddress", u8"本市(县)其他住址"},
{"Belief", u8"宗教信仰"},
{"Height", u8"身高"},
{"BloodType", u8"血型"},
{"Education", u8"文化程度"},
{"MaritalStatus", u8"婚姻状况"},
{"VeteranStatus", u8"兵役状况"},
{"WorkAddress", u8"服务处所"},
{"Career", u8"职业"},
{"WWToCity", u8"何时由何地迁来本市(县)"},
{"WWHere", u8"何时由何地迁往本址"},
{"Date", u8"登记日期"}
};
};
类中的私有成员 m_obj 表示返回结果对应的 json 对象。m_url 表示请求的 url,m_filename 表示用于存储 access token 的文件的文件名。
request 函数输入请求图像的 base64 编码以及请求参数,返回一个 json 对象,json 对象中包含请求的结果。
getResult 将请求的结果进行解析为自定义的结构体数据类型。以便用于后序的打印。
由于请求返回的 json 中各字段是用的英文,所以定义一个静态 Map 将英文映射为中文。
完整代码如下
Household.h 代码如下: screenshot/functions/Household.h https://github.com/busyboxs/screenshot/blob/master/functions/Household.h
#pragma once
#include
#include
#include
#include
#include
#include "util.h"
#include "customVariables.h"
struct HouseholdInfo
{
uint64_t logID{};
uint32_t resultNumber{};
std::map wordsResult{};
void print()
{
std::cout << "log id: " << logID << '\n';
std::cout << "words result number: " << resultNumber << '\n';
for (auto& [name, res] : wordsResult)
{
std::cout << "\t" << UTF8ToGB(name.c_str()) << ": ";
res.print();
}
}
};
class Household
{
public:
Household();
~Household();
Json::Value request(std::string imgBase64, std::map& options);
void getResult(HouseholdInfo& result);
private:
Json::Value m_obj;
std::string m_url;
// file to save token key
std::string m_filename;
inline static std::map resultName
{
{"Name", u8"姓名"},
{"Relationship", u8"户主或与户主关系"},
{"Sex", u8"性别"},
{"BirthAddress", u8"出生地"},
{"Nation", u8"民族"},
{"Birthday", u8"生日"},
{"CardNo", u8"身份证号"},
{"HouseholdNum", u8"户号"},
{"FormerName", u8"曾用名"},
{"Hometown", u8"籍贯"},
{"OtherAddress", u8"本市(县)其他住址"},
{"Belief", u8"宗教信仰"},
{"Height", u8"身高"},
{"BloodType", u8"血型"},
{"Education", u8"文化程度"},
{"MaritalStatus", u8"婚姻状况"},
{"VeteranStatus", u8"兵役状况"},
{"WorkAddress", u8"服务处所"},
{"Career", u8"职业"},
{"WWToCity", u8"何时由何地迁来本市(县)"},
{"WWHere", u8"何时由何地迁往本址"},
{"Date", u8"登记日期"}
};
};
void HouseholdTest();
HouseholdInfo HouseholdDetect(std::string imgPath);
Household.cpp 代码如下: screenshot/functions/Household.cpp https://github.com/busyboxs/screenshot/blob/master/functions/Household.cpp
#include "Household.h"
Household::Household()
{
m_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/household_register";
m_filename = "tokenKey";
}
Household::~Household()
{
}
Json::Value Household::request(std::string imgBase64, std::map& options)
{
std::string response;
Json::Value obj;
std::string token;
// 1. get HTTP post body
std::string body;
mergeHttpPostBody(body, imgBase64, options);
// 2. get HTTP url with access token
std::string url = m_url;
getHttpPostUrl(url, m_filename, token);
// 3. post request, response store the result
int status_code = httpPostRequest(url, body, response);
if (status_code != CURLcode::CURLE_OK) {
obj["curl_error_code"] = status_code;
m_obj = obj;
return obj; // TODO: maybe should exit
}
// 4. make string to json object
generateJson(response, obj);
// if access token is invalid or expired, we will get a new one
if (obj["error_code"].asInt() == 110 || obj["error_code"].asInt() == 111) {
token = getTokenKey();
writeFile(m_filename, token);
return request(imgBase64, options);
}
m_obj = obj;
//checkErrorWithExit(obj);
return obj;
}
void Household::getResult(HouseholdInfo& result)
{
if (m_obj.get("error_code", "null"))
{
result.wordsResult["error_code"].words = m_obj.get("error_code", "null").asString();
result.wordsResult["error_msg"].words = m_obj.get("error_msg", "null").asString();
return;
}
result.logID = m_obj["log_id"].asUInt64();
result.resultNumber = m_obj["words_result_num"].asUInt();
Json::Value::Members keys = m_obj["words_result"].getMemberNames();
for (auto it = keys.begin(); it != keys.end(); ++it)
{
WordsOnlyPart resultPart;
getWordsOnlyPart(m_obj["words_result"][*it], resultPart);
result.wordsResult[resultName[*it].c_str()] = resultPart;
}
}
void HouseholdTest()
{
std::string img_file = "./images/household_test.png";
std::string out;
readImageFile(img_file.c_str(), out);
std::string img_base64 = base64_encode(out.c_str(), (int)out.size());
// set options
std::map options;
Json::Value obj;
Household householdObj;
HouseholdInfo result;
obj = householdObj.request(img_base64, options);
householdObj.getResult(result);
result.print();
}
HouseholdInfo HouseholdDetect(std::string imgPath)
{
std::string out;
readImageFile(imgPath.c_str(), out);
std::string img_base64 = base64_encode(out.c_str(), (int)out.size());
// set options
std::map options;
Json::Value obj;
Household householdObj;
HouseholdInfo result;
obj = householdObj.request(img_base64, options);
householdObj.getResult(result);
return result;
}
运行结果
测试图像
https://github.com/busyboxs/screenshot/releases/tag/1.0
你好!请问在哪下载工具?
666