汽车零件分类报警系统(4) 接上文一、摄像头1的OCR识别执行函数对摄像头1的当前帧进行OCR识别过滤有效结果后存入list_zong1每3次调用后触发w2set1处理结果。execute_after_n_calls(3, w2set1) def _performOCR1(self): result ocr2.ocr(self.frame1, clsFalse) if result and not None in result: try: for i in result[0]: # print(i) mianji are(i) # print(yi,i,mianji) ma process_string(i[1][0]) # if i[1][1] 0.92 and ma and 80i[0][0][0]550 and mianji1000: if i[1][1] 0.92 and ma and 320 i[0][0][0] 1060 and mianji 1000: self.list_zong1.extend(ma) # print(i[1][0], are(i)) # print(******************) except: pass使用ocr2是北汽不需要角度调整速度比较快。确保识别结果不为none遍历识别到的每个文字块。调用了计算识别框面积的函数和使用正则表达式合格编码的函数。这里result的结构其实就是paddleOCR的返回格式列表的元素也是一个列表分别是文字块的四个点坐标列表和识别出的文字置信度列表大致如下result[0] [ [ # 第一个文字块 [[左上角坐标], [右上角坐标], [右下角坐标], [左下角坐标]], # 位置信息 [识别出的文字, 置信度] # 文字和置信度 ], [ # 第二个文字块... ] ]if多条件过滤同时满足i[1][1]也就是置信度大于0.92ma提取到有效编码i[0][0][0]也就是识别框x坐标在固定区域内mianji识别框面积大于1000。最后存入结果列表二、摄像头2的识别结果处理与报警逻辑def w2set2(self): if self.list_zong2: try: for i in self.list_zong2: if self.list_zong2.count(i) 1: self.set_zong2.add(i) set_len2 set_bing(self.set_zong2) self.list2.extend(list(set_len2)) self.daan2 most_common_element(self.list2) if self.frame_counter % 25 0: # 约每 10 秒刷新一下 self.list2.clear() text2 ,.join(set_len2) self.lineEdit_2.setText(text2) if (not self.daan2) or (not set_len2): pass elif len(set_len2)1 and (list(set_len2)[0] self.daan2): pass else: print(二) print(set_len2, self.daan2) tu2 cv2.putText(self.frame2.copy(), text2, (100, 200), cv2.FONT_HERSHEY_SIMPLEX, 3, (0, 0, 255), 6, cv2.LINE_AA) nam2 time.strftime(%Y_%m_%d_%H_%M, time.localtime()) path os.path.join(rD:\MVS\MVS\Development\Samples\Python\shiyan\baojing\镜头二, f{nam2}-{self.daan2}.jpg) cv2.imencode(.jpg, tu2)[1].tofile(path) self.label_5.setVisible(True) sendCmdToDevice(LIGHT, self.ser2) QtCore.QTimer.singleShot(5000, lambda: hide_label_and_send_cmd(self.label_5, self.ser2)) self.frame_counter 0 except Exception as e: print(e) self.list_zong2.clear() self.set_zong2.clear() self.set_12hunset([self.daan1,self.daan2]) print(1:, self.daan1) print(2:, self.daan2) print(合:, self.set_12hun)这个函数和之前的w2set结构基本上是相同的但也有差异1.历史清空周期不同# w2set1 if self.frame_counter % 16 0: # 约每1秒清空15fps self.list1.clear() # w2set2 if self.frame_counter % 25 0: # 约每1.67秒清空 self.list2.clear()摄像头2的历史记录保留时间更长。2.报警截图保存路径不同这里自然是要保存到镜头2中3.图像标注参数不同镜头2字体更大4.报警器不同不同串口控制不同报警器硬件5.新增功能双摄像头联动判断# 合并两个摄像头的识别结果 self.set_12hun set([self.daan1, self.daan2]) print(1:, self.daan1) print(2:, self.daan2) print(合:, self.set_12hun)将摄像头1和摄像头2的最终结果合并到一个集合中用于判断两个摄像头识别的是否是同一个零件这是典型的工业多工位协同检测系统确保零件在所有工位都符合要求三、摄像头2的OCR识别执行函数execute_after_n_calls(3, w2set2) def _performOCR2(self): # 执行OCR操作 result2 ocr2.ocr(self.frame2, clsFalse) if result2 and not None in result2: try: for i in result2[0]: mianjiare(i) # print(er,mianji,i) maprocess_string(i[1][0]) if i[1][1] 0.84 and ma and mianji1600 and (350i[0][0][0]1060): #25000 self.list_zong2.extend(ma) except: pass elif None in result2: self.daan2 self.set_12hun set([self.daan1, self.daan2]) print(1:, self.daan1) print(2:, self.daan2) print(合:, self.set_12hun)当摄像头2识别失败时清空daan2重新合并两个摄像头的识别结果其他和摄像头1是一样的四、摄像头3的识别结果处理与报警逻辑def w2set3(self): maxx 0 if self.list_zong3: try: for i in self.list_zong3: self.guo.append(i[1][0]) for ii in self.guo: if self.guo.count(ii) 1: self.set_zong3.add(ii) # print(YYYY,self.set_zong3) for j in self.list_zong3: if (j[1][0] in self.set_zong3) and (are(j) maxx): aa j maxx are(j) text3 aa[1][0].replace(0, O).replace(o, O).replace(S, 5).replace(I, 1).replace(L,1).replace(v,V).replace(B,8).replace(p,P) self.lineEdit_3.setText(text3) if (not text3) or self.set_12hunset() or self.set_12hun{}: pass elif self.set_12hun and In_which(text3,self.set_12hun): pass else: print(三) print(text3) print(self.set_12hun) tu3 cv2.putText(self.frame3.copy(), text3, (100, 200), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 5, cv2.LINE_AA) nam3 time.strftime(%Y_%m_%d_%H_%M, time.localtime()) path os.path.join(rD:\MVS\MVS\Development\Samples\Python\shiyan\baojing\镜头三, f{nam3}-{self.set_12hun}.jpg) cv2.imencode(.jpg, tu3)[1].tofile(path) self.set_12hun.clear() self.label_6.setVisible(True) sendCmdToDevice(LIGHT, self.ser2) QtCore.QTimer.singleShot(5000, lambda: hide_label_and_send_cmd(self.label_6, self.ser2)) except: pass self.guo.clear() self.list_zong3.clear() self.set_zong3.clear()这也没啥要说了主要差异1.数据处理方式不同摄像头1、2先统计出现1次的编码 → 标准化 → 取众数摄像头3保留完整的识别信息包含坐标、面积然后选择面积最大的那个识别框作为最终结果2.判断逻辑不同# 摄像头1、2判断识别结果是否一致 if (not self.daan1) or (not set_len1): pass elif len(set_len1)1 and (list(set_len1)[0] self.daan1): pass # 摄像头3判断识别结果是否在合并集合中 if (not text3) or self.set_12hunset() or self.set_12hun{}: pass elif self.set_12hun and In_which(text3, self.set_12hun): pass摄像头3不自己判断是否违规而是看识别结果是否在set_12hun摄像头12的合并结果中这是一个联动判断摄像头3作为验证或补充3.报警控制不同和摄像头2共用一个4.截图保存路径5.清空合并集合五、摄像头3的OCR识别执行函数execute_after_n_calls(3, w2set3) def _performOCR3(self): global text3 # result2 ocr2.ocr(self.frame3, clsFalse) try: # 将图像从BGR转换为HSV颜色空间 hsv_image cv2.cvtColor(self.frame3, cv2.COLOR_BGR2HSV) # 定义牛皮纸颜色的范围 lower_brown np.array([10, 30, 30]) # 最小颜色值 upper_brown np.array([30, 255, 255]) # 最大颜色值 # 使用颜色范围进行颜色检测 mask cv2.inRange(hsv_image, lower_brown, upper_brown) # 计算掩码中白色像素检测到的颜色的数量 white_pixels np.sum(mask 255) # 计算图像的总像素数 total_pixels mask.shape[0] * mask.shape[1] # 计算特定颜色的占比 color_percentage (white_pixels / total_pixels) * 100 if color_percentage 20: # 20 # resul [] result2 ocr2.ocr(self.frame3, clsFalse) if result2 and not None in result2: for j in result2[0]: # print(san,j,are(j)) if j[1][1] 0.93 and process_string(j[1][0]): self.list_zong3.append(j) else: text3 except: text3 和前面两个有本质差异他增加另一个颜色检测预处理。摄像头3可能检测的是放在牛皮纸包装上的零件编码或者零件本身是牛皮纸颜色只有当画面中有足够面积的牛皮纸时才说明有零件到位避免在空工位或无零件时进行无意义的OCR识别。六、主函数if __name__ __main__: app QtWidgets.QApplication(sys.argv) window PyQtMainEntry() window.show() sys.exit(app.exec_())if __name__ __main__确保只有直接运行此脚本时才执行被导入时不执行QApplicationQt应用程序对象管理GUI事件循环PyQtMainEntry()实例化你的主窗口类包含所有摄像头、报警器、识别逻辑window.show()显示主界面app.exec_()启动事件循环等待用户交互sys.exit()程序退出时返回状态码给操作系统