def steel_char_detect(path_1, path_2, path_3, path_4): Log_oper = Log("Log_ASC") Log_oper.add_log("Normal>>开始载入跟踪模型") try: steel_model = YOLO() except Exception as err: Log_oper.add_log("Error>>执行中出现错误{},程序自动重启".format(err)) os.system('taskkill /IM ArNTSteelDefectsClassifier64.exe /F') Log_oper.add_log("Normal>>完成载入跟踪模型成功") Log_oper.add_log("Normal>>开始载入识别模型") try: phi = 2 weighted_bifpn = True model_path = 'char_model/char_model.h5' image_sizes = (512, 640, 768, 896, 1024, 1280, 1408) image_size = image_sizes[phi] classes = { value['id']: value['name'] for value in json.load(open('char_model/char_class.json', 'r')).values() } num_classes = len(classes) score_threshold = 0.25 colors = [ np.random.randint(0, 256, 3).tolist() for _ in range(num_classes) ] _, char_model = efficientdet(phi=phi, weighted_bifpn=weighted_bifpn, num_classes=num_classes, score_threshold=score_threshold) char_model.load_weights(model_path, by_name=True) char_model_param = { 'image_size': image_size, 'classes': classes, 'score_threshold': score_threshold, 'colors': colors } except Exception as err: Log_oper.add_log("Error>>执行中出现错误{},程序自动重启".format(err)) os.system('taskkill /IM ArNTSteelDefectsClassifier64.exe /F') Log_oper.add_log("Normal>>完成载入识别模型成功") Log_oper.add_log("Normal>>开始创建二级连接") try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('191.168.162.192', 12001)) send_heartbeat = threading.Thread(target=thread_send_heartbeat, args=( s, Log_oper, )) send_heartbeat.start() recv_info = threading.Thread(target=thread_recv_info, args=( s, Log_oper, )) recv_info.start() except Exception as err: Log_oper.add_log("Error>>执行中出现错误{},程序自动重启".format(err)) os.system('taskkill /IM ArNTSteelDefectsClassifier64.exe /F') Log_oper.add_log("Normal>>完成成功连接到二级") last_steel_no = "00000000000000" judge_num = 0 counter = 0 cache_num = 0 cache_char = [] path_camera = path_1["path_camera"] path_steel = path_1["path_steel"] path_char = path_1["path_char"] path_char_l2 = path_1["path_char_l2"] while True: img_path_list = [] Log_oper.add_log("Normal>>获得文件夹图像路径列表") for root, dirs, files in os.walk(path_camera): time.sleep(1) img_path_list = [] #确定是否钢板已走完 if len(files) > 0: judge_num = 0 else: judge_num = judge_num + 1 for file in files: if os.path.splitext(file)[1] == '.jpg': src_img_path = os.path.join(path_camera, file) img_path_list.append(src_img_path) Log_oper.add_log("Normal>>开始处理{}的图像".format(src_img_path)) start = time.time() try: src_image_Image = Image.open(src_img_path) src_image_Opencv = np.asarray(src_image_Image) src_image_width, src_image_height = src_image_Image.size[ 0], src_image_Image.size[1] except: Log_oper.add_log("Error>>文件打开错误,直接跳过") time.sleep(1) continue else: try: r_image, result = steel_model.detect_image( src_image_Image) is_save = False for n in range(0, len(result)): (top, left, bottom, right) = result[n]['box'] to_top = top - 0 to_bottom = src_image_height - bottom roi_w = right - left to_left = left - 0 to_right = src_image_width - right if roi_w > src_image_width * 0.2 and to_left > src_image_width * 0.15 and to_right > src_image_width * 0.15 and to_top >= 0 and to_bottom >= 0 and result[ n]['class'] != 'tchar': #存在字符则进行存储 datetime = time.strftime("%Y%m%d") save_src_path = ((path_steel + "\%s") % datetime) if not os.path.exists(save_src_path): os.mkdir(save_src_path) save_src_img_path = os.path.join( save_src_path, file) cv2.imwrite(save_src_img_path, src_image_Opencv) Log_oper.add_log("Normal>>图像上存在字符,图像保存") #判断字符是否为倒置 judge_char_inv = False #if bottom<src_image_height/2: # judge_char_inv=True if result[n]['class'] == 'unchar': judge_char_inv = True if judge_char_inv is True: src_image_Opencv = rotate_bound( src_image_Opencv, 180) top, bottom = src_image_height - bottom, src_image_height - top left, right = src_image_width - right, src_image_width - left Log_oper.add_log( "Normal>>检测到字符为倒置状态,进行翻转") #拓展图像 left = max(0, left - 0) right = min(src_image_width, right + 0) roi_w = right - left top_s, bottom_s = top, bottom for i in range(0, src_image_height): top = max(0, top - 1) bottom = min(src_image_height, bottom + 1) roi_h = bottom - top if roi_h >= roi_w or roi_h >= src_image_height: break top_offset = abs(top_s - top) bottom_offset = abs(bottom_s - bottom) char_roi = src_image_Opencv[ int(top):int(bottom), int(left):int(right)] Log_oper.add_log("Normal>>成功获得字符ROI") src_char_roi = char_roi.copy() char_roi = char_roi[:, :, ::-1] char_roi_h, char_roi_w = char_roi.shape[:2] char_roi_norm, scale = preprocess_image( char_roi, image_size=image_size) boxes, scores, labels = char_model.predict_on_batch( [ np.expand_dims(char_roi_norm, axis=0) ]) boxes, scores, labels = np.squeeze( boxes), np.squeeze(scores), np.squeeze( labels) boxes = postprocess_boxes( boxes=boxes, scale=scale, height=char_roi_h, width=char_roi_w) indices = np.where( scores[:] > score_threshold)[0] boxes = boxes[indices] labels = labels[indices] scores = scores[indices] res_nms = nms(boxes, scores, 0.1) boxes = boxes[res_nms] labels = labels[res_nms] scores = scores[res_nms] draw_boxes(src_char_roi, boxes, scores, labels, colors, classes) #整理字符 steel_no, steel_no_score, steel_type, steel_size = get_steel_info( boxes, scores, labels, classes) steel_no = steel_no.replace("B", "8") steel_no = steel_no.replace("D", "0") steel_no = steel_no.replace("I", "1") steel_no = steel_no.replace("O", "0") steel_no = steel_no.replace("S", "5") exist_char = True if len(steel_no) != 14: Log_oper.add_log( "Warning>>当前识别钢板号{}不符合规则,放弃发送({})". format(steel_no, file)) exist_char = False if False == steel_no.isdigit(): Log_oper.add_log( "Warning>>当前识别钢板号{}未全部由数字组成,放弃发送({})" .format(steel_no, file)) exist_char = False if exist_char is True: cache_char.append([ steel_no, steel_no_score, steel_type, steel_size, src_char_roi, char_roi, top_offset, bottom_offset, file ]) #缓存字符统一处理 cache_num = cache_num + 1 if len(cache_char) <= 0: continue if len(result) > 0 and cache_num < 10: continue cache_char.sort(key=itemgetter(1), reverse=True) steel_no, steel_no_score, steel_type, steel_size, src_char_roi, char_roi, top_offset, bottom_offset, file = cache_char[ 0] cache_num = 0 cache_char = [] if last_steel_no == steel_no: Log_oper.add_log( "Normal>>当前识别钢板号{}已发送过,无需再次发送({})".format( steel_no, file)) continue last_steel_no = steel_no #保存带标签的图片到本地 char_roi_h, char_roi_w = char_roi.shape[:2] src_char_roi_cut = src_char_roi[ max(int(0 + top_offset) - 10, 0):min( int(char_roi_h - bottom_offset) + 50, char_roi_h), :] save_char_img_path = os.path.join(path_char, file) cv2.imwrite(save_char_img_path, src_char_roi_cut) Log_oper.add_log("Normal>>成功保存字符识别效果图") #保存字符图片到二级发送文件夹 #char_roi_cut=char_roi[int(0+top_offset):int(char_roi_h-bottom_offset),:] char_roi_cut_resize = cv2.resize( char_roi, (char_roi.shape[1], int(char_roi.shape[1] * 0.75))) datetime = time.strftime("%Y%m%d") path_char_l2_curr = ((path_char_l2 + "\%s") % datetime) if not os.path.exists(path_char_l2_curr): os.mkdir(path_char_l2_curr) save_l2_char_img_path = os.path.join( path_char_l2_curr, file) cv2.imwrite(save_l2_char_img_path, char_roi_cut_resize) Log_oper.add_log("Normal>>成功保存字符到二级文件夹") #保存样本 save_sample_path = r"D:\ArNTCameraImage\Camera_No1\CameraImg_src" save_sample_path_curr = ( (save_sample_path + "\%s") % datetime) if not os.path.exists(save_sample_path_curr): os.mkdir(save_sample_path_curr) save_sample_path_curr_img = os.path.join( save_sample_path_curr, file) cv2.imwrite(save_sample_path_curr_img, src_image_Opencv) #发送到L2 counter = counter + 1 if counter > 30000: counter = 1 send_to_l2(s, Log_oper, steel_no, steel_type, steel_size, os.path.join(datetime, file), counter) Log_oper.add_log("Normal>>识别字符发送到二级") except Exception as err: Log_oper.add_log("Error>>执行中出现错误{}".format(err)) time.sleep(1) continue else: pass Log_oper.add_log("Normal>>完成处理{}的图像,共用时{}秒".format( src_img_path, time.time() - start)) #钢板走完直接发送字符,不受缓冲数量限制 if judge_num > 5: if len(cache_char) > 0: try: Log_oper.add_log("Normal>>钢板已走完,图像数量未达到缓存数量,直接进行判断") cache_char.sort(key=itemgetter(1), reverse=True) steel_no, steel_no_score, steel_type, steel_size, src_char_roi, char_roi, top_offset, bottom_offset, file = cache_char[ 0] cache_num = 0 cache_char = [] if last_steel_no == steel_no: Log_oper.add_log( "Normal>>当前识别钢板号{}已发送过,无需再次发送({})".format( steel_no, file)) continue last_steel_no = steel_no #保存带标签的图片到本地 char_roi_h, char_roi_w = char_roi.shape[:2] src_char_roi_cut = src_char_roi[ max(int(0 + top_offset) - 10, 0):min( int(char_roi_h - bottom_offset) + 50, char_roi_h), :] save_char_img_path = os.path.join(path_char, file) cv2.imwrite(save_char_img_path, src_char_roi_cut) Log_oper.add_log("Normal>>成功保存字符识别效果图") #保存字符图片到二级发送文件夹 #char_roi_cut=char_roi[int(0+top_offset):int(char_roi_h-bottom_offset),:] char_roi_cut_resize = cv2.resize( char_roi, (char_roi.shape[1], int(char_roi.shape[1] * 0.75))) datetime = time.strftime("%Y%m%d") path_char_l2_curr = ((path_char_l2 + "\%s") % datetime) if not os.path.exists(path_char_l2_curr): os.mkdir(path_char_l2_curr) save_l2_char_img_path = os.path.join( path_char_l2_curr, file) cv2.imwrite(save_l2_char_img_path, char_roi_cut_resize) Log_oper.add_log("Normal>>成功保存字符到二级文件夹") #发送到L2 counter = counter + 1 if counter > 30000: counter = 1 send_to_l2(s, Log_oper, steel_no, steel_type, steel_size, os.path.join(datetime, file), counter) Log_oper.add_log("Normal>>识别字符发送到二级") except Exception as err: Log_oper.add_log("Error>>执行中出现错误{}".format(err)) time.sleep(1) continue else: pass delete_file(Log_oper, img_path_list) steel_model.close_session()
def detect_char_mini(self, img, img_name, top_offset, bottom_offset): try: self.log_oper.add_log("Normal>>开始进行单行字符识别") image_size = self.char_model_param_mini['image_size'] score_threshold = self.char_model_param_mini['score_threshold'] classes = self.char_model_param_mini['classes'] colors = self.char_model_param_mini['colors'] src_img = img.copy() res_img = img.copy() img = img[:, :, ::-1] img_h, img_w = img.shape[:2] img_norm, scale = preprocess_image(img, image_size=image_size) boxes, scores, labels = self.char_model_mini.predict_on_batch( [np.expand_dims(img_norm, axis=0)]) boxes, scores, labels = np.squeeze(boxes), np.squeeze( scores), np.squeeze(labels) boxes = postprocess_boxes(boxes=boxes, scale=scale, height=img_h, width=img_w) indices = np.where(scores[:] > score_threshold)[0] boxes = boxes[indices] labels = labels[indices] scores = scores[indices] res_nms = nms(boxes, scores, 0.1) boxes = boxes[res_nms] labels = labels[res_nms] scores = scores[res_nms] draw_boxes(src_img, boxes, scores, labels, colors, classes) #整理字符 steel_no, steel_no_score, steel_no_boxes = get_steel_info_mini( boxes, scores, labels, classes) #cv2.imshow("ss",src_img) #cv2.waitKey() #input(steel_no) steel_no = steel_no.replace("B", "8") steel_no = steel_no.replace("D", "0") steel_no = steel_no.replace("I", "1") steel_no = steel_no.replace("O", "0") steel_no = steel_no.replace("S", "5") exist_char = True if len(steel_no) != 14: self.log_oper.add_log( "Warning>>当前识别钢板号{}不符合规则,放弃发送({})".format( steel_no, img_name)) exist_char = False if False == steel_no.isdigit(): self.log_oper.add_log( "Warning>>当前识别钢板号{}未全部由数字组成,放弃发送({})".format( steel_no, img_name)) exist_char = False if exist_char is True: #进行钢板号二次分类 char_w, char_h = 0, 0 char_x_min, char_x_max = 99999, 0 char_y_min, char_y_max = 99999, 0 img_mini_list = [] for i in range(0, len(steel_no_boxes)): box = steel_no_boxes[i] xmin, ymin, xmax, ymax = box char_w = char_w + (xmax - xmin) char_h = char_h + (ymax - ymin) if xmin < char_x_min: char_x_min = xmin if ymin < char_y_min: char_y_min = ymin if xmax > char_x_max: char_x_max = xmax if ymax > char_y_max: char_y_max = ymax img_mini = img[int(ymin):int(ymax), int(xmin):int(xmax)] img_mini_list.append(img_mini) img_arr = self.classifier.get_norm_img(img_mini_list) class_score, conf_score = self.classifier.predict_img_arr( img_arr) steel_no_ref = '' for c in class_score: steel_no_ref = steel_no_ref + str(c) ## if steel_no != steel_no_ref: ## self.log_oper.add_log("Warning>>识别不一样,原识别号:{},验证识别号:{}".format(steel_no,steel_no_ref)) ## else: ## self.log_oper.add_log("Normal>>识别相同") #发送二级的图上写字符 if len(steel_no_boxes) > 0: char_w = char_w / len(steel_no_boxes) char_h = char_h / len(steel_no_boxes) cv2.rectangle(res_img, (max(0, int(char_x_min - char_w * 0.2)), max(0, int(char_y_min - char_h * 2))), (min(img_w, int(char_x_max + char_w * 0.2)), min(img_h, int(char_y_max - char_h * 2))), (0, 255, 255), 3) #2 for i in range(0, len(steel_no_boxes)): box = steel_no_boxes[i] xmin, ymin, xmax, ymax = box cv2.putText(res_img, str(list(steel_no)[i]), (int(xmin), int(max(0, char_y_min - char_h))), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) # self.cache_char.append([ steel_no, steel_no_score, "", "", src_img, res_img, top_offset, bottom_offset, img_name ]) self.log_oper.add_log("Normal>>完成单行字符{}的识别,识别板号为:{}".format( img_name, steel_no)) except Exception as err: self.log_oper.add_log("Error>>单行识别字符过程中出现错误,错误代码为{}".format(err))
def detect_char_mini(self, img, img_name, top_offset, bottom_offset): try: self.log_oper.add_log("Normal>>开始进行单行字符识别") image_size = self.char_model_param_mini['image_size'] score_threshold = self.char_model_param_mini['score_threshold'] classes = self.char_model_param_mini['classes'] colors = self.char_model_param_mini['colors'] src_img = img.copy() img = img[:, :, ::-1] img_h, img_w = img.shape[:2] img_norm, scale = preprocess_image(img, image_size=image_size) boxes, scores, labels = self.char_model_mini.predict_on_batch( [np.expand_dims(img_norm, axis=0)]) boxes, scores, labels = np.squeeze(boxes), np.squeeze( scores), np.squeeze(labels) boxes = postprocess_boxes(boxes=boxes, scale=scale, height=img_h, width=img_w) indices = np.where(scores[:] > score_threshold)[0] boxes = boxes[indices] labels = labels[indices] scores = scores[indices] res_nms = nms(boxes, scores, 0.1) boxes = boxes[res_nms] labels = labels[res_nms] scores = scores[res_nms] draw_boxes(src_img, boxes, scores, labels, colors, classes) #整理字符 steel_no, steel_no_score = get_steel_info_mini( boxes, scores, labels, classes) #cv2.imshow("ss",src_img) #cv2.waitKey() #input(steel_no) steel_no = steel_no.replace("B", "8") steel_no = steel_no.replace("D", "0") steel_no = steel_no.replace("I", "1") steel_no = steel_no.replace("O", "0") steel_no = steel_no.replace("S", "5") exist_char = True if len(steel_no) != 14: self.log_oper.add_log( "Warning>>当前识别钢板号{}不符合规则,放弃发送({})".format( steel_no, img_name)) exist_char = False if False == steel_no.isdigit(): self.log_oper.add_log( "Warning>>当前识别钢板号{}未全部由数字组成,放弃发送({})".format( steel_no, img_name)) exist_char = False if exist_char is True: self.cache_char.append([ steel_no, steel_no_score, "", "", src_img, img, top_offset, bottom_offset, img_name ]) self.log_oper.add_log("Normal>>完成单行字符{}的识别,识别板号为:{}".format( img_name, steel_no)) except Exception as err: self.log_oper.add_log("Error>>单行识别字符过程中出现错误,错误代码为{}".format(err))