精华内容
下载资源
问答
  • 常见的文字解码方式
    千次阅读
    2021-11-29 00:35:50

    Java的编码解码

    前言:

    介绍编码和解码之前,我们先了解一下我们的计算机,计算机中存储数据的具体单位是存储单元,

    一个最小的信息单元就是“”(bit),一"位"只能表示0和1中的一个,即一个二进制位;

    字节”(Byte):是由相连8个位组成的信息存储单位它是目前计算机最基本的存储单位,一个字节通常可以存储一个字符(如字母、数字等)。只有字节才有地址的概念。对一种计算机的存储设备以字节为单位赋予的地址称为字节编址;也是目前计算机最基本的存储单元编址;

    java的基本数据类型:

    数据类型bit数说明
    byte8位最大存储数据量是255,存放的数据范围是-128~127之间
    short16位最大数据存储量是65536,数据范围是-32768~32767之间
    int32位最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1
    long64位最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1
    float32位数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F
    double64位数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加
    boolean只有true和false两个取值
    char16位存储Unicode码,用单引号赋值

    进入今天的正题:

    首先要知道编码和解码是char和byte两个数据类型之间转换中产生的;

    为什么要编码?

    最直接的回答就是防止我们的中文和一些特殊字符出现乱码的现象;

    详细点讲就是计算机只能识别0和1两个数字,所有的符号和文字都必须经过转换编码才能“翻译”成我们计算机认识的“语言”,相反也是,我们要想显示出我们能读懂的“语言”也必须要进行相应的解码才能从计算机中显示出我们能看懂的文字;

    总的来说编码的原因有:

    1. 计算机中存储信息的最小单元是一个字节即 8 个 bit,所以能表示的字符范围是 0~255 个(2的8次方)
    2. 人类要表示的符号太多,每个符号无法用一个字节来完全表示
    3. 要解决这个矛盾必须需要一个新的数据结构 char,从 char 到 byte 必须编码

    如何编码和解码呢?

    那就是通过一种特定的编码格式转换,其实现在有很多中的编码格式,只要让计算机按照规定的编码格式进行转化,就可以显示成我们自己的字符。那现在就介绍一下目前最常见的一些编码格式;

    首先我们要知道编码和编码格式是有区别的?
    编码就是一个编号(数字)到字符的一种映射关系,是一种一对一的映射关系。Unicode和ASCII 就是属于两种编码,但这两种编码能编码的范围不同,Unicode 能编码的范围要更大一些,几乎能覆盖现存的所有字符(Java语言使用的就是该码表);

    ASCII码
    在计算机种中,1 字节对应 8 位二进制数,而每位二进制数有 0、1 两种状态,因此 1 字节可以组合出 256 种状态。如果这 256 中状态每一个都对应一个符号,就能通过 1 字节的数据表示 256 个字符。美国人于是就制定了一套编码(其实就是个字典),描述英语中的字符和这 8 位二进制数的对应关系,这被称为 ASCII 码。

    ASCII 码一共定义了 128 个字符,例如大写的字母 A 是 65(这是十进制数,对应二进制是0100 0001)。这 128 个字符只使用了 8 位二进制数中的后面 7 位,最前面的一位统一规定为 0。

    Unicode
    Unicode 只是一个字符集,规定了符合对应的二进制代码,至于这个二进制代码如何存储则没有任何规定。它的想法很简单,就是为每个字符规定一个用来表示该字符的数字,仅此而已。

    Unicode编码方案

    之前提到,Unicode 没有规定字符对应的二进制码如何存储。以汉字“汉”为例,它的 Unicode 码点是 0x6c49,对应的二进制数是 110110001001001,二进制数有 15 位,这也就说明了它至少需要 2 个字节来表示。可以想象,在 Unicode 字典中往后的字符可能就需要 3 个字节或者 4 个字节,甚至更多字节来表示了。

    这就导致了一些问题,计算机怎么知道你这个 2 个字节表示的是一个字符,而不是分别表示两个字符呢?这里我们可能会想到,那就取个最大的,假如 Unicode 中最大的字符用 4 字节就可以表示了,那么我们就将所有的字符都用 4 个字节来表示,不够的就往前面补 0。这样确实可以解决编码问题,但是却造成了空间的极大浪费,如果是一个英文文档,那文件大小就大出了 3 倍,这显然是无法接受的。
    于是,为了较好的解决 Unicode 的编码问题, UTF-8 和 UTF-16 两种当前比较流行的编码方式诞生了。当然还有一个 UTF-32 的编码方式,也就是上述那种定长编码,字符统一使用 4 个字节,虽然看似方便,但是却不如另外两种编码方式使用广泛。

    对于编码格式目前最常见的是UTF-8、GBK,它们都是用来序列化或存储 Unicode 编码的数据的,但是分别是2中不同的格式,他们都是 Unicode 的实现方式,当然也还有很多,这里就先介绍这两种啦。

    • GBK

      全称叫《汉字内码扩展规范》,是国家技术监督局为 windows95 所制定的新的汉字内码规范,它的出现是为了扩展 GB2312,加入更多的汉字,它的编码范围是 8140~FEFE(去掉 XX7F)总共有 23940 个码位,它能表示 21003 个汉字,它的编码是和 GB2312 兼容的,也就是说用 GB2312 编码的汉字可以用 GBK 来解码,并且不会有乱码。

    • UTF-8

      UTF-8 采用了一种变长技术,每个编码区域有不同的字码长度。不同类型的字符可以是由 1~6 个字节组成。

    编码规则:

    1. 如果一个字节,最高位(第 8 位)为 0,表示这是一个 ASCII 字符(00 - 7F)。可见,所有 ASCII 编码已经是 UTF-8 了。
    2. 如果一个字节,以 11 开头,连续的 1 的个数暗示这个字符的字节数,例如:110xxxxx 代表它是双字节 UTF-8 字符的首字节。
    3. 如果一个字节,以 10 开始,表示它不是首字节,需要向前查找才能得到当前字符的首字节

    使用utf-8进行编码解码
    “汉”的 Unicode 码点是 0x6c49(110 1100 0100 1001),通过上面的对照表可以发现,0x0000 6c49 位于第三行的范围,那么得出其格式为 1110xxxx 10xxxxxx 10xxxxxx。接着,从“汉”的二进制数最后一位开始,从后向前依次填充对应格式中的 x,多出的 x 用 0 补上。这样,就得到了“汉”的 UTF-8 编码为 11100110 10110001 10001001,转换成十六进制就是 0xE6 0xB7 0x89。

    解码的过程也十分简单:如果一个字节的第一位是 0 ,则说明这个字节对应一个字符;如果一个字节的第一位1,那么连续有多少个 1,就表示该字符占用多少个字节。

    java中编解码场景

    流读取文件,其中就存在着字符与字节之间的转换; InputStreamReader 类就是关联字节到字符的桥梁,它负责在 I/O 过程中处理读取字节到字符的转换;

    // 创建指定字符集的 InputStreamReader
    InputStreamReader(InputStream in, String CharsetName)
    // 创建使用指定字符集的 OutputStreamWriter
    OutputStreamWriter(OutputStream out, String CharsetName)
    

    处理字符串编码问题

    //获取utf-8对应的的字符集
    Charset charset = Charset.forName("utf-8");
    //将字符串通过utf-8进行编码转化成字节
    byte[] bytes = str.getBytes(charset);
    //再将字节根据相同的编码格式进行解码
    String string = new String(bytes, "utf-8");
    System.out.println(string);
    

    处理请求参数传递编码问题

    URLEncoder.encode(strUri, "UTF-8");
    URLDecoder.decode(strUri, "UTF-8");
    

    值得一看的相关文章:https://blog.csdn.net/troyaninpc/article/details/79476751

    下一篇:session会话理解

    更多相关内容
  • js对文字进行编码涉及3个函数:escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decodeURIComponent
  • 1.基于FFmpeg实现rtsp访问 2.编解码音视频 3.视频流添加文字 4.音视频同步mp4 5.兼容Windows和Linux
  • 文本解码时,每一个时间步不断的解码得到当前的文字,当前文字到底生成候选词典(vocab)中的哪一个,需要一定的策略,显然遍历的复杂度较高;例如,如果时间步是T=500,候选vocab容量为5000,则随机遍历复杂度可达到${...

    在Seq2Seq模型生成文本的decoder端,假设处于第t步,则生成的结果依赖于encoder端对输入句子的向量hidden state和先前生成的t-1个字;我们会得到一个第t个字的向量,然后通过softmax的方式得到该步时的整个vocabulary的概率分布。当前字到底生成候选词典(vocab)中的哪一个,需要一定的策略,显然遍历的复杂度较高,如何选取也会影响生成文本的质量,一些常见的优化方法如下。

    一、贪心搜索
    即第t+1时间步取一个词使得第1步到第t+1的概率最大,然后依次进行递进搜索。例如下图,每一个时间步都取出对应使得概率最大的词(可以联系语言模型的定义),生成了序列[A,B,C]
    在这里插入图片描述
    二、Beam Search
    又称集束搜索,Beam Search(集束搜索)是一种启发式图搜索算法,通常用在图的解空间比较大的情况下,为了减少搜索所占用的空间和时间,在每一步深度扩展的时候,剪掉一些质量比较差的结点,保留下一些质量较高的结点。这样减少了空间消耗,并提高了时间效率,但缺点就是有可能存在潜在的最佳方案被丢弃,因此Beam Search算法是不完全的,一般用于解空间较大的系统中。

    相对贪心策略绝大的搜索空间,我们每次选制定的个数,num_beams个;num_beams=1时集束搜索就退化成了贪心搜索;num_beams=2,即,每个时间步都会保留到当前步为止条件概率最优的2个序列。然后依次往前递推;

    如下图所示,假设字典vocab是之含有A,B,C,D,E的大小为5的字典;第一步有两个候选 A,C概率最高先被选出;第二步有AA,AB,AC,AD,AE,CA,CB,…,CD,CE共10种可能,依然只选概率最高的两种,如下图是AB,CE被选出,因为这两个概率最高

    在这里插入图片描述
    三、随机采样
    虽然Beam Search优化了空间效率,高效的选取了一些结点,但还是容易生成重复、无意义的文本,这点在做实验中比较容易遇到。目前提出了随机采样(sampling)的做法对Beam Search做出一些改进;候选字有一定的概率分布,通过一些策略提高生成文本的质量。比较常见的做法如下:

    1.Temperature Sampling

    在softmax计算过程中引入温度参数 t来改变vocabulary probability distribution,使其更偏向high probability words
    P ( x ∣ x 1 : t − 1 ) = e x p ( u t / t ) ∑ t ′ e x p ( u t ′ / t ) ) P(x|x_{1:t-1})=\frac{exp(u_{t}/t)}{\sum _{{t}'}exp(u_{{t}'}/t))} P(xx1:t1)=texp(ut/t))exp(ut/t),其中t的取值在[0,1)之间。

    2.Top-k 采样
    在解码过程中从 P ( x ∣ x 1 : i − 1 ) P(x|x_{1:i-1}) P(xx1:i1)分布中,取概率最高的k个tokens,将其概率求和记为sum-topk。概率重新分布转化如下:上述这k个tokens分别除以概率和sum-topk得到各自新的概率,其余token概率变为0。Top-k Sampling存在的问题是,常数k是给定的值,k设置过小则会容易生成更平淡或泛的句子。当k很大的时候,候选集合会包含一些不合适的token。下面的核采样方法则会有更动态的选取策略。

    3.NUCLEUS SAMPLING 方法,或记为Top-p方法
    主要的想法根据概率的分布来决定一个可以用来被采样的token集合。给定所有候选tokenx的分布 P ( x ∣ x 1 : i − 1 ) P(x|x_{1:i-1}) P(xx1:i1),这样的满足top-p条件的集合 V ( p ) ⊂ V V^{(p)}\subset V V(p)V
    s u m x ∈ V ( p ) P ( x ∣ x 1 : i − 1 ) ≥ p sum_{x\in V^{(p)}}P(x|x_{1:i-1})\geq p sumxV(p)P(xx1:i1)p

    p ′ = s u m x ∈ V ( p ) P ( x ∣ x 1 : i − 1 ) ≥ p p'=sum_{x\in V^{(p)}}P(x|x_{1:i-1})\geq p p=sumxV(p)P(xx1:i1)p,原始的分布重新计算转化到一个新的分布如下,可以看到不在候选集里的直接概率为0,屏蔽掉了,在候选集里 的要除以这个和p’。
    P ′ ( x ∣ x 1 : i − 1 ) = { P ( x ∣ x 1 : i − 1 ) / p ′ i f x ∈ V ( p ) 0 o t h e r s i z e P'(x|x_{1:i-1})=\left\{\begin{matrix} P(x|x_{1:i-1})/p'&if x\in V^{(p)}\\ 0 & othersize \end{matrix}\right. P(xx1:i1)={P(xx1:i1)/p0ifxV(p)othersize

    参考链接

    [1]https://blog.csdn.net/hecongqing/article/details/105040105?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control
    [2]https://zhuanlan.zhihu.com/p/68383015
    [3]The Curious Case of Neural Text Degeneration(https://link.zhihu.com/?target=https%3A//arxiv.org/abs/1904.09751)

    展开全文
  • 音视频-编解码-拉丁文字图形化设计方法研究.pdf
  • UniEncoder解码库-可以快速解码和编码,日常开发中经常会进行对字符串的各种编码和解码,很方便。
  • 音视频-编解码-视频图像中文字提取方法研究.pdf
  • 音视频-编解码-论蒙古文字的图形化设计.pdf
  • 音视频-编解码-图像、文字文本与灵视诗学.pdf
  • 音视频-编解码-视频图像字幕文字的检测与去除.pdf
  • 易语言Base64编解码新汇编源码,Base64编解码新汇编,P_Bin,P_Str,Base64编码,Base64Encode,Base64解码,Base64Decode
  • 音视频-编解码-文字图形化设计在中国的发展与演变.pdf
  • 实例如下: //将内容进行UNICODE编码 function unicode_encode($name) { $name = iconv('UTF-8', 'UCS-2', $name); $len = strlen($name);... { // 两个字节的文字 $str .= '\u'.base_convert(o
  • 字符是各种文字和符号的总称,包括乱码;一个字符对应1~n个字节,一字节对应8位,每位用0或1表示。 2)字符集(Character Set) 字符集是多个字符的集合,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符...
  • 16进制解码工具

    2015-07-29 17:01:31
    可以对16进制进行解码解码文字形式,可以对URL解码
  • 音视频-编解码-视频图像中叠加维吾尔文字定位技术研究古丽恰西哈列.pdf
  • Java Escape算法编码示例,包括解码类文件源码,解码说明:本方法保证 不论参数s是否经过escape()编码,均能得到正确的“解码”结果。 运行环境:Java/Eclipse
  • js对文字进行编码涉及3个函数:escape,encodeURI,encodeURIComponent,另外还有相对应的解码函数,本文对编码及解决函数坐下介绍,感兴趣的朋友可以参考下
  • 音视频-编解码-见形知义文字的图形化设计在学龄前儿童识字学习中的应用.pdf
  • VisualC.音视频编解码技术及实践].求是科技.高清文字
  • C#二维码图片生成,二维码图片解码含源代码 ...将指定的文字或数字生成...将生成的二维码图二内容进行解码成对应的文字或数字。 可进行设置图片的大小,以及图片的颜色、透明度等。 可设图片的背景颜色、透明度等效果。
  • js对文字进行编码涉及3个函数:escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decodeURIComponent 1、 传递参数时需要使用encodeURIComponent,这样组合的url才不会被#等特殊字符截断...
  • 本文全面梳理一下OCR文字识别三种解码算法,先介绍一下什么是OCR文字识别,然后介绍一下常用的特征提取方法CRNN,最后介绍3种常用的解码算法CTC/Attention/ACE。什么是OC...

    本文全面梳理一下OCR文字识别三种解码算法,先介绍一下什么是OCR文字识别,然后介绍一下常用的特征提取方法CRNN,最后介绍3种常用的解码算法CTC/Attention/ACE

    什么是OCR文字识别?

    一般来说,文字识别之前需要先对文字进行定位(文字检测主要有基于物体检测和基于分割两种方法),文字识别就是通过输入文字图片,然后解码成文字的方法。本文主要讲文字识别部分,文字识别主要分成三种类型:单字分类、整词分类和整词识别。当能够定位出单字时,可以用图像分类的方法直接对单字进行分类;当需要预测整词数量较少时,可以对整词进行分类;当有大量整词需要预测并且没有单字定位时,就需要用解码序列的方法进行识别了。因此,文字识别中最常用的是文字序列识别,适用场景更为广泛。本文将主要介绍文字序列识别的解码算法。

    OCR解码是文字识别中最为核心的问题。本文主要对OCR的序列方法CTC、Attention、ACE进行介绍,微信OCR算法就是参考这三种解码算法的。

    不同的解码算法的特征提取器可以共用,后面接上不同的解码算法就可以实现文字识别了,以下用CRNN作为特征提取器。

    CRNN

    CRNN的特征抽取器由一个CNN和一个BiLSTM组成,其中BiLSTM使用的是stack形深层双向LSTM结构。

    CRNN特征提取器流程如下:

    1.假设输入图像尺寸为32x100x3(HxWxC),经过CNN转换成1x25x512(HxWxC)。

    2.将CNN的输出维度转换为25个1x512的序列,送入深层双向LSTM中,得到CRNN的输出特征,维度转换成为25xn(n是字符集合总数)。

    OCR文字识别的难点

    OCR文字识别的解码主要难点在于如何进行输入输出的对齐。如上图所示,如果每个1xn预测一个字符,那么可能会出现多个1xn预测同一个字符,这样子得到的最终结果会产生重复字符。所以需要设计针对文字识别的解码算法来解决输入输出的对齐问题。

    目前我了解到的主要有三种解码方法,可以解决OCR解码的一对多问题,分别为CTC、Attention和ACE三种。

    CTC

    CTC是最为经典的OCR解码算法,假设CRNN特征抽取器的输出维度Txn,其中T=8,n包含blank(记作 - )字符(blank字符是间隔符,意思是前后字符不连续)。对每一列1xn进行softmax得到概率最大的字符,得到的最终序列需要去除连续的重复字符,比如最终得到的序列为-stt-ate,那么去重合并后就得到state序列。

    那么state的序列概率就变成了所有去重合并后为state的字符序列概率之和,只要最大化字符序列概率,就可以优化CRNN+CTC的文字识别算法。由于每个字符前后都可以插入blank,所以可以将所有可能状态如下图展开。

    为了方便起见,对于所有state序列的合法路径做一些限制,规则如下:

    1.转换只能往右下方向,其它方向不允许

    2.相同的字符之间起码要有一个空字符

    3.非空字符不能被跳过

    4.起点必须从前两个字符开始

    5.终点必须落在结尾两个字符

    根据上述约束规则,遍历所有"state"序列的合法路径,“state”的所有合法路径如下图所示:

    其中绿色框部分为起点和终点,蓝色箭头为"state"序列的合法路径。当然可以通过枚举所有路径,然后求所有路径的概率之和即为"state"序列的概率。但是枚举所有路径计算复杂度太高了,于是CTC引入了HMM的前向-后向算法来减少计算复杂度(可以参考一下我之前的回答,增加隐马尔可夫模型(HMM)的理解)。

    以前向算法为例(后向算法可以认为是状态序列的反转,计算方法相同),简单来说,就是利用分治和动态规划的思想,把8个时间点拆分成7个重复单元,然后先计算出第一个重复单元红色虚线框中每个状态的观测概率,并且保存下来当作下一个重复单元的初始状态,循环计算7次就得了最终的观测概率。比起暴力求解观测概率,复杂度大大降低。

    Attention

    基于Attention的OCR解码算法,把OCR文字识别当成文字翻译任务,即通过Attention Decoder出文字序列。

    RNN -> Seq2Seq

    左图是经典的RNN结构,右图是Seq2Seq结构。RNN的输入序列和输出序列必须有相同的时间长度,而机器翻译以及文字识别任务都是输入输出不对齐的,不能直接使用RNN结构进行解码。于是在Seq2Seq结构中,将输入序列进行Encoder编码成一个统一的语义向量Context,然后送入Decoder中一个一个解码出输出序列。在Decoder解码过程中,第一个输入字符为<start>,然后不断将前一个时刻的输出作为下一个时刻的输入,循环解码,直到输出<stop>字符为止。

    Seq2Seq -> Attention Decoder

    Seq2Seq把所有的输入序列都编码成一个统一的语义向量Context,然后再由Decoder解码。由于context包含原始序列中的所有信息,它的长度就成了限制模型性能的瓶颈。如机器翻译问题,当要翻译的句子较长时,一个Context可能存不下那么多信息,就会造成精度的下降。除此之外,如果按照上述方式实现,只用到了编码器的最后一个隐藏层状态,信息利用率低下。

    所以如果要改进Seq2Seq结构,最好的切入角度就是:利用Encoder所有隐藏层状态解决Context长度限制问题。于是Attention Decoder在Seq2Seq的基础上,增加了一个Attention Layer,如上图所示。

    在Decoder时,每个时刻的解码状态跟Encoder的所有隐藏层状态进行cross-attention计算,cross-attention将当前解码的隐藏层状态和encoder的所有隐藏层状态做相关性计算,然后对encoder的所有隐藏层加权求和,最后和当前解码的隐藏层状态concat得到最终的状态。这里的cross-attention计算方式也为后来的Transformer框架打下了基础(详细看我之前写的文章计算机视觉"新"范式: Transformer)。

    另外,从形式上看,Attention Decoder很自然的可以替换成最近非常流行的Transformer,事实上,最近也有几篇基于Vision Transformer的文本识别算法。

    ACE

    基于ACE的解码方法不同于CTC和Attention,ACE的监督信号实际上是一种弱监督(输入输出没有做形式上的对齐,没有先后顺序信息,倾向于学习表征),并且可以用于多行文字识别。

    对于单行文字,假设输出维度为Txn(T是序列长度,n是字符集合总数),那么第k个字符出现的总数为   ,然后除以T,就能得到第k个字符出现的概率分布(记作   ),做相同计算,可以求出所有字符的概率分布,最后和label字符的概率分布计算交叉熵优化网络。同理,对于多行文字,只需要将HxW压缩成T=HW,然后计算所有字符的概率分布即可。

    CTC/Attention/ACE三种解码算法比较

    从模型设计上来看,可以采用结合上面3种方法的多任务文本识别模型。在训练时,以CTC为主,Attention Decoder和ACE辅助训练。在预测时,考虑到速度和性能,只采用CTC进行解码预测。多任务可以提高模型的泛化性,同时如果对预测时间要求不高,多结果也可以提供更多的选择和对比。

    上图来源于微信OCR技术的比较:

    1.CTC和ACE方法不需要额外的计算参数,Attention需要额外的计算参数

    2.推理内存,ACE < CTC < Attention;推理速度,ACE > CTC > Attention

    3.CTC效果更好一些,适合长文本;Attention可以得到语言模型;ACE可以用于计数和2D预测

    由于Attention依赖于上一个预测结果,导致只能串行解码,推理速度影响较大,但是可以得到语言模型做pretrain迁移使用;而CTC可以通过引入blank字符做形式上对齐,并且通过HMM前向-后向算法加速;ACE则直接不依赖顺序信息,直接估计整体分布。三者各有利弊,实际使用时,需要结合具体任务按需使用。

    Reference

    [1] An End-to-End Trainable Neural Network for Image-based Sequence Recognition and Its Application to Scene Text Recognition

    [2] Connectionist Temporal Classification: Labelling Unsegmented Sequence Data with Recurrent Neural Networks

    [3] Robust Scene Text Recognition with Automatic Rectification

    [4] Aggregation Cross-Entropy for Sequence Recognition

    [5] https://mp.weixin.qq.com/s/6IGXof3KWVnN8z1i2YOqJA

    强烈推荐以下三篇blog

    https://zhuanlan.zhihu.com/p/43534801

    https://zhuanlan.zhihu.com/p/51383402

    https://xiaodu.io/ctc-explained/

    
    
    
    觉得还不错就给我一个小小的鼓励吧!
    
    
    
    展开全文
  • 本文全面梳理一下OCR文字识别三种解码算法,先介绍一下什么是OCR文字识别,然后介绍一下常用的特征提取方法CRNN,最后介绍3种常用的解码算法CTC/Attention/ACE。什么是OC...

    本文全面梳理一下OCR文字识别三种解码算法,先介绍一下什么是OCR文字识别,然后介绍一下常用的特征提取方法CRNN,最后介绍3种常用的解码算法CTC/Attention/ACE

    什么是OCR文字识别?

    一般来说,文字识别之前需要先对文字进行定位(文字检测主要有基于物体检测和基于分割两种方法),文字识别就是通过输入文字图片,然后解码成文字的方法。本文主要讲文字识别部分,文字识别主要分成三种类型:单字分类、整词分类和整词识别。当能够定位出单字时,可以用图像分类的方法直接对单字进行分类;当需要预测整词数量较少时,可以对整词进行分类;当有大量整词需要预测并且没有单字定位时,就需要用解码序列的方法进行识别了。因此,文字识别中最常用的是文字序列识别,适用场景更为广泛。本文将主要介绍文字序列识别的解码算法。

    OCR解码是文字识别中最为核心的问题。本文主要对OCR的序列方法CTC、Attention、ACE进行介绍,微信OCR算法就是参考这三种解码算法的。

    不同的解码算法的特征提取器可以共用,后面接上不同的解码算法就可以实现文字识别了,以下用CRNN作为特征提取器。

    CRNN

    CRNN的特征抽取器由一个CNN和一个BiLSTM组成,其中BiLSTM使用的是stack形深层双向LSTM结构。

    CRNN特征提取器流程如下:

    1.假设输入图像尺寸为32x100x3(HxWxC),经过CNN转换成1x25x512(HxWxC)。

    2.将CNN的输出维度转换为25个1x512的序列,送入深层双向LSTM中,得到CRNN的输出特征,维度转换成为25xn(n是字符集合总数)。

    OCR文字识别的难点

    OCR文字识别的解码主要难点在于如何进行输入输出的对齐。如上图所示,如果每个1xn预测一个字符,那么可能会出现多个1xn预测同一个字符,这样子得到的最终结果会产生重复字符。所以需要设计针对文字识别的解码算法来解决输入输出的对齐问题。

    目前我了解到的主要有三种解码方法,可以解决OCR解码的一对多问题,分别为CTC、Attention和ACE三种。

    CTC

    CTC是最为经典的OCR解码算法,假设CRNN特征抽取器的输出维度Txn,其中T=8,n包含blank(记作 - )字符(blank字符是间隔符,意思是前后字符不连续)。对每一列1xn进行softmax得到概率最大的字符,得到的最终序列需要去除连续的重复字符,比如最终得到的序列为-stt-ate,那么去重合并后就得到state序列。

    那么state的序列概率就变成了所有去重合并后为state的字符序列概率之和,只要最大化字符序列概率,就可以优化CRNN+CTC的文字识别算法。由于每个字符前后都可以插入blank,所以可以将所有可能状态如下图展开。

    为了方便起见,对于所有state序列的合法路径做一些限制,规则如下:

    1.转换只能往右下方向,其它方向不允许

    2.相同的字符之间起码要有一个空字符

    3.非空字符不能被跳过

    4.起点必须从前两个字符开始

    5.终点必须落在结尾两个字符

    根据上述约束规则,遍历所有"state"序列的合法路径,“state”的所有合法路径如下图所示:

    其中绿色框部分为起点和终点,蓝色箭头为"state"序列的合法路径。当然可以通过枚举所有路径,然后求所有路径的概率之和即为"state"序列的概率。但是枚举所有路径计算复杂度太高了,于是CTC引入了HMM的前向-后向算法来减少计算复杂度(可以参考一下我之前的回答,增加隐马尔可夫模型(HMM)的理解)。

    以前向算法为例(后向算法可以认为是状态序列的反转,计算方法相同),简单来说,就是利用分治和动态规划的思想,把8个时间点拆分成7个重复单元,然后先计算出第一个重复单元红色虚线框中每个状态的观测概率,并且保存下来当作下一个重复单元的初始状态,循环计算7次就得了最终的观测概率。比起暴力求解观测概率,复杂度大大降低。

    Attention

    基于Attention的OCR解码算法,把OCR文字识别当成文字翻译任务,即通过Attention Decoder出文字序列。

    RNN -> Seq2Seq

    左图是经典的RNN结构,右图是Seq2Seq结构。RNN的输入序列和输出序列必须有相同的时间长度,而机器翻译以及文字识别任务都是输入输出不对齐的,不能直接使用RNN结构进行解码。于是在Seq2Seq结构中,将输入序列进行Encoder编码成一个统一的语义向量Context,然后送入Decoder中一个一个解码出输出序列。在Decoder解码过程中,第一个输入字符为<start>,然后不断将前一个时刻的输出作为下一个时刻的输入,循环解码,直到输出<stop>字符为止。

    Seq2Seq -> Attention Decoder

    Seq2Seq把所有的输入序列都编码成一个统一的语义向量Context,然后再由Decoder解码。由于context包含原始序列中的所有信息,它的长度就成了限制模型性能的瓶颈。如机器翻译问题,当要翻译的句子较长时,一个Context可能存不下那么多信息,就会造成精度的下降。除此之外,如果按照上述方式实现,只用到了编码器的最后一个隐藏层状态,信息利用率低下。

    所以如果要改进Seq2Seq结构,最好的切入角度就是:利用Encoder所有隐藏层状态解决Context长度限制问题。于是Attention Decoder在Seq2Seq的基础上,增加了一个Attention Layer,如上图所示。

    在Decoder时,每个时刻的解码状态跟Encoder的所有隐藏层状态进行cross-attention计算,cross-attention将当前解码的隐藏层状态和encoder的所有隐藏层状态做相关性计算,然后对encoder的所有隐藏层加权求和,最后和当前解码的隐藏层状态concat得到最终的状态。这里的cross-attention计算方式也为后来的Transformer框架打下了基础(详细看我之前写的文章计算机视觉"新"范式: Transformer)。

    另外,从形式上看,Attention Decoder很自然的可以替换成最近非常流行的Transformer,事实上,最近也有几篇基于Vision Transformer的文本识别算法。

    ACE

    基于ACE的解码方法不同于CTC和Attention,ACE的监督信号实际上是一种弱监督(输入输出没有做形式上的对齐,没有先后顺序信息,倾向于学习表征),并且可以用于多行文字识别。

    对于单行文字,假设输出维度为Txn(T是序列长度,n是字符集合总数),那么第k个字符出现的总数为   ,然后除以T,就能得到第k个字符出现的概率分布(记作   ),做相同计算,可以求出所有字符的概率分布,最后和label字符的概率分布计算交叉熵优化网络。同理,对于多行文字,只需要将HxW压缩成T=HW,然后计算所有字符的概率分布即可。

    CTC/Attention/ACE三种解码算法比较

    从模型设计上来看,可以采用结合上面3种方法的多任务文本识别模型。在训练时,以CTC为主,Attention Decoder和ACE辅助训练。在预测时,考虑到速度和性能,只采用CTC进行解码预测。多任务可以提高模型的泛化性,同时如果对预测时间要求不高,多结果也可以提供更多的选择和对比。

    上图来源于微信OCR技术的比较:

    1.CTC和ACE方法不需要额外的计算参数,Attention需要额外的计算参数

    2.推理内存,ACE < CTC < Attention;推理速度,ACE > CTC > Attention

    3.CTC效果更好一些,适合长文本;Attention可以得到语言模型;ACE可以用于计数和2D预测

    由于Attention依赖于上一个预测结果,导致只能串行解码,推理速度影响较大,但是可以得到语言模型做pretrain迁移使用;而CTC可以通过引入blank字符做形式上对齐,并且通过HMM前向-后向算法加速;ACE则直接不依赖顺序信息,直接估计整体分布。三者各有利弊,实际使用时,需要结合具体任务按需使用。

    Reference

    [1] An End-to-End Trainable Neural Network for Image-based Sequence Recognition and Its Application to Scene Text Recognition

    [2] Connectionist Temporal Classification: Labelling Unsegmented Sequence Data with Recurrent Neural Networks

    [3] Robust Scene Text Recognition with Automatic Rectification

    [4] Aggregation Cross-Entropy for Sequence Recognition

    [5] https://mp.weixin.qq.com/s/6IGXof3KWVnN8z1i2YOqJA

    强烈推荐以下三篇blog

    https://zhuanlan.zhihu.com/p/43534801

    https://zhuanlan.zhihu.com/p/51383402

    https://xiaodu.io/ctc-explained/

    
    往期精彩回顾
    
    
    
    适合初学者入门人工智能的路线及资料下载机器学习及深度学习笔记等资料打印机器学习在线手册深度学习笔记专辑《统计学习方法》的代码复现专辑
    AI基础下载机器学习的数学基础专辑黄海广老师《机器学习课程》课件合集
    本站qq群851320808,加入微信群请扫码:
    
    
    展开全文
  • jother编码解码工具

    2014-10-04 13:47:23
    javascript中将文字转换成标点的编码
  • 多媒体将选定的所有元素(包括文字、音频、静态图像、视频和图形)集成到单一媒体对象中。流技(Streaming technology)可在媒体对象被读取、收听或者观看的同时实时传输这些对象。在RealAudio公司1995年提供首个商用流...
  • 使用方法:utf8to16(base64decode(你的加密字符串));
  • 参照王纲大佬的用ffmpeg的avfilter给视频文件加载文字的例程,修改了一下,改成给jpeg图片加载文字
  • 摘要:提出了一种在TI OMAPl510...在多媒体通信中,视频区别于音频和文字的显著特点是其大数据量以及高处理复杂度。现有的移动终端一般采用DSP芯片作为核心,DSP芯片在数据处理方面具有较多的优势,但其系统处理和控制

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 67,373
精华内容 26,949
热门标签
关键字:

常见的文字解码方式