예제 #1
0
def convert_to_html(xml_f):
    xpath = os.path.join('xml', xml_f)
    l = xml2list(xpath)
    list2html(l, f'{xml_f[:-4]}.png', img_d, 'html')
예제 #2
0
def run_evaluate(predict_dir, target_dir, img_dir=None, simi=False, thres=0):
    fp_list = []
    classification_p_list = []
    total_intersection = 0
    total_prediction = 0
    total_gt = 0
    for predict_f in os.listdir(predict_dir):
        predict_path = os.path.join(predict_dir, predict_f)
        target_path = os.path.join(target_dir, predict_f)
        predict_list = xml2list(predict_path)
        target_list = xml2list(target_path)
        if img_dir is not None:
            img_p = os.path.join(img_dir, predict_f[:-4] + '.png')
            img = Image.open(img_p)
            for predict in predict_list:
                p_cls, p_bb = predict
                p_bb = [x - 5 for x in p_bb]
                d = ImageDraw.Draw(img)
                d.rectangle(p_bb, outline=color_classes[p_cls])
                img.save(f'outputs/{predict_f[:-4] + ".png"}')

        list_map = match_lists(predict_list, target_list)
        tbb_map = {}
        for predict in predict_list:
            p_cls, p_bb = predict
            p_score = 0.1
            p_bb = tuple(p_bb)
            matched_target = list_map[(p_cls, p_bb, p_score)]
            if matched_target is None:
                fp_list.append((predict, 'background'))
                continue
            t, iou = matched_target
            t_cls, t_bb = t
            t_cls = ICDAR_convert[t_cls]
            if t_bb in tbb_map:
                tbb_map[t_bb].append(p_bb)
            else:
                tbb_map[t_bb] = [p_bb]
            if p_cls == t_cls:
                if iou < thres:
                    fp_list.append((predict, 'localization'))
                    continue
                fp_list.append((predict, 'correct'))
                classification_p_list.append((p_cls, t_cls))
                continue
            else:
                if iou >= thres:
                    classification_p_list.append((p_cls, t_cls))
                sim = False
                for s in similar_class_sets:
                    if p_cls in s and t_cls in s:
                        sim = True
                        break
                if sim:
                    if simi:
                        fp_list.append((predict, 'correct'))
                    else:
                        fp_list.append((predict, 'similar'))
                else:
                    fp_list.append((predict, 'other'))
        page_intersection = 0
        page_prediction = 0
        page_gt = 0
        for t_bb in tbb_map:
            for prediction in tbb_map[t_bb]:
                x_left = max(t_bb[0], prediction[0])
                y_top = max(t_bb[1], prediction[1])
                x_right = min(t_bb[2], prediction[2])
                y_bottom = min(t_bb[3], prediction[3])
                intersection_area = (x_right - x_left) * (y_bottom - y_top)
                page_intersection += intersection_area
                page_prediction += (prediction[2] - prediction[0]) * (
                    prediction[3] - prediction[1])
            page_gt += (t_bb[2] - t_bb[0]) * (t_bb[3] - t_bb[1])
        total_intersection += page_intersection
        total_prediction += page_prediction
        total_gt += page_gt

    print('Bounding box Precision')
    bb_precision = total_intersection / total_prediction
    print(bb_precision)
    print('--------')
    print('Bounding box Recall')
    bb_recall = total_intersection / total_gt
    print(bb_recall)
    print('--------')
    print('Bounding box F1')
    bb_f1 = 2 * bb_precision * bb_recall / (bb_precision + bb_recall)
    print(bb_f1)
    print('---------')

    class_counts = {}
    for p in classification_p_list:
        p_cls, t_cls = p
        if p_cls not in class_counts:
            class_counts[p_cls] = {}
        if t_cls in class_counts[p_cls]:
            class_counts[p_cls][t_cls] += 1
        else:
            class_counts[p_cls][t_cls] = 1
    class_precisions = {}
    all_tp = 0
    all_denom = 0
    for p_cls in class_counts:
        tp = 0
        fp = 0
        for t_cls in class_counts[p_cls]:
            if p_cls == t_cls:
                tp = class_counts[p_cls][t_cls]
            else:
                fp += class_counts[p_cls][t_cls]
        denom = tp + fp
        all_tp += tp
        all_denom += denom
        class_precisions[
            p_cls] = tp / denom if denom != 0 else 'No false positives or true positives found'
    print('All class precision')
    all_precision = all_tp / all_denom
    print(all_precision)
    print('-----------------')
    all_tp = 0
    all_denom = 0
    class_recalls = {}
    for p_cls in class_counts:
        tp = class_counts[p_cls][p_cls] if p_cls in class_counts[p_cls] else 0
        fn = 0
        for p2_cls in class_counts:
            if p2_cls == p_cls:
                continue
            if p_cls in class_counts[p2_cls]:
                fn += class_counts[p2_cls][p_cls]
        denom = tp + fn
        all_tp += tp
        all_denom += denom
        class_recalls[
            p_cls] = tp / denom if denom != 0 else 'No false negatives or true positives found'

    print('All class recall')
    all_recall = all_tp / all_denom
    print(all_recall)
    print('--------------')

    print('All class F1')
    all_f1 = 2 * all_precision * all_recall / (all_precision + all_recall)
    print(all_f1)
    print('--------------')

    print('Class recalls')
    print(class_recalls)
    print('------------')
    print('Class precisions')
    print(class_precisions)
    print('------------')

    class_f1 = {}
    for cl in class_recalls:
        rec = class_recalls[cl]
        prec = class_precisions[cl]
        if rec + prec == 0:
            class_f1[cl] = 0
            continue
        class_f1[cl] = 2 * rec * prec / (rec + prec)
    print('Class F1s')
    print(class_f1)
    print('-------------')

    print('Class counts')

    print(class_counts)
    df = pd.DataFrame(class_counts)
    df = df.fillna(value=0)
    df['Total'] = df.sum(axis=1)
    print(df[sorted(df.columns)])
    print('------------')

    tp_num = 0
    fp_num = 0
    current_class = None
    roc_tp = [0]
    roc_fp = [0]
    p_r_curve = []
    for p in fp_list:
        predict, category = p
        is_tp = category == 'correct'
        if is_tp:
            if current_class is None:
                current_class = True
                continue
            if not current_class:
                roc_tp.append(tp_num)
                roc_fp.append(fp_num)
            tp_num += 1
        else:
            if current_class is None:
                current_class = False
                continue
            if current_class:
                roc_tp.append(tp_num)
                roc_fp.append(fp_num)
            fp_num += 1
        precision = tp_num / (tp_num + fp_num)
        p_r_curve.append((precision, tp_num))
    roc_tp.append(tp_num)
    roc_fp.append(fp_num)
    p_r_curve = [(x, y / tp_num) for x, y in p_r_curve]
    max_ps = []
    for i in range(11):
        chk_num = i / 10
        m_p = 0
        for x, y in p_r_curve:
            if y <= chk_num:
                continue
            if x > m_p:
                m_p = x
        max_ps.append(m_p)
    mAP = sum(max_ps) / len(max_ps)

    uz = list(zip(*p_r_curve))
    make_p_r_curve(uz[0], uz[1])
    normalized_tp = [x / tp_num for x in roc_tp]
    normalized_fp = [x / fp_num for x in roc_fp]
    make_roc_chart(normalized_tp, normalized_fp)

    filtered_fp_list = [fp for fp in fp_list if fp[1] != 'correct']
    print(f'True Positives: {tp_num}')
    print(f'False Positives: {fp_num}')
    return filtered_fp_list