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