最近做了一个基于opencv的试卷识别项目,在此分享一下。
文末附有源码。
视频观看:
20211212
主界面:
选择图片后:
识别以后:
识别完成以后会自动截取不同的题目,然后保持到不同的文件夹中,分数会单独的保存到一个txt文本中。
手写数字数据集:
手写数字识别代码,建议不要直接用mnist手写数字数据集,因为使用这个数据集训练出来的网络,根本识别不了我自己写的数字,亲身体验!没办法,我只好自己制作了手写数据集,其实很简单。数据集如下所示:
其余的都差不多是这样,就不过多展示了。需要注意的是图片上面只有数字是黑色的,这样方面提取出数字,如果写错了,可以用一些图像编辑的软件将错的部分涂成白色即可,就和上图一样。
手写数字识别代码:
import tensorflow as tf
import cv2 as cv
import numpy as np
from get_data import *
model=tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128,activation='relu'),
tf.keras.layers.Dense(128,activation='relu'),
tf.keras.layers.Dense(128,activation='relu'),
tf.keras.layers.Dense(10,activation='softmax')
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
model.fit(x_train,y_train,batch_size=32,epochs=10,validation_split=0.1,validation_freq=1)
model.save('mode_2.h5')
是不是很简单呢?请看第四行:
from get_data import *
关于图像处理的部分在get_data.py这个代码中,下面是get_data.py的代码。
get_data.py
import numpy as np
import cv2 as cv
x_train=[]
y_train=[]
aa=9
for aa in range(10):
src=cv.imread('data/{}.jpg'.format(aa))
gray=cv.cvtColor(src,cv.COLOR_BGR2GRAY)
thred=np.where(gray>150,255,0).astype('uint8')
thred=255-thred
#开闭运算
k = np.ones((3, 3), np.uint8)
#thred=cv.dilate(thred,k)
thred = cv.morphologyEx(thred, cv.MORPH_CLOSE, k)
cnts=cv.findContours(thred,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)[0]
print(len(cnts))
for i in cnts:
area = cv.contourArea(i)
if aa!=1:
b=20
else:b=15
if area>=b:
x, y, w, h = cv.boundingRect(i)
cv.rectangle(src,(x,y),(x+w,y+h),(0,0,255),2)
lkuo=thred[y:y+h,x:x+w]
da = max(h, w)
rate = da / 40
ro = cv.resize(lkuo, (int(w / rate), int(h / rate)))
h, w = ro.shape
t, b = int((43 - h) / 2), 43 - h - int((43 - h) / 2)
l, r = int((43 - w) / 2), 43 - w - int((43 - w) / 2)
ro = cv.copyMakeBorder(ro, t, b, l, r, cv.BORDER_CONSTANT, value=0)
ro = cv.resize(ro, (40, 40))
ro = np.where(ro > 0, 255, 0).astype('float32')
ro = ro / 255
x_train.append(ro)
y_train.append(aa)
x_train=np.array(x_train).astype('float32')
y_train=np.array(y_train).astype('float32')
y_train=np.reshape(y_train,(y_train.shape[0],1))
np.random.seed(1)
np.random.shuffle(x_train)
np.random.seed(1)
np.random.shuffle(y_train)
print(y_train)
if __name__=='__main__':
pass
好了,到这里手写数字识别的部分已经完结了,后面可以直接调用我们训练好的网络就可以识别了,下面是关于试卷检测的代码:
import time
import cv2 as cv
import numpy as np
from tensorflow.keras.models import load_model
import os
model =load_model('mode.h5')
def zb(img,a):
# b=np.sort(a,axis=0)
idx = np.argsort(a, axis=0)
aa = a[idx[:, 0]]
idx12=np.argsort(aa[:2],axis=0)
idx34 = np.argsort(aa[2:], axis=0)