Python+Opencv实现摄像头答题卡识别

时间:2024-02-17 08:21:22

前言:大家好,我是一名高中物理教师,比较喜欢学习编程,由于平时批改作业比较忙,所以突然冒出个想法,做个摄像头答题卡识别就会减轻我平时批改作业的很多负担,特别是选择题,重复性的劳动,意义不大,如果用机器代替工作那该多好呀,网上一搜,有很多教程,但是都不太满意,所以我趁着躲避新冠在家隔离的这段时间,边学边做,终于做成了,还没开学,等开学了就去试试,通过博客园,把我的心得分享给大家!

首先,我学习了三本书,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即可

总结:说得好像论七八糟,大神请略过,第一次发博客手生,请见谅!