二分类精度指标计算

8位RGB图像,例(255,255,255),转二值图像(灰度图像)0和255

python 复制代码
# 8位rgb转二值图


import cv2

import glob
from tqdm import tqdm
import os


all_inputs = glob.glob(r'./output/*.png')
output_pth = r'./gray_result'

if not os.path.exists(output_pth):
    os.makedirs(output_pth)

for i in tqdm(range(len(all_inputs))):
    path = all_inputs[i]
    # 以灰度模式直接读取图像(即使原图是彩色,也会被转成单通道)
    gray_img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

    full_filename = os.path.basename(path)
    outpth = os.path.join(output_pth, full_filename)

    # 保存灰度图像
    cv2.imwrite(outpth, gray_img)

    # 查看形状
    # print(gray_img.shape)  # (height, width)

精度指标计算方式一

python 复制代码
# 变化检测数据精度计算

import numpy as np
import glob
from PIL import Image
from sklearn.metrics import confusion_matrix,cohen_kappa_score
from sklearn.metrics import f1_score
from tqdm import tqdm

def mean_iou(input, target, classes = 2):
    """  compute the value of mean iou
    :param input:  2d array, int, prediction
    :param target: 2d array, int, ground truth
    :param classes: int, the number of class
    :return:
        miou: float, the value of miou
    """
    miou = 0
    for i in range(classes):
        intersection = np.logical_and(target == i, input == i)
        # print(intersection.any())
        union = np.logical_or(target == i, input == i)
        print(union)
        temp = np.sum(intersection) / np.sum(union)
        miou += temp
    return miou/classes

def compute_f1(prediction, target):
    """
    :param prediction: 2d array, int,
            estimated targets as returned by a classifier
    :param target: 2d array, int,
            ground truth
    :return:
        f1: float
    """
    prediction.tolist(), target.tolist()
    img, target = np.array(prediction).flatten(), np.array(target).flatten()
    f1 = f1_score(y_true=target, y_pred=img, average='micro')
    return f1


def compute_kappa(prediction, target):
    """
    :param prediction: 2d array, int,
            estimated targets as returned by a classifier
    :param target: 2d array, int,
            ground truth
    :return:
        kappa: float
    """
    prediction.tolist(), target.tolist()
    img, target = np.array(prediction).flatten(), np.array(target).flatten()
    kappa = cohen_kappa_score(target, img)
    return kappa

def calculateTP(GT, PRE, size):
    TP = 0
    for y in range(0, size):
        for x in range(0, size):
            if GT[y, x].any() == 255 and PRE[y, x].any() == 255:
                TP += 1
            else:
                continue
    return TP

def calculateTN(GT, PRE, size):
    TN = 0
    for y in range(0,size):
        for x in range(0,size):
            if GT[y,x].any() == 0 and PRE[y,x].any() == 0:
                TN += 1
            else:
                continue
    return TN

def calculateFP(GT, PRE, size):
    FP = 0
    for y in range(0,size):
        for x in range(0,size):
            if GT[y,x].any() == 0 and PRE[y,x].any() == 255:
                FP+=1
            else:
                continue
    return FP

def calculateFN(GT,PRE, size):
    FN = 0
    for y in range(0,size):
        for x in range(0,size):
            if GT[y,x].any() == 255 and PRE[y,x].any() == 0:
                FN += 1
            else:
                continue
    return FN

# 标签
all_targets = glob.glob(r'S2looking/标签label/*.png')

# 输入文件
all_inputs = glob.glob(r'/Eval_CD/output/*.png')   # 读取所有图像文件

# 文件大小
img_size = 1024

sum_mean_IoU = 0
sum_F1 = 0
sum_kappa = 0
TP_sum = 0
TN_sum = 0
FP_sum = 0
FN_sum = 0

for i in tqdm(range(len(all_inputs))):
    target = all_targets[i]
    input = all_inputs[i]
    # print(target)
    target = Image.open(target)
    #target = target.convert('L')
    target = np.array(target)  # 将pillow对象转换为np数据
    input = Image.open(input)
    input= np.array(input)

    TP = calculateTP(target, input, img_size)
    TN = calculateTN(target, input, img_size)
    FP = calculateFP(target, input, img_size)
    FN = calculateFN(target, input, img_size)
    TP_sum += TP
    TN_sum += TN
    FP_sum += FP
    FN_sum += FN


presion = TP_sum / (TP_sum + FP_sum)
recall1 = TP_sum / (TP_sum + FN_sum)
#recall2 = TN_sum / (TP_sum + FN_sum)
Accuracy = (TP_sum + TN_sum) / (TP_sum + TN_sum + FP_sum + FN_sum)
F1 = (2 * recall1 * presion) / (recall1 + presion)
# 预测结果前景iou
IOU1 = TP_sum / (TP_sum + FP_sum + FN_sum)
# 预测结果背景iou
IOU2 = TN_sum / (TN_sum + FP_sum + FN_sum)
# MIoU = (IoU正例p + IoU反例n) / 2 = [ TP / (TP + FP + FN) + TN / (TN + FN + FP) ] / 2
IOU = (IOU1 + IOU2) / 2

print("presion: ", presion)
print("recall: ", recall1)
print("Accuracy: ", Accuracy)
print("F1: ", F1)
print("mIou: ", IOU)

精度指标计算方式二

python 复制代码
import os
import cv2
import numpy as np
from tqdm import tqdm


