环境Windows7、vs2013
1、在百度AI官网下载百度OCR_SDK,解压;
2、编译jsoncpp、libcurl和openssl_lib库,将他们的include、lib、bin文件夹合并;
或者直接在csdn下载:已经编译好的三个库,jsoncpp版本比较老
3、新建vs2013项目,项目->属性->配置属性->vc++目录->包含目录文件添加百度OCR_SDK文件夹路径以及以上三个库合并后include的路径;项目->属性->配置属性->vc++目录->库目录添加三个库合并后的lib路径;项目->属性->配置属性->vc++目录->可执行文件目录添加三个库合并后的bin路径;
4、项目->属性->链接器->输入添加jsoncpp.lib、libcurl_debug.lib、libeay32.lib、ssleay32.lib;(具体看lib文件夹下的名称);
5、百度AI文字识别api接入通过以上链接学习如何获得百度许可;
6、百度AI文字识别快速入门。
头文件
#include"afx.h"
#include
#include"ocr.h"
#include
主函数:主要申请百度许可,并将识别结果交给ReadBack()/ReadFront()来处理。
int main()
{
string app_id = "你自己申请的id";
string api_key = "你自己申请的api_id";
string secret_key = "你自己申请的secret_key";
aip::Ocr client(app_id, api_key, secret_key);
Json::Value result;
std::string image;
aip::get_file_content("你自己的图片路径", &image);
//确定正面还是反面,注意正面和反面调用的函数不同
std::string id_card_side = "back";
// 调用身份证识别
result = client.idcard(image, id_card_side, aip::null);
// 如果有可选参数
std::map options;
options["detect_direction"] = "true";
options["detect_risk"] = "false";
// 带参数调用身份证识别
result = client.idcard(image, id_card_side, options);
//调用读取背面的函数
ReadBack(result);
return 0;
}
ReadBack()函数:用于读取身份证背面信息并输出
void ReadBack(Json::Value result)
{
Json::Value l;
string str;
int i = 0;
for each(l in result)
{
i++;
if (i == 4)
{
str = l.toStyledString();
}
}
int Counter = 0;
for (int i = 0; i < str.length(); i++)
{
string words = "";//记录字符串
string numbers = "";//记录数字
char word = str[i];//记录单个字符赋值给字符串
if (word == 'w')
{
words = "";
for (int j = 0; j < 5; j++)
{
word = str[i++];
words += word;
}
if (words == "words")
{
Counter++;
switch (Counter)
{
case 1:
{
cout << "失效日期:";
// Getresult1(i, str)函数用于读取纯数字信息或数字+字母信息
string fail_date = Getresult1(i, str);
cout << fail_date.c_str() << endl;
break;
}
case 2:
{
cout << "签发日期:";
string suc_date = Getresult1(i, str);
cout << suc_date << endl;
break;
}
case 3:
{
cout << "签发机关:";
// Getresult(i, str)函数用于读取带数字的字符串
string office = Getresult(i, str);
cout << office << endl;
break;
}
default:
break;
}
}
}
}
}
ReadFront()函数:用于读取并显示身份证正面信息
void ReadFront(Json::Value result)
{
Json::Value l;
string str;
int i = 0;
for each(l in result)
{
i++;
if (i == 4)
{
str = l.toStyledString();
}
}
int Counter = 0;
for (int i = 0; i < str.length(); i++)
{
string words = "";//记录字符串
string numbers = "";//记录数字
char word = str[i];//记录单个字符赋值给字符串
if (word == 'w')
{
words = "";
for (int j = 0; j < 5; j++)
{
word = str[i++];
words += word;
}
if (words == "words")
{
Counter++;
switch (Counter)
{
case 1:
{
cout << "住址:";
string address = Getresult(i, str);
cout << address.c_str() << endl;
break;
}
case 2:
{
cout << "公民身份证号码:";
string card_code = Getresult1(i, str);
cout << card_code << endl;
break;
}
case 3:
{
cout << "生日:";
string bir = Getresult1(i, str);
cout << bir << endl;
break;
}
case 4:
{
cout << "姓名:";
string name = Getresult(i, str);
cout << name << endl;
break;
}
case 5:
{
cout << "性别:";
string raice = Getresult(i, str);
cout << raice << endl;
break;
}
case 6:
{
cout << "民族:";
string gender = Getresult(i, str);
cout << gender << endl;
break;
}
default:
break;
}
}
}
}
}
Getresult()函数:用于读取带数字的字符串
string Getresult(int i, string str)
{
string Result;
string words = "";//记录字符串
string numbers = "";//记录数字
char word = str[i];//记录单个字符赋值给字符串
//计算words字符个数
int num = i + 5;//记录字符串前“的位置
int count = 0;//记录字符串长度
int six = 0;//判断某unicode编码是否超过六位;有则代表有数字
int wordNum = 0;//记录数字字符位数
bool flag = false;//记录字符中是否含有数字
int size = 0;//记录数字字符个数
int Size[10];//将字符位置存入数组
for (int i = 0; i < 10; i++)
{
Size[i] = -1;
}
map Num;
string inf = "";
for (int x = num;; x++)
{
if (str[x] != '\"')
{
count++;
word = str[x];
inf += word;
six++;
if (six % 6 == 0)
{
wordNum++;//记录字符位置
}
}
else
{
break;
}
//看是否字符中含有数字
if (six % 6 == 0 && str[x + 1] != '\\'&&str[x + 1] != '\"')
{
int z = x + 1;
int p = 0;//记录有几位数字
flag = true;
while (str[z] != '\\'&&str[z] != '\"')
{
char number = str[z];
numbers += number;
z++;
p++;
}
Num.insert(map::value_type(wordNum, numbers));
Size[size++] = wordNum;
numbers = "";
six -= p;//多加的字符串
}
}
if (flag = true)
{
map::iterator iter;
const char *buf = inf.c_str();
//UnEscape(buf)函数将unicode编码转化为汉字,但是并不支持带数字的字符串
string nLength = UnEscape(buf);
for (int i = 0; i < 10; i++)
{
if (Size[i] != -1)
{
iter = Num.find(Size[i]);
string val = iter->second;
nLength.insert(Size[i] * 2, val);
}
}
Result = nLength;
Num.erase(Num.begin(), Num.end());
}
else
{
const char *buf = inf.c_str();
string nLength = UnEscape(buf);
Result = nLength;
}
return Result;
}
Getresult1()函数:用于纯数字符串
string Getresult1(int i, string str)
{
string Result;
string words = "";//记录字符串
string numbers = "";//记录数字
char word = str[i];//记录单个字符赋值给字符串
//计算words字符个数
int num = i + 5;//记录字符串前“的位置
int count = 0;//记录字符串长度
int six = 0;//判断某unicode编码是否超过六位;有则代表有数字
int wordNum = 0;//记录数字字符位数
bool flag = false;//记录字符中是否含有数字
int size = 0;//记录数字字符个数
int Size[10];//将字符位置存入数组
for (int i = 0; i < 10; i++)
{
Size[i] = -1;
}
map Num;
string inf = "";
for (int x = num;; x++)
{
if (str[x] != '\"')
{
word = str[x];
inf += word;
}
else
{
break;
}
}
Result = inf;
return Result;
}
UnEscape()函数将unicode编码转化为汉字,但不支持含有数字的字符串
原文链接
std::string UnEscape(const char* strSource)
{
std::string strResult;
int nDestStep = 0;
int nLength = strlen(strSource);
if (!nLength || nLength < 6) return strResult;
char* pResult = new char[nLength + 1];
wchar_t* pWbuufer = nullptr;
if (!pResult)
{
pResult = NULL;
return strResult;
}
ZeroMemory(pResult, nLength + 1);
for (int nPos = 0; nPos < nLength; nPos++)
{
if (strSource[nPos] == '\\' && strSource[nPos + 1] == 'u')
{
char szTemp[5];
char szSource[5];
ZeroMemory(szTemp, 5);
ZeroMemory(szSource, 5);
CopyMemory(szSource, (char*)strSource + nPos + 2, 4);
sscanf_s(szSource, "%04X", szTemp);
CopyMemory(pResult + nDestStep, szTemp, 4);
nDestStep += 2;
}
}
nDestStep += 2;
pWbuufer = new wchar_t[nDestStep];
if (!pWbuufer)
{
delete[] pWbuufer;
pWbuufer = nullptr;
return strResult;
}
ZeroMemory(pWbuufer, nDestStep);
CopyMemory(pWbuufer, pResult, nDestStep);
delete[] pResult;
pResult = nullptr;
CHAR* MultPtr = nullptr;
int MultLen = -1;
//GB2312_ACP = 936
MultLen = ::WideCharToMultiByte(GB2312_ACP, WC_COMPOSITECHECK, pWbuufer, -1, NULL, NULL, NULL, NULL);
MultPtr = new CHAR[MultLen + 1];
if (MultPtr)
{
ZeroMemory(MultPtr, MultLen + 1);
::WideCharToMultiByte(GB2312_ACP, WC_COMPOSITECHECK, pWbuufer, -1, MultPtr, MultLen, NULL, NULL);
strResult = MultPtr;
delete[] MultPtr;
MultPtr = nullptr;
}
delete[] pWbuufer;
pWbuufer = nullptr;
return strResult;
}
至此完美解决了unicode转化为汉字的问题,第一次写博客难免有些疏漏,希望与各位互相学习,互相进步,互勉!