本文是对前天的文章--OpenCV+TensorFlow图片手写数字识别(附源码)进行进一步探讨:如何在原来的基础上进一步提高准确率?
上篇文章是参考别人的博客,在那篇文章最后的识别效果不是很准确,效果如下:
上面是博主对识别错误的原因猜想,归结为网络或者训练次数的原因。
后面我自己做了测试,发现并不是网络的原因,为什么呢?因为MNist数据集训练后,我使用它的测试数据验证了500张的准确率是99.6%(如下图),那么它的识别效果不应该如此。
回过头来再去测试原来的代码,如果有朋友测试过前天文章的代码,就会发现有一些明显的图片,它仍然会识别错,如下图:
是什么原因造成这样的识别错误?不是网络原因(最起码不是主要原因)。用过MNist数据集的朋友都知道它的每个数字图片都是28*28的形状如下图:
而我们通过OpenCV查找轮廓,获取外接矩形,然后截取ROI缩放到28*28进行预测,ROI图像有些是会变形的,比如下面的截取的ROI:
上面的图像的宽高比明显大于28/28=1,一个矩形缩放成正方形,图像压缩后数字容易变形扭曲,导致识别上和原始数据集中的样本数据差异较大,所以识别出错。怎么解决?调整宽高比尽量保证是1:1,先来看下原来截取ROI部分的代码:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.GaussianBlur(gray, (3, 3), 0)
ret, thresh = cv2.threshold(thresh, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
thresh_copy = thresh.copy()
_, contours, hierarchy = cv2.findContours(thresh_copy, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
num = 0
for cnt in contours:
(x, y, w, h) = cv2.boundingRect(cnt)
if w < 10 and h < 10 or w>300 or h>300:
continue
ROI = None
ROI = thresh[y-5:y+h+10, x-5:x+w+10].copy() # 获得感兴趣区域,也即每个数字的区
更改后截取ROI的代码从第8行起:
for cnt in contours:
(x, y, w, h) = cv2.boundingRect(cnt)
if w < 10 and h < 10 or w>300 or h>300:
continue
ROI = None
# 高 > 宽
if h > w:
diff = int((h - w + 10)/2)
ROI = thresh[y-5:y+h+10, x-diff:x+w+diff].copy()
# 宽 > 高
elif w > h:
diff = int((w - h + 10) / 2)
ROI = thresh[y-diff:y + h+diff, x-5:x + w+10].copy()
对比截取后的ROI:
对比测试结果:
当然调整宽高比在图像分类中应用比较广泛,因为图像分类中基本都需要训练样本图像保持同样的宽和高,识别时也需要缩放到样本大小,应尽量避免缩放后目标发生形变。
手写数字调整宽高比只是其中一种手段,你也可以通过图像变换扩充数据,提高识别率,以下为猫的图片进行简单变换后的效果,其他图片类似。
关注【OpenCV与AI深度学习】
长按或者扫描下面二维码即可关注