解决百度AI身份证识别显示unicode码而不显示汉字问题

环境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  
using namespace std;
#define GB2312_ACP 936

主函数:主要申请百度许可,并将识别结果交给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转化为汉字的问题,第一次写博客难免有些疏漏,希望与各位互相学习,互相进步,互勉!

你可能感兴趣的:(文字识别)