using System;
using HalconDotNet;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace HalconTools
{
///
/// 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.
///
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;
/// Constructor
/// MatchingAssistant that created this instance
/// Current set of matching parameters
public MatchingOptSpeed(MatchingAssistant mAss, MatchingParam mPars)
{
mAssistant = mAss;
mParams = mPars;
NotifyStatisticsObserver = new StatisticsDelegate(dummy);
mScoreMinStep = -10;
mGreedinessStep = 10;
reset();
tImageCount = mAssistant.TestImages.Count;
}
///
/// In each execution step a certain parameter set is applied
/// to the whole set of test images and the performance is then
/// evaluated.
///
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);
}
///
/// Resets all parameters for evaluating the performance to their initial values.
///
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;
}
///
/// 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);
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