功能介绍
对主流银行卡的卡号、有效期、发卡行、卡片类型4个关键字段进行结构化识别,识别准确率超过99%
应用场景
- 金融远程身份认证:综合应用银行卡和身份证识别技术,结构化识别录入客户银行账户和身份信息,可应用于金融场景用户实名认证,有效降低用户输入成本,提升用户体验
- 电商支付绑卡:接入银行卡识别API服务实现拍照识别,或集成移动端离线SDK实现设备端扫描识别,结构化返回卡号、卡片类型等信息,有效提升信息录入的准确性,并降低用户手工输入成本,提升用户使用体验
特色优势
- 字段齐全:对银行卡号、有效期两个基本字段信息进行结构化识别,并根据识别到的卡号判断发卡行及卡片类型,满足各类相关业务需求
- 准确率高:依托百度优秀的图像处理技术和海量优质数据,可识别各种角度的银行卡照片,识别准确率高
- 服务稳定:依托百度云技术实力,提供高可靠性、弹性可伸缩、高并发承载的文字识别公有云服务,服务可用性高达99.99%
接口描述
支持对主流银行卡的卡号、有效期、发卡行、卡片类型4个关键字段进行结构化识别,识别准确率超过99%。
请求说明
- HTTP 方法: POST
- 请求 URL: https://aip.baidubce.com/rest/2.0/ocr/v1/bankcard
- URL参数: access_token
- Header 参数: Content-Type = application/x-www-form-urlencoded
- Body 参数:见下表
返回说明
返回参数如下表:
返回示例如下:
{
"log_id": 144718895115129615,
"result": {
"bank_card_number": "3568 8900 8000 0005",
"valid_date": "07/21",
"bank_card_type": 2,
"bank_name": "招商银行"
}
}
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 BankCardInfo
{
uint64_t logID{};
uint32_t direction{};
std::map resultMap{};
void print()
{
std::cout << "log id: " << logID << '\n';
std::cout << "direction: " << direction << '\n';
for (auto& [name, res] : resultMap)
{
std::cout << UTF8ToGB(name.c_str()) << ": " << UTF8ToGB(res.c_str()) << '\n';
}
}
};
然后定义了一个类来调用接口并获取结果
class BankCard
{
public:
BankCard();
~BankCard();
Json::Value request(std::string imgBase64, std::map& options);
void getResult(BankCardInfo& result);
private:
Json::Value m_obj;
std::string m_url;
// file to save token key
std::string m_filename;
inline static std::vector cardTypes{
u8"不能识别",
u8"借记卡",
u8"贷记卡",
u8"准贷记卡",
u8"预付费卡"
};
inline static std::map resultName{
{"bank_card_number", u8"银行卡卡号"},
{"valid_date", u8"有效期"},
{"bank_card_type", u8"银行卡类型"},
{"bank_name", u8"银行名称"}
};
};
类中的私有成员 m_obj 表示返回结果对应的 json 对象。m_url 表示请求的 url,m_filename 表示用于存储 access token 的文件的文件名。
request 函数输入请求图像的 base64 编码以及请求参数,返回一个 json 对象,json 对象中包含请求的结果。
getResult 将请求的结果进行解析为自定义的结构体数据类型。以便用于后序的打印和绘图等。
完整代码如下
bankcard.h 代码如下: screenshot/functions/bankcard.h
#pragma once
#include
#include
#include
#include
#include
#include
#include "util.h"
#include "customVariables.h"
struct BankCardInfo
{
uint64_t logID{};
uint32_t direction{};
std::map resultMap{};
void print()
{
std::cout << "log id: " << logID << '\n';
std::cout << "direction: " << direction << '\n';
for (auto& [name, res] : resultMap)
{
std::cout << UTF8ToGB(name.c_str()) << ": " << UTF8ToGB(res.c_str()) << '\n';
}
}
};
class BankCard
{
public:
BankCard();
~BankCard();
Json::Value request(std::string imgBase64, std::map& options);
void getResult(BankCardInfo& result);
private:
Json::Value m_obj;
std::string m_url;
// file to save token key
std::string m_filename;
inline static std::vector cardTypes{
u8"不能识别",
u8"借记卡",
u8"贷记卡",
u8"准贷记卡",
u8"预付费卡"
};
inline static std::map resultName{
{"bank_card_number", u8"银行卡卡号"},
{"valid_date", u8"有效期"},
{"bank_card_type", u8"银行卡类型"},
{"bank_name", u8"银行名称"}
};
};
void BankCardTest();
BankCardInfo BandCardDetect(std::string imgPath);
bankcard.cpp 代码如下: screenshot/functions/bankcard.cpp
#include "bankcard.h"
BankCard::BankCard()
{
m_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/bankcard";
m_filename = "tokenKey";
}
BankCard::~BankCard()
{
}
Json::Value BankCard::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 BankCard::getResult(BankCardInfo& result)
{
if (m_obj.get("error_code", "null"))
{
result.resultMap["error_code"] = m_obj.get("error_code", "null").asString();
result.resultMap["error_msg"] = m_obj.get("error_msg", "null").asString();
return;
}
result.logID = m_obj["log_id"].asUInt64();
result.direction = m_obj["direction"].asUInt();
Json::Value::Members keys = m_obj["result"].getMemberNames();
for (auto it = keys.begin(); it != keys.end(); ++it)
{
if (auto type = *it; type == "bank_card_type")
{
result.resultMap[resultName[*it].c_str()] = cardTypes[m_obj["result"][*it].asInt()];
}
else
{
result.resultMap[resultName[*it].c_str()] = m_obj["result"][*it].asString();
}
}
}
void BankCardTest()
{
std::string img_file = "./images/bandcard_test.jpg";
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;
BankCard bandcardObj;
BankCardInfo result;
obj = bandcardObj.request(img_base64, options);
bandcardObj.getResult(result);
result.print();
}
BankCardInfo BandCardDetect(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;
BankCard bandcardObj;
BankCardInfo result;
obj = bandcardObj.request(img_base64, options);
bandcardObj.getResult(result);
return result;
}
测试图像