using System;
using HalconDotNet;
namespace HalconTools
{
///
/// To determine the performance of a shape-based model, given
/// a parameter setup for model creation and detection,
/// this class applies a model detection for the whole set
/// of test images loaded and computes an all-over statistics.
///
public class MatchingOptStatistics: MatchingOpt
{
// recognize - group
private int mMatchesNumProb;
private bool mModelFound;
private int mSpecMatchesNum;
private int mMaxMatchesNum;
private int mFoundMatchesNum;
private int mImagesWithOneMatchNum;
private int mImagesWithSpecMatchesNum;
private int mImagesWithMaxMatchesNum;
// statistic - group
private double mScoreMin;
private double mScoreMax;
private double mTimeMin;
private double mTimeMax;
private double mRowMin;
private double mRowMax;
private double mColMin;
private double mColMax;
private double mAngleMin;
private double mAngleMax;
private double mScaleRowMin;
private double mScaleRowMax;
private double mScaleColMin;
private double mScaleColMax;
/// Constructor
/// MatchingAssistant that created this instance
/// Current set of matching parameters
public MatchingOptStatistics(MatchingAssistant mAss, MatchingParam mPars)
{
mAssistant = mAss;
mParams = mPars;
NotifyStatisticsObserver = new StatisticsDelegate(dummy);
reset();
tImageCount = mAssistant.TestImages.Count;
}
///
/// With each execution step the shape-based model is searched in
/// the current test image. The detection result is then compared
/// with the previous results and the overall statistics is adjusted.
///
public override bool ExecuteStep()
{
string fileName, imgNumStr;
int val, i;
string matchFormatStr;
int actualMatches;
int expectedMatches;
int maxNumMatches;
double score, time, row, col, angle, angleB, scaleR, scaleC;
if(!iterator.MoveNext())
return false;
fileName = (string)iterator.Current;
mAssistant.setTestImage(fileName);
if(!(mOptSuccess = mAssistant.applyFindModel()))
return false;
mResults = mAssistant.getMatchingResults();
actualMatches = mResults.count;
// determine recognition rate ------------------
expectedMatches = mParams.mRecogManualSel;
maxNumMatches = mParams.mNumMatches;
mSpecMatchesNum += expectedMatches;
mMaxMatchesNum += maxNumMatches;
mFoundMatchesNum += actualMatches;
if(actualMatches > 0)
mImagesWithOneMatchNum++;
if(actualMatches >= expectedMatches)
mImagesWithSpecMatchesNum++;
if(actualMatches == maxNumMatches)
mImagesWithMaxMatchesNum++;
mCurrentIndex++;
this.inspectTabRecogRateData[2] = "-";
this.inspectTabRecogRateData[3] = "-";
this.inspectTabRecogRateData[4] = "-";
imgNumStr = " of " + mCurrentIndex + " images)";
val = mImagesWithOneMatchNum;
this.inspectTabRecogRateData[0] = Math.Round(100.0* ((double)val / mCurrentIndex), 2)
+ " % (" + val + imgNumStr;
val = mImagesWithSpecMatchesNum;
this.inspectTabRecogRateData[1] = Math.Round(100.0* ((double) val / mCurrentIndex), 2)
+ " % (" + val + imgNumStr;
if(mMaxMatchesNum > 0)
{
matchFormatStr = " of " + mMaxMatchesNum + " models)";
val = mImagesWithMaxMatchesNum;
this.inspectTabRecogRateData[2] = Math.Round(100.0* ((double)val / mCurrentIndex), 2)
+ " % (" + val + imgNumStr;
val = mFoundMatchesNum;
this.inspectTabRecogRateData[3] = Math.Round(100.0*((double) val / mMaxMatchesNum), 2)
+ " % (" + val + matchFormatStr;
}
if(mSpecMatchesNum > 0)
{
matchFormatStr = " of " + mSpecMatchesNum + " models)";
val = mFoundMatchesNum;
this.inspectTabRecogRateData[4] = Math.Round(100.0* ((double)val / mSpecMatchesNum), 2)
+ " % (" + val + matchFormatStr;
}
NotifyStatisticsObserver(MatchingOpt.UPDATE_INSP_RECOGRATE);
// determine statistics data ------------
if(actualMatches > 0)
{
i=0;
if(!mModelFound)
{
mScoreMin = mScoreMax = mResults.mScore[0].D;
mTimeMin = mTimeMax = mResults.mTime;
mRowMin = mRowMax = mResults.mRow[0].D;
mColMin = mColMax = mResults.mCol[0].D;
mAngleMin = mAngleMax = mResults.mAngle[0].D;
mScaleRowMin= mScaleRowMax= mResults.mScaleRow[0].D;
mScaleColMin= mScaleColMax= mResults.mScaleCol[0].D;
mModelFound = true;
i++;
}
for(; i < actualMatches; i++)
{
score = mResults.mScore[i].D;
if(score < mScoreMin)
mScoreMin = score;
else if(score > mScoreMax)
mScoreMax = score;
row = mResults.mRow[i].D;
if(row < mRowMin)
mRowMin = row;
else if(row > mRowMax)
mRowMax = row;
col = mResults.mCol[i].D;
if(col < mColMin)
mColMin = col;
else if(col > mColMax)
mColMax = col;
angle = mResults.mAngle[i].D;
if(angle < mAngleMin)
mAngleMin = angle;
else if(angle > mAngleMax)
mAngleMax = angle;
scaleR = mResults.mScaleRow[i].D;
if(scaleR < mScaleRowMin)
mScaleRowMin = scaleR;
else if(scaleR > mScaleRowMax)
mScaleRowMax = scaleR;
scaleC = mResults.mScaleCol[i].D;
if(scaleC < mScaleColMin)
mScaleColMin = scaleC;
else if(scaleC > mScaleColMax)
mScaleColMax = scaleC;
}//end of for
time = mResults.mTime;
if(time < mTimeMin)
mTimeMin = time;
else if(time > mTimeMax)
mTimeMax = time;
}//end of if
if(mModelFound)
{
this.inspectTabStatisticsData[0] = "" + Math.Round(mScoreMin, 2);
this.inspectTabStatisticsData[1] = "" + Math.Round(mScoreMax, 2);
this.inspectTabStatisticsData[2] = "" + Math.Round((mScoreMax - mScoreMin),2);
this.inspectTabStatisticsData[3] = "" + Math.Round(mTimeMin, 2);
this.inspectTabStatisticsData[4] = "" + Math.Round(mTimeMax, 2);
this.inspectTabStatisticsData[5] = "" + Math.Round((mTimeMax - mTimeMin),2);
this.inspectTabStatisticsData[6] = "" + Math.Round(mRowMin, 2);
this.inspectTabStatisticsData[7] = "" + Math.Round(mRowMax, 2);
this.inspectTabStatisticsData[8] = "" + Math.Round((mRowMax - mRowMin), 2);
this.inspectTabStatisticsData[9] = "" + Math.Round(mColMin, 2);
this.inspectTabStatisticsData[10] = "" + Math.Round(mColMax, 2);
this.inspectTabStatisticsData[11] = "" + Math.Round((mColMax - mColMin), 2);
angle = (double)mAngleMin*180.0/Math.PI;
angleB = (double)mAngleMax*180.0/Math.PI;
this.inspectTabStatisticsData[12] = "" + Math.Round(angle, 2);
this.inspectTabStatisticsData[13] = "" + Math.Round(angleB, 2) ;
this.inspectTabStatisticsData[14] = "" + Math.Round((angleB - angle), 2) ;
this.inspectTabStatisticsData[15] = "" + Math.Round(mScaleRowMin, 2);
this.inspectTabStatisticsData[16] = "" + Math.Round(mScaleRowMax, 2);
this.inspectTabStatisticsData[17] = "" + Math.Round((mScaleRowMax - mScaleRowMin),2);
this.inspectTabStatisticsData[18] = "" + Math.Round(mScaleColMin, 2);
this.inspectTabStatisticsData[19] = "" + Math.Round(mScaleColMax, 2);
this.inspectTabStatisticsData[20] = "" + Math.Round((mScaleColMax - mScaleColMin), 2);
NotifyStatisticsObserver(MatchingOpt.UPDATE_INSP_STATISTICS);
}
return (mCurrentIndex < tImageCount);
}
///
/// Resets all parameters for evaluating the performance to their initial values.
///
public override void reset()
{
mMatchesNumProb = mParams.mNumMatches;
mModelFound = false;
mSpecMatchesNum = 0;
mMaxMatchesNum = 0;
mFoundMatchesNum = 0;
mImagesWithOneMatchNum = 0;
mImagesWithSpecMatchesNum = 0;
mImagesWithMaxMatchesNum = 0;
mOptSuccess = false;
for(int i=0; i < 21;i++)
this.inspectTabStatisticsData[i]="-";
inspectTabRecogRateData[0] = "100.00 % (1 of 1 image)";
inspectTabRecogRateData[1] = "100.00 % (1 of 1 image)";
inspectTabRecogRateData[2] = "100.00 % (1 of 1 image)";
inspectTabRecogRateData[3] = "100.00 % (1 of 1 model)";
inspectTabRecogRateData[4] = "100.00 % (1 of 1 model)";
tImageCount = mAssistant.TestImages.Count;
iterator = mAssistant.TestImages.Keys.GetEnumerator();
mCurrentIndex = 0;
}
///
/// If the optimization has stopped, then check whether it was
/// completed successfully or whether it was aborted
/// due to errors or to user interaction.
/// Depending on the failure or success of the run, the GUI is notified
/// for visual update of the results and obtained statistics.
///
public override void stop()
{
if(tImageCount==0)
{
NotifyStatisticsObserver(MatchingAssistant.ERR_NO_TESTIMAGE);
}
else if(!mOptSuccess)
{
NotifyStatisticsObserver(MatchingOpt.UPDATE_TEST_ERR);
}
}
}//end of class
}//end of namespace