原文博客: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)