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))
Example #3
0
    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))