PyCosmed数字识别

博客详细介绍了PyCosmed数字识别的过程,包括图像预处理(灰度化、二值化)、图像分割策略来避免数字相连、计算图像的Hash码以及识别结果展示。在识别结果部分,展示了分割数据集和原始图像下的不同效果。最后提到尝试使用主成分分析(PCA)但未发现明显可分性。
摘要由CSDN通过智能技术生成

PyCosmed数字识别程序回顾与优化。


图像预处理

首先要将截取的图片转为灰度图像,然后绘制灰度直方图,确定二值化阈值150,然后进行二值化:

在这里插入图片描述

# 获取图像
def get_img(index):
    img = Image.open("E:\\Python\\PyCosmed\\v3.0\DIGIT2\\"+str(index)+".png")
    plt.subplot(221)
    plt.imshow(img)
    return img

# 分析灰度直方图,从而选择合适的二值化阈值
def gray_hist(img):
    img_arr = np.array(img.convert('L'))    #  convert - 转换图像格式   L - 八位黑白像素
                                            #  array - image格式转为array数组
    plt.subplot(223)
    plt.imshow(img_arr)

    img_arr = img_arr.flatten()             #  flatten - 转化为一维数组
    plt.subplot(222)
    plt.hist(img_arr,bins=256)              #  hist - 绘制直方图  bins - 条形数
    plt.ylim((0,50))

# 图像二值化
def binarize(img, threshold=threshold):
    """二值化"""
    img = img.convert('L')
    table = []
    for i in range(256):
        if i < threshold:
            table.append(0)
        else:
            table.append(1)
    bin_img = img.point(table, '1')
    plt.subplot(222)
    plt.imshow(bin_img)
    return bin_img

图像分割

加入分割宽度机制,避免数字相连情况:

在这里插入图片描述

分割后的图像集:

在这里插入图片描述

def vertical_cut(img):
    """纵向切割"""
    px = list(np.sum(np.array(img) == 0, axis=0))
    py = list(np.sum(np.array(img) == 0, axis=1))

    # 列表保存像素累加值大于0的列
    x0 = []
    for x in range(len(px)):
        if px[x] > 0:
            x0.append(x)
    y0 = []
    for y in range(len(py)):
        if py[y] > 1:
            y0.append(y)

    # 找出边界
    cut_list = [x0[0]]
    for i in range(1, len(x0)):
        if abs(x0[i] - x0[i - 1]) > 1:
            if abs(x0[i-1] - cut_list[-1]) < 10:
                cut_list.extend([x0[i - 1]+1, x0[i]])
            elif abs(x0[i-1] - cut_list[-1]) < 16:
                cut_list.extend([x0[i-1]+1, x0[i-1]+8])
                cut_list.extend([x0[i-1]+8, x0[i]])
            elif abs(x0[i-1] - cut_list[-1]) < 24:
                cut_list.extend([x0[i-1]+1, x0[i-1]+8])
                cut_list.extend([x0[i-1]+8, x0[i-1]+16])
                cut_list.extend([x0[i-1]+16, x0[i]])
    if abs(x0[-1] - cut_list[-1]) < 10:
        cut_list.append(x0[-1]+1)
    elif abs(x0[-1] - cut_list[-1]) < 17:
        cut_list.extend([cut_list[-1]+8, cut_list[-1]+8])
        cut_list.append(x0[-1]+1)
    elif abs(x0[-1] - cut_list[-1]) < 25:
        cut_list.extend([cut_list[-1]+8, cut_list[-1]+8])
        cut_list.extend([cut_list[-1]+8, cut_list[-1]+8])
        cut_list.append(x0[-1]+1)

    cut_list_y = [y0[0]]
    cut_list_y.append(y0[-1]+1)

    cut_imgs = []
    # 切割顺利的话应该是整对
    if len(cut_list) % 2 == 0:
        for i in range(len(cut_list) // 2):
            cut_img = img.crop([cut_list[i * 2], cut_list_y[0], cut_list[i * 2 + 1], cut_list_y[1]])
            plt.imshow(cut_img)
        return cut_imgs
    else:
        print('Vertical cut failed.')
        return

计算Hash码

分割后的图像被统一缩放到8*15的大小,然后计算其Hash码,并提取每个字符的标准Hash码:

# 标准Hash码
hash_vals = {
    "0": "110000111000000110011001100110000001100000111100001111000011110000111100001111000001100010011001100110011000000111000011",
    "1": "111000000000000000000000111110001111100011111000111110001111100011111000111110001111100011111000111110001111100011111000",
    "2": "100000111000000111110001111110011111100111111001111110011111000111110011111000111100011111001111100111110000000000000000",
    "3": "100000111000000111111000111111001111110011111001110000011100000111111000111111001111110011111100111110000000000110000011",
    "4": "111100011111000111100001111000011100100111001001100110011001100100111001000000000000000011111001111110011111100111111001",
    "5": "110000001100000010011111100111111001111110011111100000111000000011111000111111001111110011111100111110000000000100000011",
    "6": "111110011110000111000111110011111001111110011111000000010000000100011000001111000011110000011100100110001000000111000011",
    "7": "000000000000000011111001111110011111100111110011111100111111001111100111111001111100011111001111110011111000111110011111",
    "8": "111000111100000110011000100111001001110010001001110000011100000110001000100111000001110000011100100111001000000011000011", 
    "9": "110000111000000110011001000110000011110000111100000111001001100010000000111010001111100111110001111000111000011110001111",
    ".": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000011100000"
}

def hashing(img):
    """计算哈希值"""
    img = img.resize((8, 15), Image.LANCZOS)
    px = np.array(img).flatten()
    hash_val = (px > px.mean()).astype(int)
    hash_val = ''.join(str(e) for e in hash_val)
    return hash_val

def hamming(hash1, hash2):
    """计算汉明距离"""
    if len(hash1) != len(hash2):
        print('hash1: ', hash1)
        print('hash2: ', hash2)
        raise ValueError("Undefined for sequences of unequal length")

    return sum(i != j for i, j in zip(hash1, hash2))

def recognize(img):
    """识别结果"""
    # img = img.convert('L')
    # img = binarize(img)
    # chars = vertical_cut(img)

    # 相近度列表
    nearness = {}
    # expr = ''
    # for char in chars:
    hash_val = hashing(img)
    for h in hash_vals:
        nearness[h] = hamming(hash_val, hash_vals[h])
    expr = sorted(nearness.items(), key=lambda d: d[1])[0][0]

    return expr

识别结果

分割数据集下的识别结果:

在这里插入图片描述

原始图像下的识别结果:

One More Thing

另外对分割图像集进行个主成分分析(PCA),在第一主成分和第二主成分平面上不具有明显的可分性,故没有进一步研究:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值