**轉載自 https://blog.csdn.net/zichen_ziqi/article/details/80408465**
機器學習&圖像分割——模型評價總結(含完整代碼)
- 模型評價的方法指標有很多,如:PR-curve,MAE,ROC,Precision,Recall,AUC,AP,mAP,DSI,VOE,RVD等等;
- 本文旨在介紹機器學習&圖像分割的模型評價指標,包括完整代碼,持續更新中......
- 碼字不易,若有幫助,懇請點贊,?????????
問題1:在顯著性檢測方面,假設現有三種方法(DSR,GMA,MCA)檢測標準數據庫中的部分圖像(還有原圖與真值圖),分別得到三種結果,如何求三種方法與真值圖之間的MAE(平均絕對誤差),並繪製PR-curve曲線圖呢?
(1)image原圖
(2)mask圖像 (ground truth,真值圖)
(3)resultsDSR圖像
(4)resultsGMA圖像
(5)resultsMCA圖像
文件夾內容如下圖,鏈接:https://pan.baidu.com/s/1Wg_necXBCYsCk7pf2s7gog 或PR-curve繪製,密碼:lka7
輸出結果爲:
具體實現——Matlab代碼如下:
- clear all;clc;close all;
- addpath('Functions\');%加載文件夾Functions中的函數
- %% 三種方法得到的結果路徑,以及真值圖路徑
- result1 = 'resultsDSR\';
- result2 = 'resultsMCA\';
- result3 = 'resultsGMR\';
- mask = 'mask\';
- %% 創建文件夾evaluation index,目的是保存PR曲線圖
- newFolder = 'evaluation index';
- if ~exist(newFolder)
- mkdir(newFolder);
- end
- %% Evaluation index 1: evaluating MAE
- resultSuffixDSR = '_DSR.png';
- resultSuffixMCA = '_MCA.png';
- resultSuffixGMR = '_stage1.png';
- gtSuffix = '.png';
-
- maeDSR = CalMeanMAE(result1, resultSuffixDSR, mask, gtSuffix);
- maeMCA = CalMeanMAE(result2, resultSuffixMCA, mask, gtSuffix);
- maeGMR = CalMeanMAE(result3, resultSuffixGMR, mask, gtSuffix);
- %% Evaluation index 2: ploting PR curve
- [rec1, prec1] = DrawPRCurve(result1, resultSuffixDSR, mask, gtSuffix, true, true, 'r');
- hold on
- [rec2, prec2] = DrawPRCurve(result2, resultSuffixMCA, mask, gtSuffix, true, true, 'g');
- hold on
- [rec3, prec3] = DrawPRCurve(result3, resultSuffixGMR, mask, gtSuffix, true, true, 'b');
- hold off;
- grid on;
- box on;
- xlabel('Recall');
- ylabel('Precision');
- % title(strcat('PR-curve',' ( ',sprintf(' MAE = %1.6f ',maeDSR),' )'));
- title('PR-curve');
- lg = legend({'DSR method','CA method','GMR method'});
- set(lg, 'location', 'southwest');
- k=1.2;
- set(gcf,'units',get(gcf,'paperunits'));
- set(gcf,'paperposition',get(gcf,'position')*k);
- saveas(gcf,strcat(newFolder,'\PR-curve','.bmp'));
問題2:醫學圖像分割領域中的模型評價指標總結
強烈建議參照以下兩篇文章:
《Performance measure characterization for evaluating neuroimage segmentation algorithms》
《Metrics for evaluating 3D medical imagesegmentation: analysis, selection, and tool》
度量指標分析工具github:https://github.com/Visceral-Project/EvaluateSegmentation
1、醫學圖像比賽(ISBI2017或者MICCAI2007)中常用到的幾個度量指標:DICE,VOE,RVD,ASD,MSD等等;如何編程實現?(Matlab代碼與Python代碼)
符號定義:
: 代表 ground truth的分割結果
:代表預測的分割結果
(1)DICE(值域爲[0,1]): 使用頻率最高。數學定義如下,具體表示兩個物體相交的面積佔總面積的比值,完美分割該值爲1。
(2)VOE(volumetric overlap error): 與DICE類似,數學定義如下,它將and操作換成了減法操作,以此來代表錯誤率。
(3)RVD(relative volume difference):表示兩者體積之間的差異,數學定義如下。
(4)ASD(average symmetric surface distance): 先定義 代表的是預測的中的邊界的像素,同樣地可以得到的定義。然後對的定義,同理可得的定義。那麼ASD的數學定義爲:
(5)MSD(maximum symmetric surface distance):與ASD定義比較類似,只不過把計算平均的操作替換成了計算最大值的操作。其數學定義爲:
參照博客:圖像分割評價標準。具體代碼見鏈接:https://pan.baidu.com/s/1C7BWIebYbE4EJIoGKtjLSA,密碼是:gjlb,內容如下:
(一)Matlab 具體的代碼實現如下:
主函數demo:
- clc;clear all;close all;
- %% step 1:讀入圖像
- SEG = imread('0009_CHS.png'); % 讀入分割圖像
- GT = imread('0009.png'); % 讀入真值圖像
-
- %% step 2:灰度化
- if (length(size(SEG))>2 && length(size(GT))>2)
- SEG = im2gray(SEG); % 灰度化分割圖像
- GT = im2gray(GT); % 灰度化真值圖像
- end
-
- %% step 3:二值化
- SEG = imbinarize(SEG); % 二值化分割圖像
- GT = imbinarize(GT); % 二值化真值圖像
-
- %% step 4:畫圖預覽
- figure(1),
- subplot(121),imshow(SEG);
- title('二值化後的分割圖像');
- subplot(122),imshow(GT);
- title('二值化後的真值圖像');
-
- %% step 5:計算各個評價指標
-
- % (1)計算DICE係數
- DSI = calDSI(SEG, GT);
- fprintf('(1) DICE係數: DSI = %.4f\n',DSI);
-
- % (2)計算VOE係數
- VOE = calVOE(SEG, GT);
- fprintf('(2) VOE係數: VOE = %.4f\n',VOE);
-
- % (3)計算RVD係數
- RVD = calRVD(SEG, GT);
- fprintf('(3) RVD係數: RVD = %.4f\n',RVD);
-
- % (4)計算Precision係數
- Precision = calPrecision(SEG, GT);
- fprintf('(4) Precision係數: Precision = %.4f\n',Precision);
-
- %(5)計算Recall係數
- Recall = calRecall(SEG, GT);
- fprintf('(5) Recall係數: Recall = %.4f\n\n\n',Recall);
-
- disp('其他評價指標的計算');
- % (6)其他評價指標的計算
- jaccard = Jaccard_Index(SEG, GT)
- sensitivity = getSensitivity(SEG, GT)
- hd = Hausdorff_Dist(SEG, GT)
- apd = Avg_PerpenDist(SEG, GT)
- confm_index = ConformityCoefficient(SEG, GT)
先看運行結果:
其中調用函數文件分別爲:
(a)calDSI函數文件:
- function DSI = calDSI(SEG, GT)
- % SEG, GT are the binary segmentation and ground truth areas, respectively.
- % 計算DICE係數,即DSI
- DSI = 2*double(sum(uint8(SEG(:) & GT(:)))) / double(sum(uint8(SEG(:))) + sum(uint8(GT(:))));
- end
(b) calVOE函數文件:
- function VOE = calVOE(SEG, GT)
- % SEG, GT are the binary segmentation and ground truth areas, respectively.
- % 計算VOE係數,即VOE
- VOE = 2*double(sum(uint8(SEG(:))) - sum(uint8(GT(:)))) / double(sum(uint8(SEG(:))) + sum(uint8(GT(:))));
- end
(c) calRVD函數文件:
- function RVD = calRVD(SEG, GT)
- % SEG, GT are the binary segmentation and ground truth areas, respectively.
- % 計算RVD係數,即RVD
- RVD = double(sum(uint8(SEG(:))) ) / double(sum(uint8(GT(:)))) - 1;
- end
(d) calPrecision函數文件:
- function precision = calPrecision(SEG, GT)
- % SEG, GT are the binary segmentation and ground truth areas, respectively.
- % precision
- precision = double(sum(uint8(SEG(:) & GT(:)))) / double(sum(uint8(SEG(:))));
- end
(e) calRecall函數文件:
- function recall = calRecall(SEG, GT)
- % SEG, GT are the binary segmentation and ground truth areas, respectively.
- % recall
- recall = double(sum(uint8(SEG(:) & GT(:)))) / double(sum(uint8(GT(:))));
- end
(f) 其他指標的函數文件見以上鍊接。
(二)Python代碼如下:
- import cv2
- from matplotlib import pyplot as plt
-
-
- # 計算DICE係數,即DSI
- def calDSI(binary_GT,binary_R):
- row, col = binary_GT.shape # 矩陣的行與列
- DSI_s,DSI_t = 0,0
- for i in range(row):
- for j in range(col):
- if binary_GT[i][j] == 255 and binary_R[i][j] == 255:
- DSI_s += 1
- if binary_GT[i][j] == 255:
- DSI_t += 1
- if binary_R[i][j] == 255:
- DSI_t += 1
- DSI = 2*DSI_s/DSI_t
- # print(DSI)
- return DSI
-
- # 計算VOE係數,即VOE
- def calVOE(binary_GT,binary_R):
- row, col = binary_GT.shape # 矩陣的行與列
- VOE_s,VOE_t = 0,0
- for i in range(row):
- for j in range(col):
- if binary_GT[i][j] == 255:
- VOE_s += 1
- if binary_R[i][j] == 255:
- VOE_t += 1
- VOE = 2*(VOE_t - VOE_s)/(VOE_t + VOE_s)
- return VOE
-
- # 計算RVD係數,即RVD
- def calRVD(binary_GT,binary_R):
- row, col = binary_GT.shape # 矩陣的行與列
- RVD_s,RVD_t = 0,0
- for i in range(row):
- for j in range(col):
- if binary_GT[i][j] == 255:
- RVD_s += 1
- if binary_R[i][j] == 255:
- RVD_t += 1
- RVD = RVD_t/RVD_s - 1
- return RVD
-
- # 計算Prevision係數,即Precison
- def calPrecision(binary_GT,binary_R):
- row, col = binary_GT.shape # 矩陣的行與列
- P_s,P_t = 0,0
- for i in range(row):
- for j in range(col):
- if binary_GT[i][j] == 255 and binary_R[i][j] == 255:
- P_s += 1
- if binary_R[i][j] == 255:
- P_t += 1
-
- Precision = P_s/P_t
- return Precision
-
- # 計算Recall係數,即Recall
- def calRecall(binary_GT,binary_R):
- row, col = binary_GT.shape # 矩陣的行與列
- R_s,R_t = 0,0
- for i in range(row):
- for j in range(col):
- if binary_GT[i][j] == 255 and binary_R[i][j] == 255:
- R_s += 1
- if binary_GT[i][j] == 255:
- R_t += 1
-
- Recall = R_s/R_t
- return Recall
-
-
-
- if __name__ == '__main__':
- # step 1:讀入圖像,並灰度化
- img_GT = cv2.imread('0009.png',0)
- img_R = cv2.imread('0009_CHS.png',0)
- # imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 灰度化
- # img_GT = img_GT[:,:,[2, 1, 0]]
- # img_R = img_R[:,: [2, 1, 0]]
-
- # step2:二值化
- # 利用大律法,全局自適應閾值 參數0可改爲任意數字但不起作用
- ret_GT, binary_GT = cv2.threshold(img_GT, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
- ret_R, binary_R = cv2.threshold(img_R, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
-
- # step 3: 顯示二值化後的分割圖像與真值圖像
- plt.figure()
- plt.subplot(121),plt.imshow(binary_GT),plt.title('真值圖')
- plt.axis('off')
- plt.subplot(122),plt.imshow(binary_R),plt.title('分割圖')
- plt.axis('off')
- plt.show()
-
-
- # step 4:計算DSI
- print('(1)DICE計算結果, DSI = {0:.4}'.format(calDSI(binary_GT,binary_R))) # 保留四位有效數字
-
- # step 5:計算VOE
- print('(2)VOE計算結果, VOE = {0:.4}'.format(calVOE(binary_GT,binary_R)))
-
- # step 6:計算RVD
- print('(3)RVD計算結果, RVD = {0:.4}'.format(calRVD(binary_GT,binary_R)))
-
- # step 7:計算Precision
- print('(4)Precision計算結果, Precision = {0:.4}'.format(calPrecision(binary_GT,binary_R)))
-
- # step 8:計算Recall
- print('(5)Recall計算結果, Recall = {0:.4}'.format(calRecall(binary_GT,binary_R)))
運行結果:
2、分割精度、過分割率、欠分割率的定義
(1)分割精度:分割準確的面積佔GT圖像中真實面積的百分比,數學定義如下:
其中表示專家手工勾畫出的分割圖像的參考面積,表示算法分割得到的圖像的真實面積,表示錯誤分割的像素點個數。
(2)過分割率:即分割在GT圖像參考面積之外的像素點的比率,數學定義如下:
其中表示本不應該包含在分割結果中的像素點個數,實際卻在分割結果中的像素點個數。換句話講,中的像素點出現在實際分割圖像中,但不出現在理論分割圖像中。
(3)欠分割率:即分割在GT圖像參考面積之中欠缺的像素點的比率,數學定義如下:
其中表示本應該包含在分割結果中的像素點個數,實際卻不在分割結果中的像素點個數。換句話講,中的像素點出現在理論分割圖像中,但不出現在實際分割圖像中。
3、靈敏度與特異度的定義
假設實驗圖像爲I,真實分割結果爲G,實際分割結果爲R。
(1)靈敏度:將實際是感興趣區域的像素點正確地判斷爲感興趣區域像素的比例,其衡量的是分割實驗中能分割感興趣區域的能力,其數學定義如下。
(1)特異度:將實際不是感興趣區域的像素點正確地判斷爲不是感興趣區域像素的比例,其衡量的是分割實驗中能正確判斷不是感興趣區域像素點的能力,其數學定義如下。
Matlab的靈敏度函數:
- function sen = getSensitivity(SEG, GT)
- % SEG, GT are the binary segmentation and ground truth areas, respectively.
- % sensitivity
- sen = double(sum(uint8(SEG(:) & GT(:)))) / double(sum(uint8(SEG(:))));
- end
參考網址:
1、如何在CSDN博客插入公式:http://private.codecogs.com/latex/eqneditor.php
2、圖像分割結果評價:https://blog.csdn.net/zhuason/article/details/52989091
3、圖像分割評價標準代碼:https://blog.csdn.net/yangyangyang20092010/article/details/51637073