def read_binary_image(img_path):
    """
    读取二值PNG图片,预处理为0/1矩阵
    规则:背景=0,变化区域=255 → 统一转为 0(背景)/1(变化)
    """
    # 读取为灰度图(自动兼容彩色图)
    img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
    if img is None:
        raise FileNotFoundError(f"无法读取图片: {img_path}")

    # 二值化:大于0的像素设为1(兼容非标准255的二值图)
    binary_img = np.where(img > 0, 1, 0).astype(np.uint8)
    return binary_img


def calculate_confusion_matrix(label, pred):
    """
    计算二分类混淆矩阵(变化检测:1=变化,0=背景)
    返回: TP, FP, FN, TN
    """
    # 确保标签和预测尺寸一致
    if label.shape != pred.shape:
        raise ValueError(f"尺寸不匹配: 标签{label.shape}, 预测{pred.shape}")

    # 计算混淆矩阵
    TP = np.sum((label == 1) & (pred == 1))  # 真正例:真实变化,预测变化
    FP = np.sum((label == 0) & (pred == 1))  # 假正例:真实背景,预测变化
    FN = np.sum((label == 1) & (pred == 0))  # 假反例:真实变化,预测背景
    TN = np.sum((label == 0) & (pred == 0))  # 真反例:真实背景,预测背景

    return TP, FP, FN, TN


def compute_metrics(TP, FP, FN, TN):
    """
    根据混淆矩阵计算评估指标
    """
    # 查准率 (Precision)
    precision = TP / (TP + FP) if (TP + FP) != 0 else 0.0
    # 查全率 (Recall)
    recall = TP / (TP + FN) if (TP + FN) != 0 else 0.0
    # F1分数
    f1 = 2 * precision * recall / (precision + recall) if (precision + recall) != 0 else 0.0
    # IoU (变化类) + mIoU (二分类平均IoU)
    iou_change = TP / (TP + FP + FN) if (TP + FP + FN) != 0 else 0.0
    iou_bg = TN / (TN + FN + FP) if (TN + FN + FP) != 0 else 0.0
    miou = (iou_change + iou_bg) / 2  # 平均交并比

    return precision, recall, f1, miou, iou_change


def evaluate_change_detection(label_dir, pred_dir):
    """
    主评估函数:批量读取文件夹,计算全局精度指标
    """
    # 获取所有标签文件名
    img_names = [f for f in os.listdir(label_dir) if f.endswith(('.png', '.PNG'))]
    if len(img_names) == 0:
        raise ValueError("标签文件夹中未找到PNG图片!")

    # 初始化全局混淆矩阵
    total_TP = 0
    total_FP = 0
    total_FN = 0
    total_TN = 0

    print(f"开始评估,共检测到 {len(img_names)} 张图片...")
    # 遍历所有图片
    for img_name in tqdm(img_names):
        label_path = os.path.join(label_dir, img_name)
        pred_path = os.path.join(pred_dir, img_name)

        # 跳过预测文件缺失的情况
        if not os.path.exists(pred_path):
            print(f"警告:预测文件不存在,跳过 → {img_name}")
            continue

        try:
            # 读取并预处理二值图
            label = read_binary_image(label_path)
            pred = read_binary_image(pred_path)

            # 计算单张图片混淆矩阵
            TP, FP, FN, TN = calculate_confusion_matrix(label, pred)

            # 累加到全局统计
            total_TP += TP
            total_FP += FP
            total_FN += FN
            total_TN += TN

        except Exception as e:
            print(f"处理图片 {img_name} 失败: {str(e)}")
            continue

    # 计算最终全局指标
    precision, recall, f1, miou, iou_change = compute_metrics(total_TP, total_FP, total_FN, total_TN)

    # 打印结果
    print("\n" + "=" * 50)
    print("变化检测二值图评估结果(全局指标)")
    print("=" * 50)
    print(f"查准率 (Precision): {precision:.4f}")
    print(f"查全率 (Recall)   : {recall:.4f}")
    print(f"F1 分数           : {f1:.4f}")
    print(f"mIoU              : {miou:.4f}")
    print(f"变化类 IoU        : {iou_change:.4f}")
    print(f"总像素 TP: {total_TP}, FP: {total_FP}, FN: {total_FN}")
    print("=" * 50)

    return precision, recall, f1, miou


# ------------------- 【用户配置】修改这里的路径 -------------------
if __name__ == "__main__":
    # 标签文件夹路径(真实变化检测二值图)
    LABEL_DIR = r"./gray_label"
    # 预测结果文件夹路径(模型输出的变化检测二值图)
    PRED_DIR = r"./gray_result"

    # 开始评估
    evaluate_change_detection(LABEL_DIR, PRED_DIR)
相关推荐
啊哈哈哈哈哈啊哈哈2 小时前
答题卡检测
人工智能·opencv·计算机视觉
火山引擎开发者社区2 小时前
火山方舟 Coding Plan 服务变更公告
人工智能
强风7942 小时前
OpenCV的创建与配置
人工智能·opencv·计算机视觉
qq_452396232 小时前
【Python × AI】Prompt Engineering 深度工程化:打造大模型的“确定性”控制链路
人工智能·python·ai·prompt
nap-joker2 小时前
【表格+图像融合+多模态分类标签不一致问题】TNF:多模态医学数据分类的三分支神经融合
人工智能·分类·数据挖掘·多模态融合·图像+表格模态融合·三分支神经网络
是Dream呀2 小时前
ABFPN:一种面向小目标检测的多尺度特征融合网络
人工智能·目标检测·目标跟踪
weixin_452953322 小时前
openclaw新手部署详细教程——适用于ubuntu22.04
linux·人工智能·ubuntu
火山引擎开发者社区2 小时前
扣子×飞书深度打通!自带浏览器的 OpenClaw,一键领养!
人工智能