kur-archive/CAPTCHA_Reader

分割验证码有啥好的方法吗

Closed this issue · 5 comments

😂😂参照你的代码写了一个golang版本的,识别一次大概200ms,只是还没想好怎么分割比较好

Wow!Cool!

以这个举例吧
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◇◇◇◇◇◇◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◆◆◆◇◇◇◆◆◆◇◇◇◆◆◆◆◆◆◇◇◇◇◆◆◆◆◆◆◆◆◇◇◇◇◇◇◆◆◆◆◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◆◆◆◆◇◇◆◆◆◇◇◇◆◆◆◆◇◇◇◇◇◇◆◆◆◆◆◆◆◆◆◇◇◇◇◆◆◆◇◇◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◆◆◆◇◇◇◆◆◆◆◆◇◆◆◆◇◇◇◆◆◆◇◇◇◇◇◇◇◆◆◆◇◇◇◆◆◆◇◇◇◆◆◆◇◇◇◇◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◆◆◆◇◇◇◆◆◆◆◆◇◇◆◆◇◇◇◆◆◆◇◇◇◇◇◇◆◆◆◇◇◇◇◇◆◆◆◇◇◆◆◆◇◇◇◇◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◆◆◆◇◇◆◆◆◆◆◆◇◆◆◇◇◇◇◆◆◆◇◇◇◇◇◆◆◆◇◇◇◇◇◆◆◆◇◆◆◆◆◆◆◆◆◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◆◆◆◇◆◆◆◇◆◆◆◆◆◇◇◇◇◆◆◆◇◇◇◇◇◆◆◆◇◇◇◇◇◆◆◆◇◇◆◆◆◆◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◆◆◆◆◆◆◆◇◆◆◆◆◆◇◇◇◇◆◆◆◇◇◇◇◇◆◆◆◇◇◇◇◇◆◆◆◇◇◆◆◆◇◇◇◇◇◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◆◆◆◆◆◆◇◇◆◆◆◆◇◇◇◇◆◆◆◇◇◇◇◇◆◆◆◇◇◇◇◆◆◆◆◇◇◇◆◆◆◇◇◇◇◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◆◆◆◆◆◇◇◇◆◆◆◇◇◇◇◇◆◆◆◇◇◇◇◆◆◆◆◇◇◇◆◆◆◇◇◇◇◆◆◆◆◇◆◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◆◆◆◆◇◇◇◇◇◇◇◇◇◇◇◆◆◆◇◇◇◇◆◆◇◆◆◆◆◆◆◆◇◇◇◇◇◆◆◆◆◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◆◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◆◇◆◆◆◆◆◇◇◇◇◇◇◇◆◆◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇

我觉得这里切割也处理的不是特别好,方正这边字母会旋转,切割处理不好会影响后面的识别率

程序他会把上面二值化的结果以1(有像素点),0(无像素点)存到二维数组中,首先如果数组一列的和为0那么就是空行,他从左向右切割,从上到下检查,首先从左到右,找到第一个字母的左端横坐标(也就是第一次数组一列不为零的横坐标),然后继续向右寻找第一个字母的右端横坐标,从上往下三个IF,

  1. 第一个是用来判断到达一个阈值以后是否应该继续向后截取(防止粘连时将两个字母当一个字母截了,)那个Estimate函数应该是用来判断向右看几格,如果几格之内找不到一个空列,就在当前位置强行截断,并记录横坐标值,

  2. 第二个是用来应对如果两个字母中间有一些没去掉的噪点,或者一两个点的时候,如果单纯用有没有空列判断,他会把这两个字母当一个字母截了。。。或者像1的if里面强行截断,截散了,所以这里如果字母宽度大于9了,且这一列只有两个点,就可以截断了

  3. 第三个是应对i和j这类,如果大于2而且出现空列,就可以直接截了

截取里面写了这三个判断,感觉自己上面说的也有些不清不楚的(早上没睡醒TAT),如果有哪里没明白可以提出来再继续讨论哈~ : P

//切割第一个字母的后竖线
`

for ($x = $tmp_x; $x < $width; ++$x) {
    $num = 0;
    for ($y = 0; $y < $height; ++$y) {
        $num += $all[$y][$x];
    }

    if ($x - $tmp_x > $yz) {
        if (!Estimate($x, $y, 'vertical', $all, $height)) {//判断是否应该继续截取
            //如果判断向后是无法找到可以停止的参照,那么就在阈值处截断,
            $end_x1 = $x;
            $tmp_x = $x;
            break;
        }
    }
    if ($num <= 2 && $x - $tmp_x > 9) {//在截取的位置宽度大于9以后如果有一行只有两个点或一个点则截断
        $end_x1 = $x + 1;
        $tmp_x = $x + 1;
        break;
    }
    if ($num == 0 && $x - $tmp_x > 2) {//有空行,且截取的宽度>2
        $end_x1 = $x;
        $tmp_x = $x;
        break;
    }
    
}

`

是的看你代码是这样的

  • 1.y轴投影为0,有空隙,直接截取
  • 2.大于宽度小于阈值选择附近比较稀疏的列截取
  • 3.直接在阈值处截取
    👍
    对了,你的字典是训练出的,还是各个角度模拟出的 ⚡️

自己当人肉打码工手动调教添加的(上课拿着台电脑在那打码2333),可以看下AddDictionary.php这个文件,比较方便的手动添加字典。

不过如果能从各种角度模拟,更有针对性的去训练它的话,可能效果更好也说不定,因为现在的字典里可能有一些冗余的数据

哦抱歉,我可能理解错你的意思,就切割这块的其他想法的话,因为也比较久了,想法上也忘得差不多了,可能给不了太多的建议,抱歉哈

不过这两天看了swoole以后我也在考虑是不是可以四个字母的对比识别用多线程并行,这样效率可能会高些吧,缩短时间

原来如此!
多线程确实可以节约3/4时间。