1. 程式人生 > 其它 >遙感影象語義分割基礎知識——常用精度指標及其Python實現

遙感影象語義分割基礎知識——常用精度指標及其Python實現

深度學習中的常用精度指標:

前言

在介紹精度指標前我們先來明確以下幾個概念,對應的示意圖如下圖所示:

TP(True Positive):分類準確的正類,意思是預測結果為正類,實際上是正類。

FP(False Positive):被錯分類為正類的負類,意思是實際為負類,但是卻被預測為正類。

TN(True Negative):分類準確的負類,意思是預測結果為負類,實際上是負類。

FN(False Negative):被錯分類為負類的正類,意思是實際為正類,但是卻被預測為負類。

精度評價指標

1.精確率

精確率(Precision)就是被準確分類為正類的樣本數與所有被分類為正類的樣本數之比,意味著預測結果是正類的樣本里具體有多少個樣本真的是正類,計算方法如下式所示:

2.召回率

召回率(Recall)就是被分為正類的樣本數與測試資料集中的實際正類的樣本數之比,意味著應該被分為正類的樣本中會有多少是被正確分類出來,如下式所示:

3.F1分數

我們希望精確率和召回率同時非常高。但實際上這兩個指標是一對矛盾體,無法做到雙高。如果想要找到二者之間的一個平衡點,我們就需要一個新的指標:F1分數(F1-Score)。F1分數同時考慮了查準率和查全率,讓二者同時達到最高,取一個平衡。計算方法如下式所示:

4.交併比

交併比(Intersection-over-Union, IoU)是指實際類別樣本和預測類別樣本的交集和並集之比,即分類準確的正類樣本數和分類準確的正類樣本數與被錯分類為負類的正類樣本數以及被錯分類為正類的負類之和的比值。計算方法如下式所示:

5.平均交併比

平均交併比(mean Intersection-over-Union, mIoU)是對每一類交併比求和平均的結果。計算方法如下式所示:

 

6 頻權交併比

頻權交併比(Frequency Weighted Intersection-over-Union, FWIoU)是根據每一類出現的頻率設定權重,權重乘以每一類的IoU並進行求和。計算方法如下式所示:

python實現

import numpy as np
import cv2
import os

""" 
混淆矩陣
P\L     P    N 
P      TP    FP 
N      FN    TN 
"""

#  獲取顏色字典
#  labelFolder 標籤資料夾,之所以遍歷資料夾是因為一張標籤可能不包含所有類別顏色
#  classNum 類別總數(含背景)
def color_dict(labelFolder, classNum):
	colorDict = []
	#  獲取資料夾內的檔名
	ImageNameList = os.listdir(labelFolder)
	for i in range(len(ImageNameList)):
		ImagePath = labelFolder + "/" + ImageNameList[i]
		img = cv2.imread(ImagePath).astype(np.uint32)
		#  如果是灰度,轉成RGB
		if (len(img.shape) == 2):
			img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB).astype(np.uint32)
		#  為了提取唯一值,將RGB轉成一個數
		img_new = img[:, :, 0] * 1000000 + img[:, :, 1] * 1000 + img[:, :, 2]
		unique = np.unique(img_new)
		#  將第i個畫素矩陣的唯一值新增到colorDict中
		for j in range(unique.shape[0]):
			colorDict.append(unique[j])
		#  對目前i個畫素矩陣裡的唯一值再取唯一值
		colorDict = sorted(set(colorDict))
		#  若唯一值數目等於總類數(包括背景)ClassNum,停止遍歷剩餘的影象
		if (len(colorDict) == classNum):
			break
	#  儲存顏色的BGR字典,用於預測時的渲染結果
	colorDict_BGR = []
	for k in range(len(colorDict)):
		#  對沒有達到九位數字的結果進行左邊補零(eg:5,201,111->005,201,111)
		color = str(colorDict[k]).rjust(9, '0')
		#  前3位B,中3位G,後3位R
		color_BGR = [int(color[0: 3]), int(color[3: 6]), int(color[6: 9])]
		colorDict_BGR.append(color_BGR)
	#  轉為numpy格式
	colorDict_BGR = np.array(colorDict_BGR)
	#  儲存顏色的GRAY字典,用於預處理時的onehot編碼
	colorDict_GRAY = colorDict_BGR.reshape((colorDict_BGR.shape[0], 1, colorDict_BGR.shape[1])).astype(np.uint8)
	colorDict_GRAY = cv2.cvtColor(colorDict_GRAY, cv2.COLOR_BGR2GRAY)
	return colorDict_BGR, colorDict_GRAY


def ConfusionMatrix(numClass, imgPredict, Label):
	#  返回混淆矩陣
	mask = (Label >= 0) & (Label < numClass)
	label = numClass * Label[mask] + imgPredict[mask]
	count = np.bincount(label, minlength=numClass ** 2)
	confusionMatrix = count.reshape(numClass, numClass)
	return confusionMatrix


