using System;
|
using HalconDotNet;
|
using System.ComponentModel;
|
using System.Windows.Forms;
|
using System.Data;
|
|
|
namespace HalconTools
|
{
|
/// <summary>
|
/// This class optimizes the performance of a defined shape-based model
|
/// for a given set of test images.
|
/// To perform an optimization of the detection parameters, the instance
|
/// has to know the used set of matching parameters and the calling
|
/// MatchingAssistant, to retrieve the set of test images and to call
|
/// the methods for finding the model.
|
/// The optimization is performed in the sense that the two detection
|
/// parameters ScoreMin and Greediness are iteratively increased and
|
/// decreased, respectively, and every new parameter combination is used
|
/// to detect the model in the set of test images. Each performance is
|
/// then measured and compared with the best performance so far.
|
/// The single execution steps are triggered by a timer from the
|
/// class MatchingAssistant, so that you can stop the optimization anytime
|
/// during the run.
|
/// </summary>
|
public class MatchingOptSpeed: MatchingOpt
|
{
|
// private class members
|
private int mCurrScoreMin;
|
private int mCurrGreediness;
|
private double mCurrMeanTime;
|
private int mScoreMinStep;
|
private int mGreedinessStep;
|
|
private int mOptScoreMin;
|
private int mOptGreediness;
|
private double mOptMeanTime;
|
|
private int mMatchesNum;
|
private int mExpMatchesNum;
|
|
|
/// <summary>Constructor</summary>
|
/// <param name="mAss">MatchingAssistant that created this instance</param>
|
/// <param name="mPars">Current set of matching parameters</param>
|
public MatchingOptSpeed(MatchingAssistant mAss, MatchingParam mPars)
|
{
|
mAssistant = mAss;
|
mParams = mPars;
|
NotifyStatisticsObserver = new StatisticsDelegate(dummy);
|
|
mScoreMinStep = -10;
|
mGreedinessStep = 10;
|
reset();
|
|
tImageCount = mAssistant.TestImages.Count;
|
}
|
|
|
/// <summary>
|
/// In each execution step a certain parameter set is applied
|
/// to the whole set of test images and the performance is then
|
/// evaluated.
|
/// </summary>
|
public override bool ExecuteStep()
|
{
|
double cScoreMin, cGreed, recogRate;
|
string fileName;
|
int actualMatches, expectedMatches;
|
bool success;
|
|
if(!iterator.MoveNext())
|
return false;
|
|
|
cScoreMin = mCurrScoreMin / 100.0;
|
cGreed = mCurrGreediness / 100.0;
|
|
statusString = "Testing Image " + (mCurrentIndex + 1) +
|
" - Minimum Score: " + cScoreMin +
|
" - Greediness: " + cGreed;
|
|
NotifyStatisticsObserver(MatchingOpt.UPDATE_RECOG_STATISTICS_STATUS);
|
|
fileName = (string)iterator.Current;
|
|
mAssistant.setTestImage(fileName);
|
|
mAssistant.setMinScore(cScoreMin);
|
mAssistant.setGreediness(cGreed);
|
|
if(!mAssistant.applyFindModel())
|
return false;
|
|
|
mResults = mAssistant.getMatchingResults();
|
actualMatches = mResults.count;
|
|
expectedMatches = 0;
|
|
switch(mParams.mRecogSpeedMode)
|
{
|
case MatchingParam.RECOGM_MANUALSELECT:
|
expectedMatches = mParams.mRecogManualSel;
|
break;
|
case MatchingParam.RECOGM_ATLEASTONE:
|
expectedMatches = 1;
|
if(actualMatches > 1)
|
actualMatches = 1;
|
break;
|
case MatchingParam.RECOGM_MAXNUMBER:
|
expectedMatches = mParams.mNumMatches;
|
break;
|
default:
|
break;
|
}
|
|
mMatchesNum += actualMatches;
|
mExpMatchesNum += expectedMatches;
|
|
|
recogRate = (mExpMatchesNum > 0) ?
|
(100.0 * mMatchesNum / mExpMatchesNum) : 0.0;
|
|
mCurrMeanTime = mCurrMeanTime * mCurrentIndex + mResults.mTime;
|
mCurrMeanTime /= ++mCurrentIndex;
|
|
//write data into strings and call for update
|
recogTabOptimizationData [0] = "" + Math.Round(cScoreMin, 2);
|
recogTabOptimizationData [1] = "" + Math.Round(cGreed, 2);
|
recogTabOptimizationData [2] = "" + Math.Round(recogRate, 2) + " %";
|
|
if( mCurrMeanTime < 1000.0 )
|
recogTabOptimizationData [3] = Math.Round(mCurrMeanTime, 2) + " ms";
|
else
|
recogTabOptimizationData [3] = Math.Round(mCurrMeanTime/1000.0, 2)+ " s";
|
|
NotifyStatisticsObserver(MatchingOpt.UPDATE_RECOG_UPDATE_VALS);
|
|
if(mCurrentIndex < tImageCount)
|
return true;
|
|
iterator.Reset();
|
mCurrentIndex = 0;
|
mMatchesNum = 0;
|
mExpMatchesNum = 0;
|
|
success = (mParams.mRecogRateOpt == 0) ?
|
(Math.Abs((double)recogRate - mParams.mRecogRate) < 0.001)
|
: (recogRate >= (mParams.mRecogRate - 0.000001));
|
|
|
if(success)
|
{
|
mOptSuccess = true;
|
if(mCurrMeanTime < mOptMeanTime)
|
{
|
mOptScoreMin = mCurrScoreMin;
|
mOptGreediness = mCurrGreediness;
|
|
this.recogTabOptimizationData[4] = "" + Math.Round(mOptScoreMin/100.0, 2);
|
this.recogTabOptimizationData[5] = "" + Math.Round(mOptGreediness/100.0, 2);
|
this.recogTabOptimizationData[6] = Math.Round(recogRate, 2) + " %";
|
|
mOptMeanTime = mCurrMeanTime;
|
recogTabOptimizationData[7] = recogTabOptimizationData[3];
|
NotifyStatisticsObserver(MatchingOpt.UPDATE_RECOG_OPTIMUM_VALS);
|
}
|
mCurrGreediness += mGreedinessStep;
|
return (mCurrGreediness <= 100);
|
}
|
|
mCurrScoreMin += mScoreMinStep;
|
|
if(mOptSuccess)
|
return (mCurrScoreMin >= 10);
|
|
return (mCurrScoreMin > 0);
|
}
|
|
|
/// <summary>
|
/// Resets all parameters for evaluating the performance to their initial values.
|
/// </summary>
|
public override void reset()
|
{
|
mOptSuccess = false;
|
|
for(int i=0; i<8; i++)
|
this.recogTabOptimizationData[i]="-";
|
|
statusString = "Optimization Status:";
|
|
mCurrScoreMin = 100;
|
mCurrGreediness = 0;
|
mCurrMeanTime = 0.0;
|
|
mOptScoreMin = 100;
|
mOptGreediness = 0;
|
mOptMeanTime = Double.MaxValue;
|
|
mMatchesNum = 0;
|
mExpMatchesNum = 0;
|
|
tImageCount = mAssistant.TestImages.Count;
|
iterator = mAssistant.TestImages.Keys.GetEnumerator();
|
mCurrentIndex = 0;
|
}
|
|
|
/// <summary>
|
/// 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.
|
/// </summary>
|
public override void stop()
|
{
|
if(tImageCount==0)
|
{
|
NotifyStatisticsObserver(MatchingAssistant.ERR_NO_TESTIMAGE);
|
NotifyStatisticsObserver(MatchingOpt.RUN_FAILED);
|
}
|
else if(!mOptSuccess && (mCurrScoreMin==0.0))
|
{
|
NotifyStatisticsObserver(MatchingOpt.UPDATE_RECOG_ERR);
|
NotifyStatisticsObserver(MatchingOpt.RUN_FAILED);
|
}
|
else if(!mOptSuccess)
|
{
|
NotifyStatisticsObserver(MatchingOpt.UPDATE_TEST_ERR);
|
NotifyStatisticsObserver(MatchingOpt.RUN_FAILED);
|
}
|
else
|
{
|
statusString = "Optimization finished successfully";
|
NotifyStatisticsObserver(MatchingOpt.UPDATE_RECOG_STATISTICS_STATUS);
|
mAssistant.setMinScore(mOptScoreMin/100.0);
|
mAssistant.setGreediness(mOptGreediness/100.0);
|
NotifyStatisticsObserver(MatchingOpt.RUN_SUCCESSFUL);
|
}
|
}
|
}//end of class
|
}//end of namespace
|