手写数字体识别,用保存的模型跑自己的图片

该博客介绍了如何使用OpenCV处理图片,找到手写数字的边界,并将其转换为MNIST格式,以便用预训练的Keras模型进行预测。通过找到图像中的轮廓并调整尺寸,将手写数字标准化,然后进行预测并显示结果。
摘要由CSDN通过智能技术生成

原文博客:https://blog.csdn.net/X_m_w/article/details/101056156
模型训练:https://blog.csdn.net/X1996_/article/details/108883710
这里是用训练的模型直接来预测,模型训练可参考上篇文章
主要是用opencv把图片处理成需要的图片格式,然后预测
输入图片:
在这里插入图片描述输出:
在这里插入图片描述

import cv2
import numpy as np
from keras import models
# 反相灰度图,将黑白阈值颠倒


def accessPiexl(img):
    height = img.shape[0]
    width = img.shape[1]
    for i in range(height):
       for j in range(width):
           img[i][j] = 255 - img[i][j]
    return img


# 反相二值化图像
def accessBinary(img, threshold=128):
    img = accessPiexl(img)
    # 边缘膨胀,不加也可以
    kernel = np.ones((3, 3), np.uint8)
    img = cv2.dilate(img, kernel, iterations=1)
    _, img = cv2.threshold(img, threshold, 0, cv2.THRESH_TOZERO)
    return img


# 利用轮廓找位置,不需要行对齐
def findBorderContours(path, maxArea=50):
    img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
    img = accessBinary(img)
    _, contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    borders = []
    for contour in contours:
        # 将边缘拟合成一个边框
        x, y, w, h = cv2.boundingRect(contour)
        if w*h > maxArea:
            border = [(x, y), (x+w, y+h)]
            borders.append(border)
    return borders


# 根据边框转换为MNIST格式
def transMNIST(path, borders, size=(28, 28)):
    imgData = np.zeros((len(borders), size[0], size[0], 1), dtype='uint8')
    img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
    img = accessBinary(img)
    for i, border in enumerate(borders):
        borderImg = img[border[0][1]:border[1][1], border[0][0]:border[1][0]]
        # 根据最大边缘拓展像素,扩大边缘边框,固定值0填充,变成正方形
        # top, bottom, left, right:上下左右要扩展的像素数
        extendPiexl = (max(borderImg.shape) - min(borderImg.shape)) // 2
        # 扩大多少由你的原图数字大小决定,使数字处在图片中间,图片越大,扩大的就大一些
        targetImg = cv2.copyMakeBorder(borderImg, 30, 30, extendPiexl + 30, extendPiexl + 30, cv2.BORDER_CONSTANT)
        targetImg = cv2.resize(targetImg, size)
        # 增加一个维度 28*28*1,我是这样理解的,相当于reshape吧
        targetImg = np.expand_dims(targetImg, axis=-1)
        imgData[i] = targetImg
    return imgData


# 预测手写数字
def predict(modelpath, imgData):
    model = models.load_model(modelpath)
    img = imgData.astype('float32') / 255
    results = model.predict(img)
    result_number = []
    for result in results:
        result_number.append(np.argmax(result))
    return result_number


# 显示结果及边框
def showResults(path, borders, results=None):
    img = cv2.imread(path)
    for i, border in enumerate(borders):
        cv2.rectangle(img, border[0], border[1], (0, 0, 255))
        if results:
            cv2.putText(img, str(results[i]), border[0], cv2.FONT_HERSHEY_COMPLEX, 0.8, (0, 255, 0), 1)
    cv2.imshow('test', img)


path = '11.png'
model = 'model.h5'
borders = findBorderContours(path)
imgData = transMNIST(path, borders)
results = predict(model, imgData)
showResults(path, borders, results)

cv2.waitKey(0)
  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值