using System; using HalconDotNet; using System.Collections; namespace HalconTools { public delegate void MeasureDelegate(int value); /// /// The controller class MeasureAssistant controls /// the communication between the GUI and the model data that /// is used to parameterize the measuring. /// public class MeasureAssistant { /// Index of the selected ROI. public int mActRoiIdx; /// Reference to the ROI controller instance. private ROIController roiController; /// List of measure handles created for the list of ROIs. private ArrayList mMeasureList; /// Reference to list of ROI instances. private ArrayList mROIList; /// HALCON image used for measuring. public HImage mImage; public int mWidth; public int mHeight; /// Flag indicating whether measurements are performed between /// individual edges or edge pairs. public bool mSelPair; /// Minimum edge amplitude. public double mThresh; /// Sigma of Gaussian smoothing. public double mSigma; /// /// Width of the measure ROI (circular ROI: radius (half width) of the /// annulus; linear ROI: half height of the rectangle). /// public double mRoiWidth; public double mRoiHeight; /// Default value for the minimum edge amplitude. public double mInitThresh; /// Default value for the sigma of Gaussian smoothing. public double mInitSigma; /// Default value for the ROI width. public double mInitRoiWidth; /// /// Type of gray-value transition; determines how edges are /// selected (dark-light or light-dark transition). /// public string mTransition; /// Position of edges to select. public string mPosition; /// Type of interpolation to be used. public string mInterpolation; /// /// Length of the displayed edges. /// public int mDispEdgeLength; /// Error messages for failed measure actions. public HTuple exceptionText; /// /// Flag indicating whether files with internal camera parameters /// and camera pose are present and valid. /// public bool mIsCalibValid; /// /// Flag indicating whether measure results should be transformed /// into world coordinates. /// public bool mTransWorldCoord; /// /// Flag indicating whether the ROI width should be used for /// displaying the extracted edges (instead of mDispEdgeLength). /// public bool mDispROIWidth; /// /// Flag to add position coordinates of the detected (and /// selected) edges to the result table. /// public bool mDispPosition; /// /// Flag to add the pair width of the detected edge (and /// selected) pairs to the result table. /// public bool mDispPairWidth; /// /// Flag to add the edge amplitude of the detected (and /// selected) edge pairs to the result table. /// public bool mDispAmplitude; /// /// Flag to add the distance between consecutive detected (and /// selected) edges to the result table. /// public bool mDispDistance; /// File with internal camera parameters. public HTuple mCamParameter; /// Camera pose file. public HTuple mCamPose; /// Unit for transformation into world coordinates. public string mUnit; /// Constant indicating an update of measure instances. public const int EVENT_UPDATE_MEASUREMENT = 2; /// /// Constant indicating the removal of measure instances from the /// measure list mMeasureList. /// public const int EVENT_UPDATE_REMOVE = 3; /// Constant indicating an update of measure results. public const int EVENT_UPDATE_RESULT_XLD = 4; /// Auxiliary constant. public const int ALL_ROI =-1; /// /// Constant indicating an error while reading an image file. public const int ERR_READING_FILE = 10; public MeasureDelegate NotifyMeasureObserver; /* To create the measure controller class the ROI controller has to be provided for initialization */ public MeasureAssistant(ROIController CRoi) { exceptionText = ""; roiController = CRoi; mROIList = roiController.getROIList(); mMeasureList = new ArrayList(15); mIsCalibValid = false; mActRoiIdx = -1; } /*********************************************************/ /* setter-methods */ /*********************************************************/ /// /// Sets a flag to determine if measure detection is calculated /// for edges or edge pairs /// public void setSelPair(bool mode) { mSelPair = mode; UpdateMeasure(); mActRoiIdx = roiController.getActiveROIIdx(); } /// /// Sets the variable mThresh to the provided value and /// triggers an update for the measure results /// public void setMinEdgeAmpl(double val) { mThresh = val; UpdateExecute(ALL_ROI); } /// /// Sets the variable mSigma to the provided value and /// triggers an update for the measure results /// public void setSigma(double val) { mSigma = val; UpdateExecute(ALL_ROI); } /// /// Sets the variable mRoiWidth to the provided value and /// triggers an update for the measure results /// public void setRoiWidth(double val) { mRoiWidth = val; UpdateMeasure(ALL_ROI); } public void setRoiHeight(double val) { mRoiHeight = val; UpdateMeasure(ALL_ROI); } /// /// Sets the variable mInterpolation to the provided value and /// triggers an update for the measure results /// public void setInterpolation(string mode) { mInterpolation = mode; UpdateMeasure(ALL_ROI); } /// /// Sets the variable mTransition to the provided value and /// triggers an update for the measure results /// public void setTransition(string mode) { mTransition = mode; UpdateExecute(ALL_ROI); } /// /// Sets the position of edges to select to the provided value and /// triggers an update od the measure results. /// public void setPosition(string mode) { mPosition = mode; UpdateExecute(ALL_ROI); } /// /// Sets the length of the displayed edges to the provided value /// and triggers an update of the measure results. /// public void setDispEdgeLength(int val) { mDispEdgeLength = val; UpdateXLD(); } /// /// Sets the width of the displayed ROI to the provided value /// and triggers an update for the measure results /// public void setFlagDispROIWidth(bool mode) { mDispROIWidth = mode; UpdateXLD(); } /********************************************************/ /* determine list of result coordinates to be displayed */ /********************************************************/ /// /// Sets a flag to determine if the edge positions of /// measure results are added and displayed on the /// measure result table /// public void showPosition(bool mode) { mDispPosition = mode; } /// /// Sets a flag to determine if the intra distance for /// measure edge pairs are added and displayed on the /// measure result table /// public void showPairWidth(bool mode) { mDispPairWidth = mode; } /// /// Sets a flag to determine if the edge amplitude of /// measure results are added and displayed on the /// measure result table /// public void showAmplitude(bool mode) { mDispAmplitude = mode; } /// /// Sets a flag to determine if the edge distance of /// measure results are added and displayed on the /// measure result table /// public void showDistance(bool mode) { mDispDistance = mode; } /// /// Sets the unit for world coordinate transformation to /// the provided value and triggers an update of the /// measure results /// public void setUnit(string val) { mUnit = val; UpdateExecute(ALL_ROI); } /// /// Sets the variable mTransWorldCoord to the provided /// value and triggers an update for the measure results /// public void setTransWorldCoord(bool mode) { mTransWorldCoord = mode; UpdateExecute(ALL_ROI); } /// /// Load an HALCON image from the file filename and /// delete the list of measure handles created for the /// previous image setup /// /// Location of image file /// Flag depicting success of the load process public bool setImage(string filename) { string tmp; RemoveAllMeasureObjects(); exceptionText = ""; try { mImage = new HImage(filename); mImage.GetImagePointer1(out tmp, out mWidth, out mHeight); } catch (HOperatorException e) { mImage = null; exceptionText = e.Message; NotifyMeasureObserver(MeasureAssistant.ERR_READING_FILE); return false; } return true; } /// /// Sets the variable mImage to the HImage provided /// /// HALCON image instance public void setImage(HImage img) { string tmp; RemoveAllMeasureObjects(); mImage = img; if (mImage != null) mImage.GetImagePointer1(out tmp, out mWidth, out mHeight); } /// /// Returns the image currently used for measurement, described /// by mImage /// public HImage getImage() { return mImage; } /// Load camera calibration data from file /// Location of *.cal file public void LoadCamParFile(string file) { exceptionText = ""; try { mCamParameter = null; mCamParameter = HMisc.ReadCamPar(file); } catch (HOperatorException e) { mIsCalibValid = false; exceptionText = e.Message; throw (e); } if (mCamParameter == null || !(mCamParameter.Length > 0) || mCamPose == null || !(mCamPose.Length > 0)) mIsCalibValid = false; else mIsCalibValid = true; if (mIsCalibValid) UpdateExecute(ALL_ROI); } /// Load camera pose data from file /// Location of *.dat file public void LoadCamPoseFile(string file) { exceptionText = ""; try { HOperatorSet.ReadPose(new HTuple(file), out mCamPose); } catch (HOperatorException e) { mIsCalibValid = false; exceptionText = e.Message; throw (e); } if (mCamParameter == null || !(mCamParameter.Length > 0) || mCamPose == null || !(mCamPose.Length > 0)) mIsCalibValid = false; else mIsCalibValid = true; if (mIsCalibValid) UpdateExecute(ALL_ROI); } /// /// Create a measure object for the new instance of an interactive /// ROI at index mActRoiIdx /// public void AddMeasureObject() { mActRoiIdx = roiController.getActiveROIIdx(); if (mActRoiIdx != -1) mMeasureList.Add(CreateMeasure((ROI)mROIList[mActRoiIdx], this)); NotifyMeasureObserver(EVENT_UPDATE_MEASUREMENT); } /// /// Update measure object for the selected interactive ROI /// at index or update measure handles for the /// entire set of interactive ROIs /// public void UpdateMeasure(int index) { if (index == -1) { for (int i =0; i < mMeasureList.Count; i++) ((Measurement)mMeasureList[i]).UpdateROI(); } else { ((Measurement)mMeasureList[index]).UpdateROI(); } NotifyMeasureObserver(EVENT_UPDATE_MEASUREMENT); } /// /// Recreate the entire measure object list, if the /// measure edge type changes from edge pose to /// edge pairs or vice versa /// public void UpdateMeasure() { RemoveAllMeasureObjects(); for (int i =0; i < mROIList.Count; i++) { ROI roi = (ROI)mROIList[i]; mMeasureList.Add(CreateMeasure((ROI)mROIList[i], this)); } NotifyMeasureObserver(EVENT_UPDATE_MEASUREMENT); } /// /// Update measure results for a selected measure object instance /// at index or the entire set of measure handles. /// public void UpdateExecute(int index) { if (index == -1) { for (int i =0; i < mMeasureList.Count; i++) ((Measurement)mMeasureList[i]).UpdateResults(); } else { ((Measurement)mMeasureList[index]).UpdateResults(); } NotifyMeasureObserver(EVENT_UPDATE_MEASUREMENT); } /// /// Update display objects of the measure results /// for the entire set of measure handles /// public void UpdateXLD() { for (int i =0; i < mMeasureList.Count; i++) ((Measurement)mMeasureList[i]).UpdateXLD(); NotifyMeasureObserver(EVENT_UPDATE_RESULT_XLD); } /// /// Clear the entire list of measure handles and /// releases the resources used /// public void RemoveAllMeasureObjects() { int count = mMeasureList.Count; for (int i=0; i < count; i++) RemoveMeasureObjectIdx(0); NotifyMeasureObserver(EVENT_UPDATE_REMOVE); } /// /// Clear the measure object corresponding to the deleted /// interactive ROI and release the resources used /// public void RemoveMeasureObjectActIdx() { int DelIdx = roiController.getDelROIIdx(); RemoveMeasureObjectIdx(DelIdx); NotifyMeasureObserver(EVENT_UPDATE_REMOVE); } /// /// Clear the measure object at the index DelIdx from /// the measure object list and release the resources used /// private void RemoveMeasureObjectIdx(int DelIdx) { Measurement m = (Measurement)mMeasureList[DelIdx]; mMeasureList.RemoveAt(DelIdx); m.ClearMeasurement(); mActRoiIdx = -1; } /// /// Factory method to create measure objects /// /// Interactive ROI /// /// Reference to measure controller class /// /// New measure object public static Measurement CreateMeasure(ROI roi, MeasureAssistant parent) { if (parent.mSelPair) return new MeasurementPair(roi, parent); else return new MeasurementEdge(roi, parent); } /// /// Composes set of HALCON iconic objects to display /// measure edge results /// /// Detected measure edges public HXLDCont getMeasureResults() { HXLDCont val; HXLDCont obj = new HXLDCont(); obj.GenEmptyObj(); for (int i=0; i < mMeasureList.Count; i++) { val = ((Measurement)mMeasureList[i]).getMeasureResults(); if (val.IsInitialized()) obj = obj.ConcatObj(val); } return obj; } /// /// Composes set of HALCON iconic objects to display /// dimension of measure object /// /// Surrounding contour of measure object public HObject getMeasureRegions() { HObject val; HObject obj = new HObject(); obj.GenEmptyObj(); for (int i=0; i < mMeasureList.Count; i++) { val = ((Measurement)mMeasureList[i]).getMeasureRegion(); if (val.IsInitialized()) obj = obj.ConcatObj(val); } return obj; } /// Returns number of measure objects /// Length of mMeasureList public int getMeasureListCount() { return mMeasureList.Count; } /// Change index for selected interactive ROI public void ClickedActiveROI() { mActRoiIdx = roiController.getActiveROIIdx(); } /// /// Compose set of measure result data to display in the result table /// /// Composition of measure result information public ArrayList getMeasureTableData() { MeasureResult resultData; ArrayList table = new ArrayList(10); if (mMeasureList.Count == 0 || mActRoiIdx == -1) return table; resultData = ((Measurement)mMeasureList[mActRoiIdx]).getMeasureResultData(); if (mSelPair) { if (mDispPosition) { table.Add(((PairResult)resultData).rowEdgeFirst); table.Add(((PairResult)resultData).colEdgeFirst); table.Add(((PairResult)resultData).rowEdgeSecond); table.Add(((PairResult)resultData).colEdgeSecond); } if (mDispAmplitude) { table.Add(((PairResult)resultData).amplitudeFirst); table.Add(((PairResult)resultData).amplitudeSecond); } if (mDispDistance) table.Add(((PairResult)resultData).interDistance); if (mDispPairWidth) table.Add(((PairResult)resultData).intraDistance); } else { if (mDispPosition) { table.Add(((EdgeResult)resultData).rowEdge); table.Add(((EdgeResult)resultData).colEdge); } if (mDispAmplitude) table.Add(((EdgeResult)resultData).amplitude); if (mDispDistance) table.Add(((EdgeResult)resultData).distance); } return table; } /// /// Compose the set of measure result types to be displayed /// in the result table. The types are determined by the user, /// who can check the corresponding flags in the GUI frontend /// /// Composition of measure result types public ArrayList getMeasureResultComposition() { ArrayList composition = new ArrayList(5); if (mSelPair) { if (mDispPosition) { composition.Add("Row 1st"); composition.Add("Col 1st"); composition.Add("Row 2nd"); composition.Add("Col 2nd"); } if (mDispAmplitude) { composition.Add("Amplitude 1st"); composition.Add("Amplitude 2nd"); } if (mDispDistance) composition.Add("Distance"); if (mDispPairWidth) composition.Add("Width"); } else { if (mDispPosition) { composition.Add("Row"); composition.Add("Column"); } if (mDispAmplitude) composition.Add("Amplitude"); if (mDispDistance) composition.Add("Distance"); } return composition; } /// /// Determine the gray value projection for the measure object /// corresponding to the interactive ROI currently selected. /// If no ROI is selected then return a null-object. /// /// Gray value profile public double[] getMeasureProjection() { if (mActRoiIdx == -1) return null; else return ((Measurement)mMeasureList[mActRoiIdx]).getGrayValueProj(); } }//end of class }//end of namespace