def OverallAccuracy(confusionMatrix):
	#  返回所有類的整體畫素精度OA
	# acc = (TP + TN) / (TP + TN + FP + TN)
	OA = np.diag(confusionMatrix).sum() / confusionMatrix.sum()
	return OA


def Precision(confusionMatrix):
	#  返回所有類別的精確率precision
	precision = np.diag(confusionMatrix) / confusionMatrix.sum(axis=0)
	return precision


def Recall(confusionMatrix):
	#  返回所有類別的召回率recall
	recall = np.diag(confusionMatrix) / confusionMatrix.sum(axis=1)
	return recall


def F1Score(confusionMatrix):
	precision = np.diag(confusionMatrix) / confusionMatrix.sum(axis=0)
	recall = np.diag(confusionMatrix) / confusionMatrix.sum(axis=1)
	f1score = 2 * precision * recall / (precision + recall)
	return f1score


def IntersectionOverUnion(confusionMatrix):
	#  返回交併比IoU
	intersection = np.diag(confusionMatrix)
	union = np.sum(confusionMatrix, axis=1) + np.sum(confusionMatrix, axis=0) - np.diag(confusionMatrix)
	IoU = intersection / union
	return IoU


def MeanIntersectionOverUnion(confusionMatrix):
	#  返回平均交併比mIoU
	intersection = np.diag(confusionMatrix)
	union = np.sum(confusionMatrix, axis=1) + np.sum(confusionMatrix, axis=0) - np.diag(confusionMatrix)
	IoU = intersection / union
	mIoU = np.nanmean(IoU)
	return mIoU


def Frequency_Weighted_Intersection_over_Union(confusionMatrix):
	#  返回頻權交併比FWIoU
	freq = np.sum(confusionMatrix, axis=1) / np.sum(confusionMatrix)
	iu = np.diag(confusionMatrix) / (
			np.sum(confusionMatrix, axis=1) +
			np.sum(confusionMatrix, axis=0) -
			np.diag(confusionMatrix))
	FWIoU = (freq[freq > 0] * iu[freq > 0]).sum()
	return FWIoU


#################################################################
#  標籤影象資料夾
LabelPath = r""
#  預測影象資料夾
PredictPath = r""
#  類別數目(包括背景)
classNum = 2
#################################################################

#  獲取類別顏色字典
colorDict_BGR, colorDict_GRAY = color_dict(LabelPath, classNum)

#  獲取資料夾內所有影象
labelList = os.listdir(LabelPath)
PredictList = os.listdir(PredictPath)

#  讀取第一個影象,後面要用到它的shape
Label0 = cv2.imread(LabelPath + "//" + labelList[0], 0)

#  影象數目
label_num = len(labelList)

#  把所有影象放在一個數組裡
label_all = np.zeros((label_num,) + Label0.shape, np.uint8)
predict_all = np.zeros((label_num,) + Label0.shape, np.uint8)
for i in range(label_num):
	Label = cv2.imread(LabelPath + "//" + labelList[i])
	Label = cv2.cvtColor(Label, cv2.COLOR_BGR2GRAY)
	label_all[i] = Label
	Predict = cv2.imread(PredictPath + "//" + PredictList[i])
	Predict = cv2.cvtColor(Predict, cv2.COLOR_BGR2GRAY)
	predict_all[i] = Predict

#  把顏色對映為0,1,2,3...
for i in range(colorDict_GRAY.shape[0]):
	label_all[label_all == colorDict_GRAY[i][0]] = i
	predict_all[predict_all == colorDict_GRAY[i][0]] = i

#  拉直成一維
label_all = label_all.flatten()
predict_all = predict_all.flatten()

#  計算混淆矩陣及各精度引數
confusionMatrix = ConfusionMatrix(classNum, predict_all, label_all)
precision = Precision(confusionMatrix)
recall = Recall(confusionMatrix)
OA = OverallAccuracy(confusionMatrix)
IoU = IntersectionOverUnion(confusionMatrix)
FWIOU = Frequency_Weighted_Intersection_over_Union(confusionMatrix)
mIOU = MeanIntersectionOverUnion(confusionMatrix)
f1ccore = F1Score(confusionMatrix)

for i in range(colorDict_BGR.shape[0]):
	#  輸出類別顏色,需要安裝webcolors,直接pip install webcolors
	try:
		import webcolors

		rgb = colorDict_BGR[i]
		rgb[0], rgb[2] = rgb[2], rgb[0]
		print(webcolors.rgb_to_name(rgb), end="  ")
	#  不安裝的話,輸出灰度值
	except:
		print(colorDict_GRAY[i][0], end="  ")

print("")
print("混淆矩陣:")
print(confusionMatrix)
print("精確度:")
print(precision)
print("召回率:")
print(recall)
print("F1-Score:")
print(f1ccore)
print("整體精度:")
print(OA)
print("IoU:")
print(IoU)
print("mIoU:")
print(mIOU)
print("FWIoU:")
print(FWIOU)

感謝知乎大佬王正慶,大佬地址https://www.zhihu.com/people/WangZhenqing_AIR

參考部落格:https://zhuanlan.zhihu.com/p/150556249