OCR 识别小工具(6)银行卡识别
busyboxs 发布于2020-12-20 浏览:1018 回复:0
0
收藏

功能介绍

对主流银行卡的卡号、有效期、发卡行、卡片类型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;
}

测试图像

 

 

 

 

 

 

 

 

收藏
点赞
0
个赞
TOP
切换版块