牛奶盒喷码字符识别(基于opencv)————(二)投影法字符分割

牛奶盒喷码字符识别(基于opencv)————(二)投影法字符分割

效果:

由于图片横纵坐标分明,故可采用投影法进行切割
老规矩线上图:

在这里插入图片描述
在这里插入图片描述

要做到切割准确率高,给大家做以下难点分析:(避坑指南)
1.比如20和55这些数字挨得太近,导致会识别成一个字符
2.如果最下一行有黑像素或者最右一列有黑像素,会切割失败,是源算法小缺陷
3.膨胀不能太多,不然会导致第一行第二行无法区分

源代码参考博客:

https://blog.csdn.net/Tuzi294/article/details/79959199

以下是我的改进:

1.对于20,55的分割

可以看到 源代码在对于20,54的处理上直接分割,输出end_j-star_j之后发现,着切割失败的三组数有明显的特征,那就是end_j-star_j大于100了,所以我们稍加判断(注意逻辑,有点打脑壳)
+8 是个经验数值,使我的分割更好
注意除法需要浮点型,所以/2.0
注意像素不能为浮点型,所以需要使用 math.floor取整
使用math 记得 import math
在这里插入图片描述

 elif(data[start: end, j].all() and start_j >= 0):
            if(end_j - start_j >= min_val_word and end_j - start_j<100):
                print(end_j - start_j)
                tmp = data[start:end, start_j: end_j]
                im2save =cv2.resize(tmp, (dsize,dsize)) #归一化处理
                cv2.imwrite(root + '%d.png' % number, im2save) 
                number += 1
            elif(end_j - start_j >= 100):
                print(end_j - start_j)
                tmp1 = data[start:end, start_j: math.floor((start_j + end_j)/2.0+8)]
                tmp2 = data[start:end, math.floor((start_j + end_j)/2.0+8): end_j]
                im2save1 =cv2.resize(tmp1, (dsize,dsize))
                im2save2 =cv2.resize(tmp2, (dsize,dsize))#归一化处理
                cv2.imwrite(root + '%d.png' % number, im2save1) 
                number += 1
                cv2.imwrite(root + '%d.png' % number, im2save2) 
                number += 1
            start_j, end_j = -1, -1

结果:
在这里插入图片描述

2.对于末尾像素处理

通读算法的同学可能理解到了,原算法是当有白色像素出现时才进行判断是否要切割。那么如果我图片的最后一点是黑像素的话,就会倒是直接不切割例如这种(这个逻辑也有点打脑壳)
在这里插入图片描述
所以我们稍加改进
切割行:

 if(not data[i].all() and start_i < 0): #有黑像素为0 nor后为1
        start_i = i
    elif(not data[i].all()):
        end_i = i
        if(end_i == len_x - 1 and end_i - start_i >= min_val): #修复bug 为了防止底部为黑像素,只能放置在这行
            rowPairs.append((start_i, end_i))

列切割:

if(not data[start: end, j].all() and start_j < 0):
            start_j = j
        elif(not data[start: end, j].all()):
             end_j = j
             if(end_j == len_y - 1 and end_j - start_j >= min_val_word): #修复bug 为了防止右边为黑像素,只能放置在这行
                tmp3 = data[start:end, start_j: end_j]
                tmp3 = cv2.erode(tmp3, kernel)
                im2save =cv2.resize(tmp3, (dsize,dsize)) #归一化处理
                cv2.imwrite(root + '%d.png' % number, im2save) 
                number += 1
                start_j, end_j = -1, -1              #我的天 这个 bug找了好久,防止右边黑像素

3.两次膨胀

由于为了让行分割并且尽量让图片连续,我膨胀核选的较小
但为了做匹配效果更好,在保存图片的时候我又做了一次膨胀
在这里插入图片描述
最终切割的效果就是上面提到的,为了做匹配,全部resize为(88,88)
为什么88?因为吉利啊,多少都可以,我也是随便设置的。
下一节该进行识别啦

猜你喜欢

转载自blog.csdn.net/qq_38269418/article/details/83663521