import tkinter标签:python,discren,image,cv2,答题卡,Label,int,Answer From: https://www.cnblogs.com/lld76/p/16717485.html
import cv2 #
from PIL import Image,ImageTk
from tkinter import filedialog #打开文件需要
import imutils
import os
import numpy
root = tkinter.Tk()
root.geometry('1000x700')
root.title('答题卡识别系统')
Label_a = tkinter.Label(root)
Label_a.place(x=0,y=0)
Label_b = tkinter.Label(root)
Label_b.place(x=510,y=20)
Label_c = tkinter.Label(root)
Label_c.place(x=510, y=270)
Label_d = tkinter.Label(root)
Label_d.place(x=650,y=500)
def enter():
filename = tkinter.filedialog.askopenfilename() # 打开文件夹
#保存图片,方便识别
photo = Image.open(filename)
photo.save('img.jpg')
#展示图片
photo = Image.open(filename).resize((500, 500)) # 打开图片
photo = ImageTk.PhotoImage(photo)
Label_a.config(image=photo)
Label_a.image=photo
#将框选内容清除,以便于下张图显示清除,否则会造成显示错误
Range.clear()
Range = []
catch_Answer = []
def rectangle():
img = cv2.imread('img.jpg')
y,x,_ = img.shape
print('原图像大小:',x,y)
if x<=500:
img = cv2.resize(img,(int(x*2),int(y*2))) #将图片宽高各除与2
elif 1000<= x:
img = cv2.resize(img,(int(x/2),int(y/2))) #将图片宽高各除与2
x, y, w, h = cv2.selectROI(img, showCrosshair=True, fromCenter=False)
screenshot = img[y:y + h, x:x + w]
print('截图区域大小,判断条件:',x,y,w,h)
#展示图
screenshot = Image.fromarray(screenshot)
screenshot = ImageTk.PhotoImage(image=screenshot)
Label_b.config(image=screenshot)
Label_b.image = screenshot
# 截屏区域
if x<=30:
x1, x2, y1, y2 = x * 2.5, (x + w) * 2.5, y * 2.5, (y + h) * 2.5
elif 30 < x <35:
x1, x2, y1, y2 = x * 5, (x + w) * 5, y * 5, (y + h) * 5
elif 35 <= x:
x1, x2, y1, y2 = x * 10, (x + w) * 10, y * 10, (y + h) * 10
Range.append((x1, x2, y1, y2)) #360 5080 3640 5940
#调用识别模块
discren('img.jpg',0)
Answer = []
def discren(path,name):
#cv2读取
# image = cv2.imread(path)
# ay0,ax0,_ = image.shape
#PIL——Image 读取
image = Image.open(path)
ax0,ay0 = image.size
#转换成cv2可以识别的图
image = numpy.asarray(image)
# 将图像扩大五倍
ax,ay = ax0*5,ay0*5
# 转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 高斯滤波
blurred = cv2.GaussianBlur(gray, (3, 3), 0)
# 自适应二值化方法
blurred = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 51, 2)
# 重塑可能用到的图像
thresh = cv2.resize(blurred, (ax, ay), cv2.INTER_LANCZOS4)
fImage = cv2.resize(image, (ax, ay), cv2.INTER_LANCZOS4)
# 均值滤波
ChQImg = cv2.blur(thresh, (40, 40))
# 二进制二值化
ChQImg = cv2.threshold(ChQImg, 30, 225, cv2.THRESH_BINARY)[1]
# 在二值图像中查找轮廓
cnts = cv2.findContours(ChQImg, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 用边缘检测绘制
cnts = cnts[1] if imutils.is_cv3() else cnts[0]
x1,x2,y1,y2 = int(Range[0][0]),int(Range[0][1]),int(Range[0][2]),int(Range[0][3])
for c in cnts:
# 计算轮廓的边界框,然后利用边界框数据计算宽高比
(x, y, w, h) = cv2.boundingRect(c)
if (w > 75 and h > 13) and x > x1 and x < x2 and y > y1 and y < y2 : # 原始数据: x>324 and x<4700 and y>3072 and y<5016
M = cv2.moments(c) # 矩形的宽高, 起点终点(划分区域)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
# 绘制中心及其轮廓
cv2.drawContours(fImage, c, -1, (0, 0, 255), 8, lineType=0)
cv2.circle(fImage, (cX, cY), 40, (255, 255, 255), -1)
if name == 0 :
# #保存题目坐标信息
Answer.append((cX, cY))
elif name == 1:
#考试答案
catch_Answer.append((cX,cY))
#框选区域
discren = fImage[y1:y2,x1:x2]
y,x,_ = discren.shape
print(y)
print('判断显示,x:',x)
if x <= 1000:
discren = cv2.resize(discren, (int(x/2), int(y/1.5)))
elif 1000 < x < 3500:
discren = cv2.resize(discren, (int(x/5), int(y/5)))
elif 3500 <= x:
discren = cv2.resize(discren,(int(x/10),int(y/10)))
#调用判断
if Answer and catch_Answer:
a = contrast(Answer, catch_Answer)
cv2.circle(discren, a, 4, (255, 255, 255), -1)
catch_Answer.clear()
#展示图
discren = Image.fromarray(discren)
discren = ImageTk.PhotoImage(image=discren)
Label_c.config(image=discren)
Label_c.image = discren
def testing():
# filename = tkinter.filedialog.askopenfilename() # 打开文件夹
# filename = filename.split('/')[::]
# print(filename)
path = 'D:/PyCharm Community Edition 2021.1.3/项目/答题卡项目/img'
paths = os.listdir(path)
for path in paths:
print('./img/'+path)
discren('./img/'+path,1)
def contrast(Answer,catch_Answer):
a = 0
for i in range(len(Answer)):
if catch_Answer[i][0] - 5 <= Answer[i][0] <= catch_Answer[i][0] + 5 and catch_Answer[i][1] - 3 <= Answer[i][1] <= catch_Answer[i][1] + 3:
a += 1
else:
if catch_Answer[i] in Answer:
a += 1
else:
print(Answer[i], catch_Answer[i])
return catch_Answer[i]
# print('一共{}道题,XX答对{},得分{}'.format(int(len(Answer)), a, a))
Label_d['text'] = '一共{}道题,XX答对{},得分{}'.format(int(len(Answer)), a, a)
tkinter.Label(root,text='框选区域').place(x=730,y=0)
tkinter.Label(root,text='识别结果').place(x=730,y=250)
tkinter.Button(root,text='答题卡模板',command=lambda:enter()).place(x=50,y=500)
tkinter.Button(root,text='框选区域',command=lambda:rectangle()).place(x=200,y=500)
tkinter.Button(root,text='识别的答题卡',command=lambda:testing()).place(x=350,y=500)
root.mainloop()