C++处理CRNN推理结果

一行文本的CRNN推理结果是一个列表,列表每个元素包含单个字符的字典索引和置信度,输出在json里形式如下:

{"char": [
	  {
	    "confidence": 0.9982025623321533,
	    "index": 1429,
	    "position": 1
	  },
	  {
	    "confidence": 0.6489381790161133,
	    "index": 1857,
	    "position": 5
	  },
	  {
	    "confidence": 0.9498909711837769,
	    "index": 3958,
	    "position": 9
	  },
	  {
	    "confidence": 0.11971486359834671,
	    "index": 2231,
	    "position": 14
	  },
	  {
	    "confidence": 0.9841734170913696,
	    "index": 1845,
	    "position": 18
	  },
	  {
	    "confidence": 0.1517036408185959,
	    "index": 2659,
	    "position": 22
	  },
	  {
	    "confidence": 0.7262901067733765,
	    "index": 5045,
	    "position": 35
	  },
	  {
	    "confidence": 0.956331729888916,
	    "index": 6476,
	    "position": 38
	  }
]}

本文将字典作为const string直接写在代码里:

std::string index2string_alphabet = "这是一个字符索引字典,全文大概20000字,包含中英文和各种外文符号"

然后通过index2string_alphabet 的下标依次索引上述index得到字符。

index2string_alphabet 是一个string,通过下表索引仅得到一个字符,但是index2string_alphabet 这个变量里不同的字其实占的字符位数不一样,如果是英文26个字母,占1位,如果是中文则占3位,所以在索引的时候需要知道当前字符是什么字符,占多少位,按规定位数取出来的字符,放到string里才可以正常显示,否则就是乱码。

由于代码文件是utf-8编码方式,对于UTF-8编码中的任意字节B:
如果B的第一位为0,则B为ASCII码,并且B独立的表示一个字符;
如果B的第一位为1,第二位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的一个字节,并且不为字符的第一个字节编码;
如果B的前两位为1,第三位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由两个字节表示;
如果B的前三位为1,第四位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由三个字节表示;
如果B的前四位为1,第五位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由四个字节表示;

通过二进制表示如下:
0xxxxxxx (一位的情况,为ASCII)
110xxxxx 10xxxxxx (110开头,代表两位)
1110xxxx 10xxxxxx 10xxxxxx (1110开头代表三位)
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (11110开头代表四位)
111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (111110开头,代表五位)
1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (1111110开头,代表六位)

所以解析逻辑就很清楚:
对于某一个带查询的index,初始化变量index0=0,逐位索引字典,根据上述规则跳过对应字符位数,但是index0只+1,直到index等于index0则找到对应字符。
代码如下:

int index0 = 0;
std::string result = "";
int index = 6555;
for(int i=0; i< index2string_alphabet.size();)
{
	std::string char_res;
	unsigned char q = index2string_alphabet[i];
	if ( q < 0x80 )
	{
		// std::cout<<"ascii char, index is "<<index2string_alphabet[i] <<std::endl;
		char_res += index2string_alphabet[i];
		i+=1;
		index0+=1;
	}
	else if ( q < 0xC0 )
	{
		//invalid char between 0x80 and 0xC0
		// std::cout<<"invalid char between 0x80 and 0xC0"<<std::endl;
		i+=1;
	}
	else if ( q < 0xE0 )
	{
		//two chars
		char_res += index2string_alphabet[i];
		char_res += index2string_alphabet[i+1];
		i+=2;
		index0+=1;
	}
	else if ( q < 0xF0 )
	{
		//three chars
		char_res += index2string_alphabet[i];
		char_res += index2string_alphabet[i+1];
		char_res += index2string_alphabet[i+2];
		i+=3;
		index0+=1;
	}
	else if ( q < 0xF8 )
	{
		//four chars
		char_res += index2string_alphabet[i];
		char_res += index2string_alphabet[i+1];
		char_res += index2string_alphabet[i+2];
		char_res += index2string_alphabet[i+3];
		i+=4;
		index0+=1;
	}
	else if ( q < 0xFC )
	{
		//five chars
		char_res += index2string_alphabet[i];
		char_res += index2string_alphabet[i+1];
		char_res += index2string_alphabet[i+2];
		char_res += index2string_alphabet[i+3];
		char_res += index2string_alphabet[i+4];
		i+=5;
		index0+=1;
	}
	else if ( q < 0xFE )
	{
		//6 chars
		char_res += index2string_alphabet[i];
		char_res += index2string_alphabet[i+1];
		char_res += index2string_alphabet[i+2];
		char_res += index2string_alphabet[i+3];
		char_res += index2string_alphabet[i+4];
		char_res += index2string_alphabet[i+5];
		i+=6;
		index0+=1;
	}
	else
	{
		//>=0xFE
		std::cout<<"invalid char >=0xFE"<<std::endl;
		i+=1;
	}
	if(index == index0)
	{
		result = char_res;
		break;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值