精华内容
下载资源
问答
  • 前言: 文字识别的关键之所在就是单个文字的切割,切割的准确度极大的影响了文字识别的正确率。本文基于传统横纵投影的思想对文字进行切割,使用java与python...本文主要对切割算法进行讨论,图片处理部分望读者...

    前言:

             文字识别的关键之所在就是单个文字的切割,切割的准确度极大的影响了文字识别的正确率。本文基于传统横纵投影的思想对文字进行切割,使用java与python实现了本算法。

     

    基本思路:

             1、横向扫描,切出每一行

             2、对每一行进行纵向扫描,得出每一个字

     

    经过对原始图像的相关处理,得出如下二值图(仅有黑白色)。这里的‘相关处理’是很复杂的,涉及图像学相关知识,我是通过opencv进行处理的。本文主要对切割算法进行讨论,图片处理部分望读者自行了解。

    (待切割图)

    横向扫描

             横向扫描就是依次从左往右统计,得出这一行黑色点的数量。比如上图尺寸为1200*430,经过横向扫描就可以得到430个数值,这个数值表示在1200个点中黑色点的数量。我们把这430个数直观的展示出来,可以得到下图:

    (横向切割统计图,x:行数   y:黑色点数)

    在上图中,y轴数值不为0的区域就是文字存在的地方,为0的区域就是每行之间相隔的距离。我们通过如下规则就可以找出每一行文字的起始点和终止点,以定位该行文字区域:1、如果前一个数为0,则记录第一个不为0的坐标;2、如果前一个数不为0,则记录第一个为0的坐标。形象的说就是从出现第一个非空白行(开始有字)到出现第一个空白行(没有字)这段区域就是文字存在的区域。

    (横向切割说明图)

    纵向扫描

             纵向扫描与横向扫描同理。针对横向扫描切割出的区域,进行纵向扫描,得出每一个字。

    我们对横向扫描得出的第一行进行纵向扫描,可以得到1200个数值,如下图:

    (横向切割统计图,x:行数   y:黑色点数  省略了部分区域)

    再运用横向扫描的思维,对纵向扫描的数据进行切割,就可以得出单个文字了。

     

    切割结果

    (切割结果)

             可以看到切割结果有些不理想,会存在很多连在一起的字。

    结果分析

             算法对于数字切割十分理想,但是对于汉字会存在切割失败的现象。分析发现部分汉字两两之间没有空白区域,是连在一起的,所以纵向扫描算法就无法准确切割。如下图所示:

    所以直接使用投影进行切割,这种方法是不可行的。我们需要对该算法进行优化,以便得出更为准确的结果。优化算法敬请期待下篇(文字切割算法-投影切割优化)。

    项目源码:我的github(https://github.com/printlin/tmOcr/tree/master)

    展开全文
  • 在上文(文字切割算法-基于投影的切割)中发现切割结果并不是很理想,所以在本文提出优化算法对结果进行进一步处理。本算法的解决思路很简单,即针对已暴露出的问题进行解决,对于未暴露的问题就无能为力了。所以...

    前言

            在上文(文字切割算法-基于投影的切割)中发现切割结果并不是很理想,所以在本文提出优化算法对结果进行进一步处理。本算法的解决思路很简单,即针对已暴露出的问题进行解决,对于未暴露的问题就无能为力了。所以算法的鲁棒性并不是很好,但是简单易实现。

    发现问题

             对基于投影的切割结果进行观察,可以将问题总结为三类。

    整体连接

    整体连接图

             多个文字连接在一起

    左右结构分开

    左右结构分开图

             左右结构的文字被切割成两个字

    左右结构分开后连接

    左右结构分开连接图

             左右结构的文字分开后,又与前后相邻文字相连

     

    解决问题

    整体连接

             由于汉字是方块字,可以认为每个字的长宽比例都是差不多的,基本都是1:1(金龙鱼调和…呸)。对于整体连接在一起的文字,可以先计算整体的长宽比。如果比例是接近于整数的(±0.2),则认为这是整体连接在一起的多个字。再计算每个字的平均长度进行切割,就可以得到一个比较不错的结果。

    整体连接说明图

           如上图,这是四个字连在一起的。长宽比:104/27≈3.85,3.85>4-0.2所以我们认为它是4个字。则平均宽度:104/4=26,按照26*27的宽长进行切割,就可以得出结果。(这里的长宽比是:宽度/长度)

    整体连接解决结果图

     

    左右结构分开

             由于左右结构分开后,两张图片的长宽比与数字符号的长宽比相似。所以我们无法判断到底是偏旁还是符号,这样就无法进行连接。这个问题将在以后提出识别算法对图片进行识别后解决。

    左右结构分开实例图

    如上图,由于无法识别图片内容,所以无法判断到底是“7”与“阝”连接,还是“阝”与“艮”连接。

    左右结构分开后连接

             采用整体连接的解决思路,先计算长宽比,如果发现长宽比不是在整数附近的(>±0.2),则认为这是左右结构分开后连接的。因为这种情况都是两张图,所以在发现第一张是分开后连接的,则将这张图先以1:1进行切割,再将剩下的部分记录。如果这张图相邻的下一张也被判断为是分开后连接的,则将上一张图剩下的部分与这张图的开头相连接,再进行1:1切割。这样就可以得到一个不错的结果。

    左右结构分开连接图

             如上图,先对第一张进行1:1切割,即按照27*27的大小从开头逐步向后切割,记录最后剩下的部分“丬”。再判断下一张图,发现也是分开后连接的,则按照27*27的大小从末尾逐步向前切割,得到剩下的部分。最后将这两个剩下的部分进行连接,得到一个完整的“北”。

    (当然这里要求在投影切割时记录图片两两之间的距离,这样才能还原被切割后的图片)

    切割结果如下:

    分开连接结果图

     

    结果

            在采用上述优化算法后,发现切割结果有了显著的成效。但是还是会存在一些不足,这些问题会在以后提出识别算法后进行优化。文字切割出来后,我们可以通过图片相似度比对算法对图片特征进行提取,以进行识别。

    整体结果图

    项目源码:我的github(https://github.com/printlin/tmOcr)

    展开全文
  • 前言 上一篇写过看的一篇字符切割的论文,只是大概...字符切割: 核心思想是MM,下面详细描述怎么对字符串图像做到自适应切割: 第一步: 图像二值化,这里不再赘述;在进行去噪的时候使用了膨胀和剪枝算法,剪枝算...

    前言

    上一篇写过看的一篇字符切割的论文,只是大概描述了论文讲的是什么(https://blog.csdn.net/m0_37661841/article/details/103582758),这一篇是具体字符切割的方法,下一篇会贴上详细的代码;

    字符切割:

    核心思想是MM,下面详细描述怎么对字符串图像做到自适应切割:

    第一步:

    图像二值化,这里不再赘述;在进行去噪的时候使用了膨胀和剪枝算法,剪枝算法伪代码可以看上面上一篇的链接;

    第二步:自适应切割

    2.1、切割:从图像直方图,找到图像的字符起始位置,和字符终止位置,然后根据起始位置和终止位置的前后关系确定字符的位置和字符的前后关系;
    细化算法结果:
    在这里插入图片描述
    2.2、定位固定段:可能存在M,W,N等可能由于二值化图像或者字符本身的原因我们在2.1的操作会将一个字符切割成多个片段;我们提前设定一个字符最优间距,然后按照字符片段位于原图的位置关系进行叠加;
    图像示例:
    在这里插入图片描述
    直方图示例:

    在这里插入图片描述
    2.3重叠字符分割:对于倾斜字符,直方图无法正确得到分割线,图像如下所示:
    在这里插入图片描述
    直方图:
    在这里插入图片描述
    增厚算法得到分割线如下:
    在这里插入图片描述
    显然这里只能分割前五个字符,后面两个字符需要继续分割;
    2.4分割联通字符:使用细化算法得到字符骨架,首先定位交叉点:作者定义了12中像素情况为交叉点:对图像种确定的多个交叉点进行筛选:
    第一,使用2.1中的方法得到2.1的分割线,判断交叉点距离分割线的长度,我们定义一个容错,在这个长度内的,我们就人为这个交叉点是必要的交叉点;
    第二:使用分割成本计算最佳交叉点:

    在这里插入图片描述
    交叉点定位结果:
    在这里插入图片描述
    丢弃不必要的交叉点,从交叉点切割图像。
    2.5、识别:对图像进行适当的缩放,得到同意大小的图像,送给识别模型识别,识别模型后面的会继续详述。

    展开全文
  • 假设现在有一个一维数组,我们查找之中的一个特殊字符,随后,将这个一维数组以这个字符为界,将数组分成若干个晓得一维数组,并存入一个二维数组。 (新生成的数组中不含这个字符

    本篇博客主要是为了用java语言解决一个算法小问题的。问题如下:

    *假设现在有一个一维数组,我们查找之中的一个特殊字符,随后,将这个一维数组以这个字符为界,将数组分成若干个晓得一维数组,并存入一个二维数组。
    (新生成的数组中不含这个字符)*

    这个问题的思路为 :

    1. 找到这个一维数组的所有的特殊字符位置及其总次数。

    2. 将这个一维数组里出现的所有特殊字符位置的下标存下来,以便第四步使用 (以下我们简称为下标数组)

    3. 判断需要生成多少个分好的一维数组。

    4. 判断此时生成的这个一维数组的长度。

    5. 给这个一维数组赋值。

    6. 将这个一维数组的引用赋值给二维数组。

    7. 返回二维数组。

    首先,实现1,2,3步,这个比较简单,只需要for循环遍历,但因为要得知我们生成下标数组的大小,所以需要用for循环两次,根据字符出现的次数,
    我们就可以得知我们需要建立多少个一维数组,通过代码如下所示:

        int num = 0;             // 字符总数  
        int[]  index ;
    
       //得知字符的个数
       for(int i = 0 ; i < arr.length ;i++ ){
           if(arr[i] == c){
              num++;
           }
       }
    
       index = new int[num];
    
       //创建下标的数组
       int h = 0;
       for(int i = 0 ; i < arr.length ;i++ ){
           if(arr[i] == c){
             index[h] = i;
             h++;
          }
       } 
    

    接下来,我们需要创建一个一维数组(第4步),来存放我们截取的数组 ,首先我们需要的临时数组(temp[]),这里,我们需要知道这个一维数组的大小,数组的大小有三种情况:

    1. 要截取从开始到第一次字符出现的地方。这时数组的大小为index[0]。

    2. 要截取最后一次字符出现的地方到结束,这是数组的大小为arr.length - index[index.length - 1] – 1。(即传入 的一维数组长度减去字符最后出现的下标再减一)。

    3. 要截取中间正常的地方,只需后一个下标减去前一个下标再减一。即index[i]-index[i-1]-1。

    得知了数组的大小,现在我们就可以给这个数组赋值了,赋值和计算数组大小一样同样分三种情况。(第五步)因为比较简单,这里只贴出代码。

      for (int j = 0; j < size & size != 0; j++) {
               if (i == 0) {                                     //第一个字符前
                temp[j] = arr[j];
                  }
    
                   else if(i == num & (index[ num - 1] != arr.length - 1)){   //最后一个字符后
                temp[j] = arr[j +index[num - 1] + 1];
                }
    
                 else{                                          //普遍情况
                    temp[j] = arr[j -size + index[i]];                  
             }
      }
    

    最后一步,只需把这个一维数组赋值给二维数组,返回这个二维数组即可。

    注意:

    1. 这里只需申请一个临时数组temp,只要不断地去给他赋值就可以,在赋值给二维数组之后,我们可以使其等于null释放(可以省略这一步,java的垃圾回收机制会回收它)。

    2. 以上的分析都只分析了一般的情况,有一种特殊情况,传入的字符数组首位或者尾位出现特殊字符时,需要特别注意,根据我们的算法,这时会令其生成长度为0的一维数组,(见运行示例2,3),所以再给临时数组赋值时必须要剔除这种情况。

    3. 最后,我们让主函数调用这个函数,并输出二维数组,如下:

    public staticvoid main(String[]args) {
    char[] array =new char[]{‘a’ , ‘b’ ,’c’ , ‘d’ ,’e’ , ‘h’ ,’b’ , ‘h’ };
    char[][]result = spilt(array ,’b’);//调用我们编好的程序

     for (inti = 0 ; i < result.length;i++) {
           for(int j = 0 ;j < result[i].length ;j++){
               System.out.print(result[i][j]);
           }
             System.out.println();
          }
      System.out.println("输出完毕");
    
    }
    

    测试结果如下:

    1. 当传入数组为{‘a’ ,’b’ ,’c’ , ‘d’ ,’e’ , ‘h’ ,’b’ , ‘h’ }
      示例一:正常情况
    2. 当传入数组为 {‘b’ ,’a’ ,’b’ , ‘c’ ,’d’ , ‘e’ ,’h’ , ‘b’ ,’h’ }
      示例二:串首为特殊字符
    3. 当传入数组为 {‘b’ ,’a’ ,’b’ , ‘c’ ,’d’ , ‘e’ ,’h’ , ‘b’ ,’h’ ,’b’ }
      示例三:串首尾均为特殊字符

      下面是源代码,这个题在各种面试里有它的增强版出现(如判断是否可以将一维数组拆分为几个和一样的小数组等等),读者可以以此扩展,最后,感谢您的阅读,因为作者本身能力的问题,语句可能比较繁杂,并且可能会有错误 (虽然我自己测试的结果是运行正常的),如果发现错误的话,请及时指出,最后,诚挚感谢您的阅读!

      public static char[][] spilt(char[] arr ,char c){
      //TODO将以为数组以字符为界拆开并生成一个不规则的二维数组存放

      int num = 0; // 字符总数
      int[] index ;

      //得知字符的个数
      for(int i = 0 ;i < arr.length ;i++ ){
      if(arr[i] == c){
      num++;
      }
      }

      index = newint[num];

      //创建下标的数组
      int h = 0;
      for(int i = 0 ;i < arr.length ;i++ ){
           if(arr[i] == c){
             index[h] =i;
                h++;
          }
      } 
      
      char[][]  newArray =new char[num + 1][];    
        char[] temp;
        for (int i = 0;i < num + 1;i++) {
        int size = 0;
            if (i == 0) {
        if((index[0] == 0)){                    //开头为字符
              size = 0;
           }
       else{
                 size =index[0];
        }
             }
             else if(i == num){
                size = arr.length -index[index.length - 1] - 1;
        }
      
       else{
          size = index[i] -index[i - 1] - 1;
              }
      
        temp = newchar[size];
      
              for (int j = 0;j < size & size != 0; j++) {
             if (i == 0) {                                     //第一个字符前
              temp[j] =arr[j];
                }
      
                 else if(i == num & (index[ num - 1] != arr.length - 1)){   //最后一个字符后
              temp[j] =arr[j +index[num - 1] + 1];
              }
      
               else{                                          //普遍情况
                  temp[j] =arr[j -size +index[i]];                  
           }
        }
        newArray[i] =temp;
      

      }
      return newArray;

      }
      }

    展开全文
  • * 先分析切割点以及切割点后一位是否为数字或冒号。如果不是,正常按70字切割;如果是,则往前地推,直到不是数字或冒号为止,返回间距值(gap)。如此,切一次判断一次。 * 序号处理: * 只考虑了五位或者六位七...
  • boost库中的字符算法查找、切割、替换、删除、合并等等详解零、小序一、大小写转换1、大小写转换函数2、大小写代码示例二、删除1、删除函数2、删除代码示例三、替换1、替换函数2、替换代码示例四、查找1、查找函数...
  • boost字符算法

    2014-05-07 14:31:00
    boost::algorithm提供了很多字符算法,包括: 大小写转换; 去除无效字符; 谓词; 查找; 删除/替换; 切割; 连接; 我们用写例子的方式来了解boost::algorithm能够为我们做些什么。 boost::algorithm学习#...
  • 短信切割算法

    2009-05-25 08:37:00
    或者几乎这种手机都不会去理解语义,直接就在70个字符切割。要做到完全理解语义也不大可能,但是突然想到,为什么不可以根据分隔符去切割呢?至少这样子不会把一段完整的内容不会被强行分割出来。
  • OCR字符切割

    千次阅读 2016-06-02 00:10:05
    字符分割是OCR中相当重要的环节, 直接关系到最后的识别准确率. 最近一直在做车牌检测, 用颜色与edge定位中一直没有办法避免某些特殊情况的干扰, 且样本来源未知, 没办法去设定一个相对较优的参数. (绝大部分时间用...
  • 对身份证识别系统中的字符分割技术进行了深入的研究, 阐述了倾斜校正、行切割、 小波降 噪、 单字符分割等算法, 实验证明, 该方法对退化的身份证图像具有很好的字符分割能力.
  • boost的字符算法

    2013-07-09 09:11:30
    boost::algorithm提供了很多字符算法,包括: 大小写转换; 去除无效字符; 谓词; 查找; 删除/替换; 切割; 连接; 我们用写例子的方式来了解boost::algorithm能够为我们做些什么。 boost::algorithm学习 #...
  • 根据前面的几篇博客已经知道,如果验证码里的字符之间没有相连,我们使用任意一个机器学习的算法(KNN,SVM等)很容易就可以把他们切割标注识别出来,实际上很多网站的验证码都不可能那么简单,那么我们字符连接如何...
  • 为了实现字段式液晶数字的自动判读,提出了一种基于字符切割和拼接的识别算法。定位字符垂直投影的波峰,在两峰之间确定切割线并对字符进行切割,利用投影特征,对切割块进行拼接,实现字符的准确分割。实验表明,该...
  • 车牌识别中的字符切割

    万次阅读 2013-05-19 18:01:07
     通过上述两种方法的介绍可以看出,水平投影法对于只有连通字符并且不存在干扰的车牌具有良好的分割效果,而且算法复杂度也相对简单,但对于含有不连通或者粘连字符的情况则有一定难度;相反,模板匹配法根据车牌...
  • 对身份证识别系统中的字符分割技术进行了深入的研究,阐述了倾斜校正、行切割、小波降噪、单字符分割等法,实验证明, 文中方法对退化的身份证图像具有很好的字符分割能力。
  • 基于openCV和python的车牌字符切割

    千次阅读 2019-02-15 00:09:50
    在车牌识别以及别的需要文本识别的场景中都需要对图像中的文本进行正确的切分以便于下一步的识别,类似人的阅读计算机在识别文本时只能一个一个的来,精准的切分字符是识别的必要条件。   算法 假设我们已经从...
  • 《我的眼睛–图灵识别》第八章:训练:图像字符切割 图像字符切割是把图像上的每个文字分割成独立的单个字符,这是识别最有效的基础。 字符分割是图像识别最关键的一步,因为分割的正确与否直接关系到最后的结果,...
  • 车牌字符切割(一)

    千次阅读 2017-11-04 20:33:08
    摘要:据了解,我国的标准车牌有统一的大小,即宽度为45cm,高度为15cm。车牌上单个字符宽为45mm,其中,第一个字符的空间...有了这些信息,就得到了车牌字符切割算法公式。 #include #include #include #includ
  • 一、算法 1、桶排序 Java代码 /* 桶排序 */ public static void booleanSort(){ int[] sortlist = new int[]{1,14,9,33,11,45,32}; boolean[] sortboolean = new boolean[46]; for...
  • 【经典算法实现 20】Merkle Tree(默克尔树)C代码实现--- 进展3:实现字符串的动态切割,实现默克尔树存储字符串三、进展2:2020/08/18 优化数据结构,添加Hash值,实现内存回收3.1 优化默克尔树数据结构3.2 实现...
  • 字符切割(raw:adbacaf sep:bac result就是ad和af) 算法分析 涉及到string类的两个函数find和substr: 1、find函数 原型:size_t find ( const string&amp; str, size_t pos = 0 ) const; 功能:查找子...

空空如也

空空如也

1 2 3 4 5 ... 18
收藏数 355
精华内容 142
关键字:

字符切割算法