图像分割结果的评估

来源:互联网 发布:isp图像处理编程 编辑:程序博客网 时间:2024/05/01 09:42

我们在用一个算法对一幅图像进行分割之后,总会面临这样一个问题,分割的结果到底好不好。用眼睛可以看出好坏,但这只是主观的好坏,如何量化的对分割的结果进行评价呢,这是这篇文章我要讨论的主题。

 

我查阅过很多方法,包括ROC曲线,Dice重合率等等,要么是我理解不好,要么是难以实现。下面的代码,将基于GT(ground truth)图像计算分割图像的分割精度、过分割率、欠分割等指标来评估算法的分割结果。

 

首先简要介绍一下相关概念

GT(ground truth)图像:我理解的就是含有理论分割结果的图像,用来和结果图像进行比较的参照图像。那么GT图像怎么来,一般通过专家手工勾画出来,得到理论值。当然为避免偶然性,你可以选择多个专家,得到多个GT分割结果,取各项评估参数的平均值。

分割精度:个人理解就是分割准确的面积占GT图像中真实面积的百分比。找了半天找了这么个公式(如下)。


不难理解,其中表示专家手工勾画出的分割图像的参考面积,表示算法分割得到的图像的真实面积,表示错误分割的像素点个数。

过分割率:即分割在GT图像参考面积之外的像素点的比率,计算公式如下:


含义同上,表示本不应该包含在分割结果中的像素点个数,实际却在分割结果中的像素点个数。换句话讲,中的像素点出现在实际分割图像中,但不出现在理论分割图像中。

欠分割率:即分割在GT图像参考面积之中欠缺的像素点的比率,计算的公式如下:


含义同上,表示本应该包含在分割结果中的像素点个数,实际却不在分割结果中的像素点个数。换句话讲,中的像素点出现在理论分割图像中,但不出现在实际分割图像中。

 

好了,理论介绍完了,下面看一下效果和代码吧,我把我做头发分割的结果拿来做一下测试。


测试结果如下:

 

计算的各类参数如下:

 


如果大家对我头发分割的算法有疑问或者感兴趣,欢迎给我留言!

 

下面奉上我的代码:



/*************************************************************************
//为图像分割的结果提供评价标准
//预先人工绘制GT图像作为参考,与分割图像进行过分割率和欠分割率的计算
************************************************************************/


#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdlib.h>


void getCounterImage(IplImage* src,IplImage* test,IplImage* dst);


using namespace std;


FILE *fp;


int main()
{
IplImage* testImg;  // 测试图像;
IplImage* gtImg;   //参照图像;
IplImage* counterImg;  //轮廓图像;
fp = fopen("meanshift 方法.txt","w+");
fprintf(fp,"%s","图像编号           ");
fprintf(fp,"%s","分割准确率           ");
fprintf(fp,"%s","过分割率           ");
fprintf(fp,"%s","欠分割率           ");
int i = 1;
while(i<=5){
fprintf(fp,"%s","\n");
fprintf(fp,"%d",i);
char fileName[100] = "E:\\testdata\\Judge\\om_hair_dilate";
char gtFileName[100] = "E:\\testdata\\Judge\\gtHair";
char NumStr[10];
char JpgStr[10]=".jpg";
char ResStr[100]="res";
itoa(i,NumStr,10);
strcat(fileName,NumStr);
strcat(fileName,JpgStr);
strcat(gtFileName,NumStr);
strcat(gtFileName,JpgStr);
testImg = cvLoadImage(fileName);
gtImg = cvLoadImage(gtFileName);
counterImg = cvCreateImage(cvGetSize(gtImg),8,1);  //单通道图像
cvZero(counterImg);
getCounterImage(gtImg,testImg,counterImg);

cvShowImage("testImage",testImg);


cvShowImage("gtImage",gtImg);
cvMoveWindow("gtImage",0,0);
cvReleaseImage(&counterImg);
char c=cvWaitKey();
if(32==c)
        i++;
}
fclose(fp);
cvWaitKey(0);
}


void getCounterImage(IplImage* src,IplImage* test,IplImage* dst)
{
double SegRate;       //分割准确率;
double OverSegRate;   //过分割率;
double LessSegRate;   //欠分割率;
CvScalar BLACK = CV_RGB(0,0,0);
CvScalar WHITE = CV_RGB(255,255,255);


for (int i = 0; i <src->height;i++)
for (int j = 0; j <src->width;j++)
{
CvScalar pixel = cvGet2D(src,i,j);
if(pixel.val[2]>200 && pixel.val[0]<50 && pixel.val[1]<50)
{
cvSet2D(dst,i,j,BLACK);
}
else
cvSet2D(dst,i,j,WHITE);
}
//cvShowImage("test",dst);
cvThreshold(dst,dst,150,255,CV_THRESH_BINARY_INV);
//查找轮廓;
CvSeq *pContour = NULL;
CvSeq *pConInner = NULL;
CvMemStorage *pStorage = NULL;
if(dst)
{
pStorage = cvCreateMemStorage(0);
cvFindContours(dst,pStorage,&pContour,sizeof(CvContour), CV_RETR_EXTERNAL , CV_CHAIN_APPROX_SIMPLE);
cvDrawContours(dst, pContour, CV_RGB(255, 255, 255), CV_RGB(255,255,255), -1, CV_FILLED, 8, cvPoint(0, 0)); 
}

cvNamedWindow("counter",0);
cvThreshold(dst,dst,150,255,CV_THRESH_BINARY_INV);
cvShowImage("counter",dst);
//cvShowImage("judge",test);
//cvSaveImage("gt1.jpg",dst);


/**开始计算过分割率和欠分割率**/
int x,y;
int SegNum=0;   //分割准确的像素点个数;
int OverSegNum=0;   //过分割的像素点个数;
int LessSegNum=0;   //欠分割的像素点个数;
int GTNum=0;     //真实像素点个数;
for (int i = 0; i <dst->height;i++)
for (int j = 0; j <dst->width;j++)
{
x = cvGet2D(test,i,j).val[0]; //分割图像
y = cvGet2D(dst,i,j).val[0];  //参照图像
if(x==0)
SegNum++;
if(y==0)
{
GTNum++;
if(x!=0)
LessSegNum++;
}
else if(x==0)
OverSegNum++;
}


SegRate = 1-(double)(abs(GTNum-SegNum))/GTNum; //分割准确率;
OverSegRate = (double)OverSegNum/(GTNum+OverSegNum);   //过分割率;
LessSegRate = (double)LessSegNum/(GTNum+OverSegNum);   //欠分割率;
cout<<"分割准确率:"<<SegRate<<endl;
cout<<"过分割率:"<<OverSegRate<<endl;
cout<<"欠分割率:"<<LessSegRate<<endl;
fprintf(fp,"%s","                  ");
fprintf(fp,"%f",SegRate);
fprintf(fp,"%s","             ");
fprintf(fp,"%f",OverSegRate);
fprintf(fp,"%s","              ");
fprintf(fp,"%f",LessSegRate);


}


Junzzy所写,欢迎大家指正!

0 0
原创粉丝点击