[PaddleSeg 源码阅读] PaddleSeg计算 mIoU

这是我改成的numpy版本的,应该可以直接用,下边是 Paddle 版本的

def calculate_area(pred, label, num_classes, ignore_index=255):
    """
    Calculate intersect, prediction and label area
    该函数用于计算交集、prediction 和 label 的像素点数

    Args:
        pred (Tensor): The prediction by model.
        label (Tensor): The ground truth of image.
        num_classes (int): The unique number of target classes.
        ignore_index (int): Specifies a target value that is ignored. Default: 255.

    Returns:
        Tensor: The intersection area of prediction and the ground on all class.
        Tensor: The prediction area on all class.
        Tensor: The ground truth area on all class
    """
    # 如果 pred.shape == (1, 1, 224, 224) 则将第一维去掉
    if len(pred.shape) == 4:
        pred = np.squeeze(pred, axis=1)
    if len(label.shape) == 4:
        label = np.squeeze(label, axis=1)
    if not pred.shape == label.shape:
        raise ValueError('Shape of `pred` and `label should be equal, '
                         'but there are {} and {}.'.format(pred.shape,
                                                           label.shape))
    
    # 这一步往上得到的 pred.shape == label.shape == (1, 224, 224)
    pred_area = []
    label_area = []
    intersect_area = []
    mask = label != ignore_index # 该 mask 用于将 ignore_index 忽略

    for i in range(num_classes): # 开始迭代每一个类
    
    	# 将 pred 中是第 i 类的位置拿出来
        pred_i = np.logical_and(pred == i, mask)
        # 将 label 中第 i 类的位置拿出来
        label_i = label == i
        # 二者做与操作,将二者相同的位置拿出来
        intersect_i = np.logical_and(pred_i, label_i)
        
        # bool -> int32 后求和,送入对应的list
        # pred_area.append(paddle.sum(np.cast(pred_i, "int32")))
        # label_area.append(paddle.sum(np.cast(label_i, "int32")))
        # intersect_area.append(paddle.sum(np.cast(intersect_i, "int32")))
        pred_area.append(np.sum(pred_i.astype("int32")))
        label_area.append(np.sum(label_i.astype("int32")))
        intersect_area.append(np.sum(intersect_i.astype("int32")))
	
	# 将以上list转变为 Paddle Tensor
    pred_area = np.array(pred_area)
    label_area = np.array(label_area)
    intersect_area = np.array(intersect_area)

    return intersect_area, pred_area, label_area



def mean_iou(intersect_area, pred_area, label_area):
    """
    Calculate iou.
    计算 IoU

    Args:
        intersect_area (Tensor): The intersection area of prediction and ground truth on all classes.
        pred_area (Tensor): The prediction area on all classes.
        label_area (Tensor): The ground truth area on all classes.

    Returns:
        np.ndarray: iou on all classes.
        float: mean iou of all classes.
    """
    
	# 计算并集
    union = pred_area + label_area - intersect_area
    
    class_iou = []
    for i in range(len(intersect_area)):
        if union[i] == 0:
        	# 如果一个该类的像素都没有,则并集
            iou = 0
        else:
        	# 计算交并比
            iou = intersect_area[i] / union[i]
        class_iou.append(iou)
    # 计算均值
    miou = np.mean(class_iou)
    return np.array(class_iou), miou

来看下 Paddleseg/utils/metrics.py 计算 mIoU 的过程

calculate_area 函数用来计算相交的区域,

送入的 pred 和 label 形如下(1, H, W):
(类别0到4,0为背景类)

[[[0 2 3 4 1 0 0]
  [3 2 3 4 1 4 0]
  [3 2 4 4 1 0 4]
  [3 2 3 4 1 4 1]
  [3 2 4 4 1 0 0]]]
def calculate_area(pred, label, num_classes, ignore_index=255):
    """
    Calculate intersect, prediction and label area
    该函数用于计算交集、prediction 和 label 的像素点数

    Args:
        pred (Tensor): The prediction by model.
        label (Tensor): The ground truth of image.
        num_classes (int): The unique number of target classes.
        ignore_index (int): Specifies a target value that is ignored. Default: 255.

    Returns:
        Tensor: The intersection area of prediction and the ground on all class.
        Tensor: The prediction area on all class.
        Tensor: The ground truth area on all class
    """
    # 如果 pred.shape == (1, 1, 224, 224) 则将第一维去掉
    if len(pred.shape) == 4:
        pred = paddle.squeeze(pred, axis=1)
    if len(label.shape) == 4:
        label = paddle.squeeze(label, axis=1)
    if not pred.shape == label.shape:
        raise ValueError('Shape of `pred` and `label should be equal, '
                         'but there are {} and {}.'.format(pred.shape,
                                                           label.shape))
    
    # 这一步往上得到的 pred.shape == label.shape == (1, 224, 224)
    pred_area = []
    label_area = []
    intersect_area = []
    mask = label != ignore_index # 该 mask 用于将 ignore_index 忽略

    for i in range(num_classes): # 开始迭代每一个类
    
    	# 将 pred 中是第 i 类的位置拿出来
        pred_i = paddle.logical_and(pred == i, mask)
        # 将 label 中第 i 类的位置拿出来
        label_i = label == i
        # 二者做与操作,将二者相同的位置拿出来
        intersect_i = paddle.logical_and(pred_i, label_i)
        
        # bool -> int32 后求和,送入对应的list
        pred_area.append(paddle.sum(paddle.cast(pred_i, "int32")))
        label_area.append(paddle.sum(paddle.cast(label_i, "int32")))
        intersect_area.append(paddle.sum(paddle.cast(intersect_i, "int32")))
	
	# 将以上list转变为 Paddle Tensor
    pred_area = paddle.concat(pred_area)
    label_area = paddle.concat(label_area)
    intersect_area = paddle.concat(intersect_area)

    return intersect_area, pred_area, label_area

打印一下 intersect_area, pred_area, label_area 三个变量的值:

>>> intersect_area
[ 97721 147687]

>>> pred_area
[ 99482 151398]

>>> label_area
[101432 149448]

然后调用:

metrics_input = (intersect_area, pred_area, label_area)
class_iou, miou = metrics.mean_iou(*metrics_input)
def mean_iou(intersect_area, pred_area, label_area):
    """
    Calculate iou.
    计算 IoU

    Args:
        intersect_area (Tensor): The intersection area of prediction and ground truth on all classes.
        pred_area (Tensor): The prediction area on all classes.
        label_area (Tensor): The ground truth area on all classes.

    Returns:
        np.ndarray: iou on all classes.
        float: mean iou of all classes.
    """
    # 用 .numpy() 转化为 np.ndarray 
    intersect_area = intersect_area.numpy()
    pred_area = pred_area.numpy()
    label_area = label_area.numpy()
    
	# 计算并集
    union = pred_area + label_area - intersect_area
    
    class_iou = []
    for i in range(len(intersect_area)):
        if union[i] == 0:
        	# 如果一个该类的像素都没有,则并集
            iou = 0
        else:
        	# 计算交并比
            iou = intersect_area[i] / union[i]
        class_iou.append(iou)
    # 计算均值
    miou = np.mean(class_iou)
    return np.array(class_iou), miou
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值