文章目录
- 1 分割常用评价指标
- 1.1 什么是MIoU
- 1.2 什么是PA
- 1.2 什么是MPA
- 2 根据混淆矩阵计算评价指标
- 2.1 计算MIoU
- 2.2 计算PA
- 2.3 计算MPA
- 3 计算 MIoU 总体代码
- 4 compute_mIoU()函数 代码解析
- 5 输出展示实例
- 6 感谢链接
1 分割常用评价指标
1.1 什么是MIoU
MIoU全称为Mean Intersection over Union,平均交并比。计算两个集合之间交集和并集的比例。
M
I
o
U
=
1
k
∑
i
=
1
k
P
∩
G
P
∪
G
MIoU=\frac{1}{k} \sum_{i=1}^{k} \frac{P \cap G}{P \cup G}
MIoU=k1i=1∑kP∪GP∩G
或者说:在每个类上计算IoU,然后平均。
M
I
o
U
=
1
k
+
1
∑
i
=
0
k
p
i
i
∑
j
=
0
k
p
i
j
+
∑
j
=
0
k
p
j
i
−
p
i
i
MIoU=\frac{1}{k+1} \sum_{i=0}^{k} \frac{p_{ii}}{\sum_{j=0}^{k}p_{ij}+\sum_{j=0}^{k}p_{ji}-p_{ii}}
MIoU=k+11i=0∑k∑j=0kpij+∑j=0kpji−piipii
i 表示真实值,j 表示预测值 ,
p
i
j
p_{ij}
pij表示将 i 预测成 j 。
1.2 什么是PA
像素精度(Aixel Accuracy, PA),表示被正确分类的像素个数占总像素数的比例(指混淆矩阵中),也就是被正确分类的正例占所有正例的比例,结合2.2节的代码看。
P
A
=
∑
i
=
0
k
p
i
i
∑
i
=
0
k
∑
j
=
0
k
p
i
j
PA=\frac{\sum_{i=0}^{k}p_{ii}}{\sum_{i=0}^{k}\sum_{j=0}^{k}p_{ij}}
PA=∑i=0k∑j=0kpij∑i=0kpii
1.2 什么是MPA
均像素精度(Mean Pixel Accuracy, MPA),在PA基础上进行调整,为每个类别内像素正确分类概率的平均值。
M
P
A
=
1
k
+
1
∑
i
=
0
k
p
i
i
∑
j
=
0
k
p
i
j
MPA=\frac{1}{k+1} \sum_{i=0}^{k} \frac{p_{ii}}{\sum_{j=0}^{k}p_{ij}}
MPA=k+11i=0∑k∑j=0kpijpii
2 根据混淆矩阵计算评价指标
混淆矩阵:Confusion Matrix,用于直观展示每个类别的预测情况,能从中计算准确率(Accuracy)、精度(Precision)、召回率(Recall)、交并比(IoU)。
混淆矩阵是n*n
的矩阵(n是类别),对角线上的是正确预测的数量。
每一行之和是该类的真实样本数量,每一列之和是预测为该类的样本数量。
混淆矩阵的生成见详我的另一篇博客 np.bincount()用在分割领域生成混淆矩阵 。
结果类似于下图:
2.1 计算MIoU
假设求dog的IoU,如下图:
true_dog = (7+2+28+111+18+801+13+17+0+3) # 上图绿框
predict_dog = (1+0+8+48+13+801+4+17+1+0) # 上图黄框
# 因为分母的801加了两次,因此要减一次
iou_dog = 801 / (true_dog + predict_dog - 801)
按照dog求IoU的方法,对每个类别进行求值,再求平均,就是语义分割模型的MIoU值。
理论上说,MIoU值越大(越接近1),模型效果越好。
代码:
def Mean_Intersection_over_Union(confusion_matrix):
Per_class_IoU = np.diag(confusion_matrix) / (
np.sum(confusion_matrix, axis=1) + np.sum(confusion_matrix, axis=0) -
np.diag(confusion_matrix))
MIoU = np.nanmean(Per_class_IoU)
return MIoU
Mean_Intersection_over_Union(matrix)
其中函数解读:
np.diag(v, k=0): 提取对角线元素或构造对角线数组。
k: 对角线的位置参数,0为默认主对角线,1为主对角线偏上一个单位,-1为主对角线偏下一个单位,以此类推。
np.sum(v, axis): 如果axis为None,则数组所有元素求和,得到一个值。如果指定axis,则按指定轴求和,例如二维数组,
axis=0: 列和,返回数组
axis=1 or -1: 行和,返回数组
np.nanmean(): array中nan取值为0,且取均值时忽略它
2.2 计算PA
代码:
def Pixel_Accuracy(confusion_matrix):
Acc = np.diag(confusion_matrix).sum() / confusion_matrix.sum()
return Acc
Pixel_Accuracy(matrix)
2.3 计算MPA
代码:
def Pixel_Accuracy_Class(confusion_matrix):
per_class_Acc = np.diag(confusion_matrix) / confusion_matrix.sum(axis=1)
Acc = np.nanmean(per_class_Acc)
return Acc
Pixel_Accuracy_Class(matrix)
3 计算 MIoU 总体代码
在get_miou.py
代码中,给出了下列代码,完成计算miou的全部过程。
在往下看之前,需要先看DeeplabV3+获取数据集预测结果灰度图,或者你知道运行下方代码操作前,要先有数据集分割预测结果(8位灰度图png)存放在本地文件夹中即可。
import os
from PIL import Image
from tqdm import tqdm
from deeplab import DeeplabV3
from utils.utils_metrics import compute_mIoU, show_results
"""
进行指标评估需要注意:
该文件生成的图为灰度图,因为值比较小,按照PNG形式的图看是没有显示效果的,所以看到近似全黑的图是正常的。
"""
if __name__ == "__main__":
miou_mode = 2
num_classes = 21
name_classes = ["background","aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]
VOCdevkit_path = '../VOCdevkit'
image_ids = open(os.path.join(VOCdevkit_path, "VOC2007/ImageSets/Segmentation/val.txt"),'r').read().splitlines()
gt_dir = os.path.join(VOCdevkit_path, "VOC2007/SegmentationClass/")
miou_out_path = "miou_out"
pred_dir = os.path.join(miou_out_path, 'detection-results')
if miou_mode == 0 or miou_mode == 1:
if not os.path.exists(pred_dir):
os.makedirs(pred_dir)
print("Load model.")
deeplab = DeeplabV3()
print("Load model done.")
print("Get predict result.")
for image_id in tqdm(image_ids):
image_path = os.path.join(VOCdevkit_path, "VOC2007/JPEGImages/"+image_id+".jpg")
image = Image.open(image_path)
image = deeplab.get_miou_png(image)
image.save(os.path.join(pred_dir, image_id + ".png"))
print("Get predict result done.")
if miou_mode == 0 or miou_mode == 2:
print("Get miou.")
hist, IoUs, PA_Recall, Precision = compute_mIoU(gt_dir, pred_dir, image_ids, num_classes, name_classes)
print("Get miou done.")
4 compute_mIoU()函数 代码解析
针对一张图片,针对10张图片,针对验证集所有图片,函数理解要有深度。
import csv
import os
from os.path import join
import matplotlib.pyplot as plt
import numpy as np
import torch
import torch.nn.functional as F
from PIL import Image
def fast_hist(a, b, n):
k = (a >= 0) & (a < n)
return np.bincount(n * a[k].astype(int) + b[k], minlength=n ** 2).reshape(n, n)
def per_class_iu(hist):
return np.diag(hist) / np.maximum((hist.sum(1) + hist.sum(0) - np.diag(hist)), 1)
def per_class_PA_Recall(hist):
return np.diag(hist) / np.maximum(hist.sum(1), 1)
def per_class_Precision(hist):
return np.diag(hist) / np.maximum(hist.sum(0), 1)
def per_Accuracy(hist):
return np.sum(np.diag(hist)) / np.maximum(np.sum(hist), 1)
def compute_mIoU(gt_dir, pred_dir, png_name_list, num_classes, name_classes):
print('Num classes', num_classes)
hist = np.zeros((num_classes, num_classes))
gt_imgs = [join(gt_dir, x + ".png") for x in png_name_list]
pred_imgs = [join(pred_dir, x + ".png") for x in png_name_list]
for ind in range(len(gt_imgs)):
pred = np.array(Image.open(pred_imgs[ind]))
label = np.array(Image.open(gt_imgs[ind]))
if len(label.flatten()) != len(pred.flatten()):
print(
'Skipping: len(gt) = {:d}, len(pred) = {:d}, {:s}, {:s}'.format(
len(label.flatten()), len(pred.flatten()), gt_imgs[ind],
pred_imgs[ind]))
continue
hist += fast_hist(label.flatten(), pred.flatten(), num_classes)
if ind > 0 and ind % 10 == 0:
print('{:d} / {:d}: mIou-{:0.2f}%; mPA-{:0.2f}%; Accuracy-{:0.2f}%'.format(
ind,
len(gt_imgs),
100 * np.nanmean(per_class_iu(hist)),
100 * np.nanmean(per_class_PA_Recall(hist)),
100 * per_Accuracy(hist)
)
)
IoUs = per_class_iu(hist)
PA_Recall = per_class_PA_Recall(hist)
Precision = per_class_Precision(hist)
for ind_class in range(num_classes):
print('===>' + name_classes[ind_class] + ':\tIou-' + str(round(IoUs[ind_class] * 100, 2)) \
+ '; Recall (equal to the PA)-' + str(round(PA_Recall[ind_class] * 100, 2))+ '; Precision-' + str(round(Precision[ind_class] * 100, 2)))
print('===> mIoU: ' + str(round(np.nanmean(IoUs) * 100, 2)) + '; mPA: ' + str(round(np.nanmean(PA_Recall) * 100, 2)) + '; Accuracy: ' + str(round(per_Accuracy(hist) * 100, 2)))
return np.array(hist, np.int), IoUs, PA_Recall, Precision
5 输出展示实例
以mobilenetv2为backbone的deeplabv3+模型在voc上的评价指标输出演示:
Load model.
model_data/deeplab_mobilenetv2.pth model, and classes loaded.
Load model done.
Get predict result.
100%|████████████████████████████████████████| 1449/1449 [15:38<00:00, 1.54it/s]
Get predict result done.
Get miou.
Num classes 21
10 / 1449: mIou-42.30%; mPA-46.51%; Accuracy-95.15%
20 / 1449: mIou-48.72%; mPA-53.71%; Accuracy-94.98%
30 / 1449: mIou-54.87%; mPA-61.61%; Accuracy-94.93%
...中间删掉了
1430 / 1449: mIou-72.43%; mPA-82.89%; Accuracy-93.59%
1440 / 1449: mIou-72.46%; mPA-82.90%; Accuracy-93.60%
===>background: Iou-93.07; Recall (equal to the PA)-97.0; Precision-95.83
===>aeroplane: Iou-82.29; Recall (equal to the PA)-92.21; Precision-88.44
===>bicycle: Iou-41.94; Recall (equal to the PA)-87.43; Precision-44.63
===>bird: Iou-83.24; Recall (equal to the PA)-92.82; Precision-88.97
===>boat: Iou-62.78; Recall (equal to the PA)-78.5; Precision-75.81
===>bottle: Iou-70.33; Recall (equal to the PA)-87.74; Precision-78.0
===>bus: Iou-93.43; Recall (equal to the PA)-95.99; Precision-97.22
===>car: Iou-85.4; Recall (equal to the PA)-90.35; Precision-93.97
===>cat: Iou-88.13; Recall (equal to the PA)-94.02; Precision-93.36
===>chair: Iou-35.82; Recall (equal to the PA)-56.13; Precision-49.75
===>cow: Iou-79.71; Recall (equal to the PA)-86.17; Precision-91.4
===>diningtable: Iou-50.65; Recall (equal to the PA)-54.37; Precision-88.11
===>dog: Iou-80.32; Recall (equal to the PA)-90.76; Precision-87.47
===>horse: Iou-78.72; Recall (equal to the PA)-88.03; Precision-88.15
===>motorbike: Iou-82.17; Recall (equal to the PA)-91.93; Precision-88.56
===>person: Iou-80.3; Recall (equal to the PA)-86.76; Precision-91.51
===>pottedplant: Iou-57.04; Recall (equal to the PA)-70.01; Precision-75.49
===>sheep: Iou-82.15; Recall (equal to the PA)-89.21; Precision-91.22
===>sofa: Iou-46.13; Recall (equal to the PA)-51.58; Precision-81.36
===>train: Iou-84.59; Recall (equal to the PA)-89.52; Precision-93.89
===>tvmonitor: Iou-66.49; Recall (equal to the PA)-72.73; Precision-88.58
===> mIoU: 72.6; mPA: 83.01; Accuracy: 93.59
Get miou done.
6 感谢链接
https://blog.csdn.net/weixin_44791964/article/details/107687970
https://blog.csdn.net/weixin_44791964/article/details/120113686
https://www.jianshu.com/p/42939bf83b8a
https://www.bilibili.com/video/BV173411q7xF?p=15
https://blog.csdn.net/qq_41375318/article/details/108380694
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)