前言:大家好,我是一名高中物理教师,比较喜欢学习编程,由于平时批改作业比较忙,所以突然冒出个想法,做个摄像头答题卡识别就会减轻我平时批改作业的很多负担,特别是选择题,重复性的劳动,意义不大,如果用机器代替工作那该多好呀,网上一搜,有很多教程,但是都不太满意,所以我趁着躲避新冠在家隔离的这段时间,边学边做,终于做成了,还没开学,等开学了就去试试,通过博客园,把我的心得分享给大家!
首先,我学习了三本书,python3.7 Pyqt5 opencv ,对我的帮助很大,感谢这几本书的作者。
第二,软件环境: anaconda(python3.7)+pycharm +pqty5 + opencv4.2.0+Excel2016 + 一堆库
第三,硬件环境: 高拍仪(1000W像素,分辨率1920*1080)
、
第四,实现的功能: ①识别选择题
②识别名字(用汉字区位码)
③识别考号
④计算得分
⑤统计全班的每题得分率
⑥选择题柱状图
第五,答题卡设置要求:横平竖直,格子的宽高相同(我设置的是64行,23列),便于分割!
第六,识别部分:① 打开摄像头,捕获一帧。
② 对图像四角变换
④ 把图像分割,计算每个格子中涂卡面积占比
⑤ 输出选项到列表
具体代码:
#① 打开摄像头,捕获一帧。这里用了定时器,否则会卡 self.timer = QTimer() # 初始化定时器 self.timer.timeout.connect(self.time)#定时器信号 self.cap = cv2.VideoCapture(0) #打开视频 self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1366)#图像宽 self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 768) #图像高 self.timer.start(1)
self.ret,self.frame = self.cap.read() #读取内存中的帧
# ②对图像四角变换 if (self.cap.isOpened()): M = cv2.getRotationMatrix2D((self.frame.shape[1] / 2, self.frame.shape[0] / 2), -90, 0.8) # 获得旋转矩阵 self.frame = cv2.warpAffine(self.frame, M, (self.frame.shape[1], self.frame.shape[0])) # 旋转90度 gray = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY) # 转换为灰度图像 blurred = cv2.GaussianBlur(gray, (3, 3), 0) # 高斯滤波1 edged = cv2.Canny(blurred, 10, 100) # 边缘检测 #cv2.imshow(\'edged\', edged) cnts = cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 查找轮廓 cnts = cnts[1] if imutils.is_cv2() else cnts[0] # # 用以区分OpenCV2.4和OpenCV3 docCnt = None if len(cnts) > 0: # 确保至少有一个轮廓被找到 cnts = sorted(cnts, key=cv2.contourArea, reverse=True) # 将轮廓按大小降序排序 for c in cnts: # 对排序后的轮廓循环处理 peri = cv2.arcLength(c, True) # 周长# 获取近似的轮廓 approx = cv2.approxPolyDP(c, 0.02 * peri, True) # 如果近似轮廓有四个顶点,那么就认为找到了答题卡 if len(approx) == 4: docCnt = approx break self.framexianshi = self.frame.copy() # 复制原图 self.paper = four_point_transform(self.frame, docCnt.reshape(4, 2)) # 对原始图像进行四点透视变换 self.framexianshi = cv2.drawContours(self.framexianshi, cnts, 0, (0, 255, 0), 2) #画绿边轮廓
#③ 形态学变换(灰度 反向二值化 开运算 膨胀)
paper = cv2.resize(self.paper, (1196, 1946)) # 重新缩放指定尺寸统一尺寸 便于分割
#cv2.imshow(\'suofanghou\', paper)
hanggao = paper.shape[0]
hanggao_1 = hanggao // 64
liekuan = paper.shape[1]
liekuan_1 = liekuan // 23
huidu = cv2.cvtColor(paper, cv2.COLOR_BGR2GRAY) # 灰度图
t, erzhihua = cv2.threshold(huidu, 95, 255, cv2.THRESH_BINARY_INV) # 反向二值化
# cv2.imshow(\'erzhihua\', erzhihua)
k = np.ones((8, 8), np.uint8) # 开运算
kaiyunsuan = cv2.morphologyEx(erzhihua, cv2.MORPH_OPEN, k) # 开运算
# cv2.imshow(\'kaiyunsuan\', kaiyunsuan)
peng = np.ones((3, 3), np.uint8)
kaiyunsuan = cv2.dilate(kaiyunsuan, peng) # 膨胀
#分割后的图像 for heng in range(0, hanggao + hanggao_1, hanggao_1): # 显示分割的横线竖线 paper = cv2.line(paper, (0, heng), (liekuan, heng), (0, 0, 255), 1) # 显示分割的横线竖线 for j in range(0, liekuan, liekuan_1): # 显示分割的横线竖线 paper = cv2.line(paper, (j, 0), (j, liekuan), (0, 0, 255), 1) # 显示分割的横线竖线 cv2.imshow(\'paperbianxian1\', paper)
# ④ 涂卡面积的占比 这里应该有更好的办法,我只用了这个办法来识别,把感兴趣区域截取更小一些或许更好,这样也完全够了!姓名与考号与此法类似我就不再重复了!
# 插入列表时候多选我使用了字典处理的
for ii in range(0, 5): # 识别1-5 的选择题 for jj in range(17, 21): lie = ii * liekuan_1 hang = jj * hanggao_1 baisemianji = cv2.countNonZero(kaiyunsuan[hang: hang + hanggao_1, lie: lie + liekuan_1]) # 涂卡的面积 quanbumianji = hanggao_1 * liekuan_1 # 全部的面积 ratio = baisemianji * 100 / quanbumianji # 涂卡比率; 比例; # print(ratio) if (ratio > self.mianjibaifenbi): if jj == 17: # print(f\'第 {ii+1} 题选:A \') self.charuxuan[ii + 1].append(\'A\') elif jj == 18: self.charuxuan[ii + 1].append(\'B\') elif jj == 19: self.charuxuan[ii + 1].append(\'C\') elif jj == 20: self.charuxuan[ii + 1].append(\'D\') self.gengxinruxuan[ii + 1].append(\'\'.join(self.charuxuan[ii + 1])) for ii in range(6, 11): # 识别6-10 的选择题 for jj in range(17, 21): lie = ii * liekuan_1 hang = jj * hanggao_1 baisemianji = cv2.countNonZero(kaiyunsuan[hang: hang + hanggao_1, lie: lie + liekuan_1]) quanbumianji = kaiyunsuan[hanggao_1: hanggao_1 + hanggao_1, liekuan_1: liekuan_1 + liekuan_1].shape[0] * \ erzhihua[hang: hang + hanggao_1, lie: lie + liekuan_1].shape[1] ratio = baisemianji * 100 / quanbumianji # 比率; 比例; if (ratio > self.mianjibaifenbi): if jj == 17: self.charuxuan[ii].append(\'A\') elif jj == 18: self.charuxuan[ii].append(\'B\') elif jj == 19: self.charuxuan[ii].append(\'C\') elif jj == 20: self.charuxuan[ii].append(\'D\') self.gengxinruxuan[ii].append(\'\'.join(self.charuxuan[ii])) for ii in range(12, 17): # 识别11-15 的选择题 for jj in range(17, 21): lie = ii * liekuan_1 hang = jj * hanggao_1 baisemianji = cv2.countNonZero(kaiyunsuan[hang: hang + hanggao_1, lie: lie + liekuan_1]) quanbumianji = kaiyunsuan[hanggao_1: hanggao_1 + hanggao_1, liekuan_1: liekuan_1 + liekuan_1].shape[0] * \ erzhihua[hang: hang + hanggao_1, lie: lie + liekuan_1].shape[1] ratio = baisemianji * 100 / quanbumianji # 比率; 比例; # print(ratio) if (ratio > self.mianjibaifenbi): if jj == 17: self.charuxuan[ii - 1].append(\'A\') elif jj == 18: self.charuxuan[ii - 1].append(\'B\') elif jj == 19: self.charuxuan[ii - 1].append(\'C\') elif jj == 20: self.charuxuan[ii - 1].append(\'D\') self.gengxinruxuan[ii - 1].append(\'\'.join(self.charuxuan[ii - 1])) for ii in range(18, 23): # 识别16-20 的选择题 for jj in range(17, 21): lie = ii * liekuan_1 hang = jj * hanggao_1 baisemianji = cv2.countNonZero(kaiyunsuan[hang: hang + hanggao_1, lie: lie + liekuan_1]) quanbumianji = kaiyunsuan[hanggao_1: hanggao_1 + hanggao_1, liekuan_1: liekuan_1 + liekuan_1].shape[0] * \ erzhihua[hang: hang + hanggao_1, lie: lie + liekuan_1].shape[1] ratio = baisemianji * 100 / quanbumianji # 比率; 比例; if (ratio > self.mianjibaifenbi): if jj == 17: self.charuxuan[ii - 2].append(\'A\') elif jj == 18: self.charuxuan[ii - 2].append(\'B\') elif jj == 19: self.charuxuan[ii - 2].append(\'C\') elif jj == 20: self.charuxuan[ii - 2].append(\'D\') self.gengxinruxuan[ii - 2].append(\'\'.join(self.charuxuan[ii - 2])) self.xuan = list(self.gengxinruxuan.values()) # 字典变成二维列表 self.xuan = list(chain.from_iterable(self.xuan)) # 二维列表变成一维 print(self.xuan) self.tishu = int(self.lineEdit_tishu.text()) self.xuan = self.xuan[: self.tishu] # 切片除题目数量 self.xuan[self.tishu:] = \' \' self.xuan = self.xuan[0:20]
第七,答案处理:① 把答案输出到列表1
② 把学生选项输出到列表2
③ 对比两个列表的元素 判断正误
#① 判断正确与否是请教QQ群里面的大神,我觉得每次请教可以用红包的方式来请教,虽然都差钱,但是每次你花10元-20元的红包来请教,一来你耽误了别人的宝贵时间,二来别人看你的问题给你解答要动脑筋的,我觉得付费是理所当然的 for i in range(len(self.answer)): dd = set(self.answer[i].upper()) xx = set(self.xuan[i].upper()) if xx == dd and self.answer[i] != \'\': self.right = self.right + 1 if i == 0: self.lineEdit_001.setStyleSheet("color:rgb(0, 170, 0)") self.label_001.setText(\'第1题√ \') self.label_001.setStyleSheet("color: rgb(0, 170, 0)") elif i == 1: self.lineEdit_002.setStyleSheet("color:rgb(0, 170, 0)") self.label_002.setText(\'第2题√ \') self.label_002.setStyleSheet("color:rgb(0, 170, 0)") elif i == 2: self.lineEdit_003.setStyleSheet("color:rgb(0, 170, 0)") self.label_003.setText(\'第3题√ \') self.label_003.setStyleSheet("color:rgb(0, 170, 0)") elif i == 3: self.lineEdit_004.setStyleSheet("color:rgb(0, 170, 0)") self.label_004.setText(\'第4题√ \') self.label_004.setStyleSheet("color:rgb(0, 170, 0)") elif i == 4: self.lineEdit_005.setStyleSheet("color:rgb(0, 170, 0)") self.label_005.setText(\'第5题√ \') self.label_005.setStyleSheet("color:rgb(0, 170, 0)") elif i == 5: self.lineEdit_006.setStyleSheet("color:rgb(0, 170, 0)") self.label_006.setText(\'第6题√ \') self.label_006.setStyleSheet("color:rgb(0, 170, 0)") elif i == 6: self.lineEdit_007.setStyleSheet("color:rgb(0, 170, 0)") self.label_007.setText(\'第7题√ \') self.label_007.setStyleSheet("color:rgb(0, 170, 0)") elif i == 7: self.lineEdit_008.setStyleSheet("color:rgb(0, 170, 0)") self.label_008.setText(\'第8题√ \') self.label_008.setStyleSheet("color:rgb(0, 170, 0)") elif i == 8: self.lineEdit_009.setStyleSheet("color:rgb(0, 170, 0)") self.label_009.setText(\'第9题√ \') self.label_009.setStyleSheet("color:rgb(0, 170, 0)") elif i == 9: self.lineEdit_010.setStyleSheet("color:rgb(0, 170, 0)") self.label_010.setText(\'10题√ \') self.label_010.setStyleSheet("color:rgb(0, 170, 0)") elif i == 10: self.lineEdit_011.setStyleSheet("color:rgb(0, 170, 0)") self.label_011.setText(\'11题√ \') self.label_011.setStyleSheet("color:rgb(0, 170, 0)") elif i == 11: self.lineEdit_012.setStyleSheet("color:rgb(0, 170, 0)") self.label_012.setText(\'12题√ \') self.label_012.setStyleSheet("color:rgb(0, 170, 0)") elif i == 12: self.lineEdit_013.setStyleSheet("color:rgb(0, 170, 0)") self.label_013.setText(\'13题√ \') self.label_013.setStyleSheet("color:rgb(0, 170, 0)") elif i == 13: self.lineEdit_014.setStyleSheet("color:rgb(0, 170, 0)") self.label_014.setText(\'14题√ \') self.label_014.setStyleSheet("color:rgb(0, 170, 0)") elif i == 14: self.lineEdit_015.setStyleSheet("color:rgb(0, 170, 0)") self.label_015.setText(\'15题√ \') self.label_015.setStyleSheet("color:rgb(0, 170, 0)") elif i == 15: self.lineEdit_016.setStyleSheet("color:rgb(0, 170, 0)") self.label_016.setText(\'16题√ \') self.label_016.setStyleSheet("color:rgb(0, 170, 0)") elif i == 16: self.lineEdit_017.setStyleSheet("color:rgb(0, 170, 0)") self.label_017.setText(\'17题√ \') self.label_017.setStyleSheet("color:rgb(0, 170, 0)") elif i == 17: self.lineEdit_018.setStyleSheet("color:rgb(0, 170, 0)") self.label_018.setText(\'18题√ \') self.label_018.setStyleSheet("color:rgb(0, 170, 0)") elif i == 18: self.lineEdit_019.setStyleSheet("color:rgb(0, 170, 0)") self.label_019.setText(\'19题√ \') self.label_019.setStyleSheet("color:rgb(0, 170, 0)") elif i == 19: self.lineEdit_020.setStyleSheet("color:rgb(0, 170, 0)") self.label_020.setText(\'20题√ \') self.label_020.setStyleSheet("color:rgb(0, 170, 0)") elif (xx.issubset(dd) == True) and (dd.difference(xx) != set()) and (self.answer[i] != \'\') and (self.xuan[i] != \'\'): self.bandu = self.bandu + 1 if i == 0: self.lineEdit_001.setStyleSheet("color:rgb(255, 0, 255)") self.label_001.setText(\'第1题乄 \') self.label_001.setStyleSheet("color: rgb(255, 0, 255)") elif i == 1: self.lineEdit_002.setStyleSheet("color:rgb(255, 0, 255)") self.label_002.setText(\'第2题乄 \') self.label_002.setStyleSheet("color:rgb(255, 0, 255)") elif i == 2: self.lineEdit_003.setStyleSheet("color:rgb(255, 0, 255)") self.label_003.setText(\'第3题乄 \') self.label_003.setStyleSheet("color:rgb(255, 0, 255)") elif i == 3: self.lineEdit_004.setStyleSheet("color:rgb(255, 0, 255)") self.label_004.setText(\'第4题乄 \') self.label_004.setStyleSheet("color:rgb(255, 0, 255)") elif i == 4: self.lineEdit_005.setStyleSheet("color:rgb(255, 0, 255)") self.label_005.setText(\'第5题乄 \') self.label_005.setStyleSheet("color:rgb(255, 0, 255)") elif i == 5: self.lineEdit_006.setStyleSheet("color:rgb(255, 0, 255)") self.label_006.setText(\'第6题乄 \') self.label_006.setStyleSheet("color:rgb(255, 0, 255)") elif i == 6: self.lineEdit_007.setStyleSheet("color:rgb(255, 0, 255)") self.label_007.setText(\'第7题乄 \') self.label_007.setStyleSheet("color:rgb(255, 0, 255)") elif i == 7: self.lineEdit_008.setStyleSheet("color:rgb(255, 0, 255)") self.label_008.setText(\'第8题乄 \') self.label_008.setStyleSheet("color:rgb(255, 0, 255)") elif i == 8: self.lineEdit_009.setStyleSheet("color:rgb(255, 0, 255)") self.label_009.setText(\'第9题乄 \') self.label_009.setStyleSheet("color:rgb(255, 0, 255)") elif i == 9: self.lineEdit_010.setStyleSheet("color:rgb(255, 0, 255)") self.label_010.setText(\'10题乄 \') self.label_010.setStyleSheet("color:rgb(255, 0, 255)") elif i == 10: self.lineEdit_011.setStyleSheet("color:rgb(255, 0, 255)") self.label_011.setText(\'11题乄 \') self.label_011.setStyleSheet("color:rgb(255, 0, 255)") elif i == 11: self.lineEdit_012.setStyleSheet("color:rgb(255, 0, 255)") self.label_012.setText(\'12题乄 \') self.label_012.setStyleSheet("color:rgb(255, 0, 255)") elif i == 12: self.lineEdit_013.setStyleSheet("color:rgb(255, 0, 255)") self.label_013.setText(\'13题乄 \') self.label_013.setStyleSheet("color:rgb(255, 0, 255)") elif i == 13: self.lineEdit_014.setStyleSheet("color:rgb(255, 0, 255)") self.label_014.setText(\'14题乄 \') self.label_014.setStyleSheet("color:rgb(255, 0, 255)") elif i == 14: self.lineEdit_015.setStyleSheet("color:rgb(255, 0, 255)") self.label_015.setText(\'15题乄 \') self.label_015.setStyleSheet("color:rgb(255, 0, 255)") elif i == 15: self.lineEdit_016.setStyleSheet("color:rgb(255, 0, 255)") self.label_016.setText(\'16题乄 \') self.label_016.setStyleSheet("color:rgb(255, 0, 255)") elif i == 16: self.lineEdit_017.setStyleSheet("color:rgb(255, 0, 255)") self.label_017.setText(\'17题乄 \') self.label_017.setStyleSheet("color:rgb(255, 0, 255)") elif i == 17: self.lineEdit_018.setStyleSheet("color:rgb(255, 0, 255)") self.label_018.setText(\'18题乄 \') self.label_018.setStyleSheet("color:rgb(255, 0, 255)") elif i == 18: self.lineEdit_019.setStyleSheet("color:rgb(255, 0, 255)") self.label_019.setText(\'19题乄 \') self.label_019.setStyleSheet("color:rgb(255, 0, 255)") elif i == 19: self.lineEdit_020.setStyleSheet("color:rgb(255, 0, 255)") self.label_020.setText(\'20题乄 \') self.label_020.setStyleSheet("color:rgb(255, 0, 255)") elif self.answer[i] != \'\' : self.wrong = self.wrong + 1 if i == 0: self.lineEdit_001.setStyleSheet("color:rgb(255, 0, 0)") self.label_001.setText(\'第1题× \') self.label_001.setStyleSheet("color: rgb(255, 0, 0)") elif i == 1: self.lineEdit_002.setStyleSheet("color:rgb(255, 0, 0)") self.label_002.setText(\'第2题× \') self.label_002.setStyleSheet("color:rgb(255, 0, 0)") elif i == 2: self.lineEdit_003.setStyleSheet("color:rgb(255, 0, 0)") self.label_003.setText(\'第3题× \') self.label_003.setStyleSheet("color:rgb(255, 0, 0)") elif i == 3: self.lineEdit_004.setStyleSheet("color:rgb(255, 0, 0)") self.label_004.setText(\'第4题× \') self.label_004.setStyleSheet("color:rgb(255, 0, 0)") elif i == 4: self.lineEdit_005.setStyleSheet("color:rgb(255, 0, 0)") self.label_005.setText(\'第5题× \') self.label_005.setStyleSheet("color:rgb(255, 0, 0)") elif i == 5: self.lineEdit_006.setStyleSheet("color:rgb(255, 0, 0)") self.label_006.setText(\'第6题× \') self.label_006.setStyleSheet("color:rgb(255, 0, 0)") elif i == 6: self.lineEdit_007.setStyleSheet("color:rgb(255, 0, 0)") self.label_007.setText(\'第7题× \') self.label_007.setStyleSheet("color:rgb(255, 0, 0)") elif i == 7: self.lineEdit_008.setStyleSheet("color:rgb(255, 0, 0)") self.label_008.setText(\'第8题× \') self.label_008.setStyleSheet("color:rgb(255, 0, 0)") elif i == 8: self.lineEdit_009.setStyleSheet("color:rgb(255, 0, 0)") self.label_009.setText(\'第9题× \') self.label_009.setStyleSheet("color:rgb(255, 0, 0)") elif i == 9: self.lineEdit_010.setStyleSheet("color:rgb(255, 0, 0)") self.label_010.setText(\'10题× \') self.label_010.setStyleSheet("color:rgb(255, 0, 0)") elif i == 10: self.lineEdit_011.setStyleSheet("color:rgb(255, 0, 0)") self.label_011.setText(\'11题× \') self.label_011.setStyleSheet("color:rgb(255, 0, 0)") elif i == 11: self.lineEdit_012.setStyleSheet("color:rgb(255, 0, 0)") self.label_012.setText(\'12题× \') self.label_012.setStyleSheet("color:rgb(255, 0, 0)") elif i == 12: self.lineEdit_013.setStyleSheet("color:rgb(255, 0, 0)") self.label_013.setText(\'13题× \') self.label_013.setStyleSheet("color:rgb(255, 0, 0)") elif i == 13: self.lineEdit_014.setStyleSheet("color:rgb(255, 0, 0)") self.label_014.setText(\'14题× \') self.label_014.setStyleSheet("color:rgb(255, 0, 0)") elif i == 14: self.lineEdit_015.setStyleSheet("color:rgb(255, 0, 0)") self.label_015.setText(\'15题× \') self.label_015.setStyleSheet("color:rgb(255, 0, 0)") elif i == 15: self.lineEdit_016.setStyleSheet("color:rgb(255, 0, 0)") self.label_016.setText(\'16题× \') self.label_016.setStyleSheet("color:rgb(255, 0, 0)") elif i == 16: self.lineEdit_017.setStyleSheet("color:rgb(255, 0, 0)") self.label_017.setText(\'17题× \') self.label_017.setStyleSheet("color:rgb(255, 0, 0)") elif i == 17: self.lineEdit_018.setStyleSheet("color:rgb(255, 0, 0)") self.label_018.setText(\'18题× \') self.label_018.setStyleSheet("color:rgb(255, 0, 0)") elif i == 18: self.lineEdit_019.setStyleSheet("color:rgb(255, 0, 0)") self.label_019.setText(\'19题× \') self.label_019.setStyleSheet("color:rgb(255, 0, 0)") elif i == 19: self.lineEdit_020.setStyleSheet("color:rgb(255, 0, 0)") self.label_020.setText(\'20题× \') self.label_020.setStyleSheet("color:rgb(255, 0, 0)") self.lineEdit_daduitishu.setText(str(self.right)) # 显示正确错误半对的数量 self.lineEdit_banduitishu.setText(str(self.bandu)) # 显示正确错误半对的数量 self.lineEdit_dacuotishu.setText(str(self.wrong)) # 显示正确错误半对的数量
#② 把答案保存在电子表格,用Opencvyxl 库 self.chengji = [\'\'] * 24 self.chengji[0] = self.imgname #序号入列表 self.chengji[1] = self.diyigezichuan + self.diergezichuan + self.disangezichuan #姓名入列表 self.chengji[2] = self.kaohaochuan #考号入列表 self.chengji[3] = (self.right * self.meitifenshu) + (self.bandu * self.bufendefen) #成绩入列表 self.chengji[4:] = self.xuan #选项入列表 self.chengjiexcel = openpyxl.load_workbook(\'chengji.xlsx\') # 打开excel self.sh1 = self.chengjiexcel[\'chengjish\'] # 打开表单一 self.sh2 = self.chengjiexcel[\'tongjish\'] # 打开表单二 for col in range(len(self.chengji)): # 信息入电子表格 self.sh1.cell(row =self.imgname + 1 , column = col+1 ).value = self.chengji[col] self.chengjiexcel.save(\'chengji.xlsx\') #保存
#③ 把选择的正确率做成柱状图用 matplotlib 库 for zhu in range(len(self.answer)): #循环显示柱状图 if self.answer[zhu] != \'\': plt.figure(\'第\'+ str(zhu+1)+\'题\') x = [\'A\', \'B\', \'C\', \'D\'] y = [(eval(\'di\' + str(zhu+1) + \'ti\').count(\'A\')),(eval(\'di\' + str(zhu+1) + \'ti\').count(\'B\')),(eval(\'di\' + str(zhu+1) + \'ti\').count(\'C\')),(eval(\'di\' + str(zhu+1) + \'ti\').count(\'D\'))] plt.bar(x, y, label=\'第\'+str((zhu+1))+\'题选\' + self.answer[zhu], color=\'g\') plt.legend() plt.savefig(\'imgzhu\\\'+ str((zhu+1))+\'题\'+\'.jpg\') plt.show()
#④用到的库如下 # -*- coding: utf-8 -*- import sys,os if hasattr(sys, \'frozen\'): os.environ[\'PATH\'] = sys._MEIPASS + ";" + os.environ[\'PATH\'] import cv2 import numpy as np import imutils import openpyxl from itertools import chain from PyQt5 import QtWidgets from untitled import Ui_Form from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * import matplotlib.pyplot as plt from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import QApplication from imutils.perspective import four_point_transform
第八,程序打包:
安装:pip uninstall pyinstaller
打开:CMD
切换路径:自己工程的路径并输入 pyinstaller -F -w Run.py
如果出现错误:
1.在执行命令 pyinstaller -F D:\py\programe\banksystem.py打包生成.exe文件时报错:python maximum recursion depth exceeded
2.处理办法分三步走:
①.命令行输入:pyi-makespec -F D:\py\programe\清单核对\bomcheck.py,会生成一个bomcheck.spec文件
②.找到bomcheck.spec这个文件给它的第二行插入下面两行代码
import sys
sys.setrecursionlimit(50000)
③.重新编译生成命令行输入:pyinstaller -F Run.spec即可
总结:说得好像论七八糟,大神请略过,第一次发博客手生,请见谅!