// Creates a job for computing the percuptual hash for a certain image source by means of a defined technique public static Job <HashData> createJobComputeHash(ImageSource _src, Technique _technique, Job <HashData> .delegate_job_done _jobDoneFunc, bool _autoStart = true) { // Local variables Job <HashData> job = null; // Check parameter if (_src == null || _technique == null) { return(null); } // Create job job = new Job <HashData>((JobParameter <HashData> _params) => { // Calculate hash return(_technique.computeHash(_src)); }, (JobParameter <HashData> _params) => { // Call user function if (_jobDoneFunc != null) { _jobDoneFunc(_params); } }); // Auto start job? if (_autoStart == true) { // Enqueue job Job <HashData> .enqueue(job, null); } return(job); }
// Dumps a compairison pair for the technique "DCT" to disk public static bool dumpDCTStepsToDiskFor(UnfoldedBindingComparisonPair _pair) { // Local variables Technique t = Technique.createTechniqueDCT(); string[] pathesSource0 = new string[DCT_PATH_COUNT]; string[] pathesSource1 = new string[DCT_PATH_COUNT]; // Create pathes pathesSource0[0] = TARGET_FOLDER + string.Format(DCT_PATH_MEANFILTER, 0); pathesSource0[1] = TARGET_FOLDER + string.Format(DCT_PATH_RESIZED, 0); pathesSource0[2] = TARGET_FOLDER + string.Format(DCT_PATH_DCTMATRIX, 0); pathesSource0[3] = TARGET_FOLDER + string.Format(DCT_PATH_DCTIMAGE, 0); pathesSource0[4] = TARGET_FOLDER + string.Format(DCT_PATH_DCTIMAGE_SUBSEC, 0); pathesSource0[5] = TARGET_FOLDER + string.Format(DCT_PATH_MEDIAN, 0); pathesSource1[0] = TARGET_FOLDER + string.Format(DCT_PATH_MEANFILTER, 1); pathesSource1[1] = TARGET_FOLDER + string.Format(DCT_PATH_RESIZED, 1); pathesSource1[2] = TARGET_FOLDER + string.Format(DCT_PATH_DCTMATRIX, 1); pathesSource1[3] = TARGET_FOLDER + string.Format(DCT_PATH_DCTIMAGE, 1); pathesSource1[4] = TARGET_FOLDER + string.Format(DCT_PATH_DCTIMAGE_SUBSEC, 1); pathesSource1[5] = TARGET_FOLDER + string.Format(DCT_PATH_MEDIAN, 1); // First source var j0 = new Job <bool?>((JobParameter <bool?> _params) => { // Dump to disk return(t.dumpIntermediateResultsToDisk(_pair.Source0, pathesSource0)); }, (JobParameter <bool?> _params) => { if (_params.Error != null) { MessageBox.Show(_params.Error.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); } } ); // Second source var j1 = new Job <bool?>((JobParameter <bool?> _params) => { // Dump to disk return(t.dumpIntermediateResultsToDisk(_pair.Source1, pathesSource1)); }, (JobParameter <bool?> _params) => { if (_params.Error != null) { MessageBox.Show(_params.Error.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); } } ); // Wait for jobs j0.waitForDone(); j1.waitForDone(); return(j0.Result.Value && j1.Result.Value); }
// Dumps a compairison pair for the technique "Wavelet" to disk public static bool dumpWaveletStepsToDiskFor(UnfoldedBindingComparisonPair _pair) { // Local variables Technique t = Technique.createTechniqueWavelet(); string[] pathesSource0 = new string[WAVELET_PATH_COUNT]; string[] pathesSource1 = new string[WAVELET_PATH_COUNT]; // Create pathes pathesSource0[0] = TARGET_FOLDER + string.Format(WAVELET_PATH_BLURRED, 0); pathesSource0[1] = TARGET_FOLDER + string.Format(WAVELET_PATH_KERNEL, 0); pathesSource0[2] = TARGET_FOLDER + string.Format(WAVELET_PATH_EDGES, 0); pathesSource0[3] = TARGET_FOLDER + string.Format(WAVELET_PATH_BLOCKS, 0); pathesSource1[0] = TARGET_FOLDER + string.Format(WAVELET_PATH_BLURRED, 1); pathesSource1[1] = TARGET_FOLDER + string.Format(WAVELET_PATH_KERNEL, 1); pathesSource1[2] = TARGET_FOLDER + string.Format(WAVELET_PATH_EDGES, 1); pathesSource1[3] = TARGET_FOLDER + string.Format(WAVELET_PATH_BLOCKS, 1); // First source var j0 = new Job <bool?>((JobParameter <bool?> _params) => { // Dump to disk return(t.dumpIntermediateResultsToDisk(_pair.Source0, pathesSource0)); }, (JobParameter <bool?> _params) => { if (_params.Error != null) { MessageBox.Show(_params.Error.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); } } ); // Second source var j1 = new Job <bool?>((JobParameter <bool?> _params) => { // Dump to disk return(t.dumpIntermediateResultsToDisk(_pair.Source1, pathesSource1)); }, (JobParameter <bool?> _params) => { if (_params.Error != null) { MessageBox.Show(_params.Error.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); } } ); // Wait for jobs j0.waitForDone(); j1.waitForDone(); return(j0.Result.Value && j1.Result.Value); }
// Constructor public ComparisonPair(ImageSource _source0, ImageSource _source1, Technique _technique) { // Copy parameters m_source0 = _source0; m_source1 = _source1; m_technique = _technique; // Compute comparator's ID m_pairID = 17; m_pairID = m_pairID * 31 + m_source0.FilePath.GetHashCode(); m_pairID = m_pairID * 31 + m_source1.FilePath.GetHashCode(); }
// Dumps a compairison pair for the technique "RADISH" to disk public static bool dumpRadishStepsToDiskFor(UnfoldedBindingComparisonPair _pair) { // Local variables Technique t = Technique.createTechniqueRadish(); string[] pathesSource0 = new string[RADISH_PATH_COUNT]; string[] pathesSource1 = new string[RADISH_PATH_COUNT]; // Create pathes pathesSource0[0] = TARGET_FOLDER + string.Format(RADISH_PATH_GRAYSCALE, 0); pathesSource0[1] = TARGET_FOLDER + string.Format(RADISH_PATH_BLURRED, 0); pathesSource0[2] = TARGET_FOLDER + string.Format(RADISH_PATH_RADONMAP, 0); pathesSource0[3] = TARGET_FOLDER + string.Format(RADISH_PATH_FEATUREVECTOR, 0); pathesSource0[4] = TARGET_FOLDER + string.Format(RADISH_PATH_DCT, 0); pathesSource1[0] = TARGET_FOLDER + string.Format(RADISH_PATH_GRAYSCALE, 1); pathesSource1[1] = TARGET_FOLDER + string.Format(RADISH_PATH_BLURRED, 1); pathesSource1[2] = TARGET_FOLDER + string.Format(RADISH_PATH_RADONMAP, 1); pathesSource1[3] = TARGET_FOLDER + string.Format(RADISH_PATH_FEATUREVECTOR, 1); pathesSource1[4] = TARGET_FOLDER + string.Format(RADISH_PATH_DCT, 1); // First source var j0 = new Job <bool?>((JobParameter <bool?> _params) => { // Dump to disk return(t.dumpIntermediateResultsToDisk(_pair.Source0, pathesSource0)); }, (JobParameter <bool?> _params) => {} ); // Second source var j1 = new Job <bool?>((JobParameter <bool?> _params) => { // Dump to disk return(t.dumpIntermediateResultsToDisk(_pair.Source1, pathesSource1)); }, (JobParameter <bool?> _params) => {} ); // Wait for jobs j0.waitForDone(); j1.waitForDone(); return(j0.Result.Value && j1.Result.Value); }
// Creates a job for comparing two computed perceptual hashes by means of a defined technique public static Job <ComparativeData> createJobCompareHashData(ImageSource _src0, ImageSource _src1, Technique _technique, bool _autoStart = true) { return(createJobCompareHashData(_src0, _src1, _technique, _autoStart)); }
// Creates a job for computing the percuptual hash for a certain image source by means of a defined technique public static Job <HashData> createJobComputeHash(ImageSource _src, Technique _technique, bool _autoStart = true) { return(createJobComputeHash(_src, _technique, null, _autoStart)); }
// Create the default technique instance for the algorithm: BMB public static Technique <BMBHash, double> createTechniqueBMB() { // Local variables Technique <BMBHash, double> t = null; // Create technique t = new Technique <BMBHash, double>(TechniqueID.BMB, (Technique _t, ImageSource _image, string[] _dumpToDiskPathes) => { // Local variables BMBHash hash = new BMBHash(); IntPtr hashUnmanaged = IntPtr.Zero; HashComputationTimings timings = new HashComputationTimings(); HashData <BMBHash> result = null; int attMethod = 1; // Extract attributes if (_t.isAttributeAvailable(Technique.ATT_BMB_METHOD) == true) { _t.getAttribute <int>(Technique.ATT_BMB_METHOD, out attMethod); } // Dump to disk? if (_dumpToDiskPathes != null && _dumpToDiskPathes.Length == DumpTechniqueStepsToDisk.BMB_PATH_COUNT) { if (PHash.dumpBMBHashToDisk(_image.FilePath, attMethod, _dumpToDiskPathes[0], _dumpToDiskPathes[1], _dumpToDiskPathes[2]) != 0) { return(null); } return(new HashData <BMBHash>(null)); } else { // Comnpute hash if (PHash.computeBMBHash(_image.FilePath, attMethod, out hashUnmanaged, timings) == -1) { return(null); } // Convert unmanaged to managed Utility.convertUnmanagedPtrToSimpleStructure <BMBHash>(hashUnmanaged, ref hash, false); // Store result result = new HashData <BMBHash>(hash, (BMBHash _data) => { return(Utility.toHexString(_data.m_data, _data.m_dataLength)); }, new HashDataTimings(timings.m_imageLoadingTimeMS, timings.m_hashComputationTimeMS)); return(result); } }, (Technique _t, HashData <BMBHash> _h0, HashData <BMBHash> _h1) => { // Local variables double dis = 0; decimal threshold = 90m; bool isSame = false; ComparativeData <double> result = null; // Extract attributes if (_t.isAttributeAvailable(Technique.ATT_GENERAL_THRESHOLD) == true) { _t.getAttribute <decimal>(Technique.ATT_GENERAL_THRESHOLD, out threshold); } // Compute distance dis = PHash.computeHammingDistance(_h0.Data.m_data, _h0.Data.m_dataLength, _h1.Data.m_data, _h1.Data.m_dataLength); // Is accepted? isSame = (1.0 - dis) >= Convert.ToSingle(threshold) / 100.0; // Store result result = new ComparativeData <double>(dis, isSame, (double _d) => { return("Match rate: " + (1.0 - _d).ToString("#0.0000")); }, (double _d) => { return(1.0 - _d); }); return(result); } ); return(t); }
// Create the default technique instance for the algorithm: wavelet public static Technique <WaveletHash, double> createTechniqueWavelet() { // Local variables Technique <WaveletHash, double> t = null; // Create technique t = new Technique <WaveletHash, double>(TechniqueID.WAVELET, (Technique _t, ImageSource _image, string[] _dumpToDiskPathes) => { // Local variables int len = 0; IntPtr hash; WaveletHash data = new WaveletHash(); HashData <WaveletHash> result = null; HashComputationTimings timings = new HashComputationTimings(); decimal attAlpha = 2m; decimal attLevel = 1m; // Extract attributes if (_t.isAttributeAvailable(Technique.ATT_WAVELET_ALPHA) == true) { _t.getAttribute <decimal>(Technique.ATT_WAVELET_ALPHA, out attAlpha); } if (_t.isAttributeAvailable(Technique.ATT_WAVELET_LEVEL) == true) { _t.getAttribute <decimal>(Technique.ATT_WAVELET_LEVEL, out attLevel); } // Dump to disk? if (_dumpToDiskPathes != null && _dumpToDiskPathes.Length == DumpTechniqueStepsToDisk.WAVELET_PATH_COUNT) { if (PHash.dumpWaveletHashToDisk(_image.FilePath, Convert.ToSingle(attAlpha), Convert.ToSingle(attLevel), _dumpToDiskPathes[0], _dumpToDiskPathes[1], _dumpToDiskPathes[2], _dumpToDiskPathes[3]) != 0) { return(null); } return(new HashData <WaveletHash>(null)); } else { // Compute hast hash = PHash.computeWaveletHash(_image.FilePath, ref len, timings, Convert.ToSingle(attAlpha), Convert.ToSingle(attLevel)); // Store result data.m_data = hash; data.m_dataLength = len; result = new HashData <WaveletHash>(data, (WaveletHash _data) => { return(Utility.toHexString(_data.m_data, _data.m_dataLength)); }, new HashDataTimings(timings.m_imageLoadingTimeMS, timings.m_hashComputationTimeMS)); return(result); } }, (Technique _t, HashData <WaveletHash> _h0, HashData <WaveletHash> _h1) => { // Local variables double dis = 0; decimal threshold = 90m; bool isSame = false; ComparativeData <double> result = null; // Extract attributes if (_t.isAttributeAvailable(Technique.ATT_GENERAL_THRESHOLD) == true) { _t.getAttribute <decimal>(Technique.ATT_GENERAL_THRESHOLD, out threshold); } // Compute distance dis = PHash.computeHammingDistance(_h0.Data.m_data, _h0.Data.m_dataLength, _h1.Data.m_data, _h1.Data.m_dataLength); // Is accepted? isSame = (1.0 - dis) >= Convert.ToSingle(threshold) / 100.0; // Store result result = new ComparativeData <double>(dis, isSame, (double _d) => { return("Match rate: " + (1.0 - _d).ToString("#0.0000")); }, (double _d) => { return(1.0 - _d); }); return(result); } ); return(t); }
// Create the default technique instance for the algorithm: DCT public static Technique <UInt64, double> createTechniqueDCT() { // Local variables Technique <UInt64, double> t = null; // Create technique t = new Technique <UInt64, double>(TechniqueID.DCT, (Technique _t, ImageSource _image, string[] _dumpToDiskPathes) => { // Local variables UInt64 hash = 0; HashData <UInt64> result = null; HashComputationTimings timings = new HashComputationTimings(); // Dump to disk? if (_dumpToDiskPathes != null && _dumpToDiskPathes.Length == DumpTechniqueStepsToDisk.DCT_PATH_COUNT) { if (PHash.dumpDCTHashToDisk(_image.FilePath, _dumpToDiskPathes[0], _dumpToDiskPathes[1], _dumpToDiskPathes[2], _dumpToDiskPathes[3], _dumpToDiskPathes[4], _dumpToDiskPathes[5]) != 0) { return(null); } return(new HashData <ulong>(0)); } else { // Compute hast PHash.computeDCTHash(_image.FilePath, ref hash, timings); // Store result result = new HashData <UInt64>(hash, null, new HashDataTimings(timings.m_imageLoadingTimeMS, timings.m_hashComputationTimeMS)); return(result); } }, (Technique _t, HashData <UInt64> _h0, HashData <UInt64> _h1) => { // Local variables double dis = 0; bool isSame = false; decimal threshold = 90m; ComparativeData <double> result = null; // Extract attributes if (_t.isAttributeAvailable(Technique.ATT_GENERAL_THRESHOLD) == true) { _t.getAttribute <decimal>(Technique.ATT_GENERAL_THRESHOLD, out threshold); } // Compute distance and normalize it dis = PHash.computeHammingDistance(_h0.Data, _h1.Data); dis /= 64; // Is accepted? isSame = (1.0 - dis) >= Convert.ToSingle(threshold) / 100.0; // Store result result = new ComparativeData <double>(dis, isSame, (double _d) => { return("Match rate: " + (1.0 - _d).ToString("#0.0000")); }, (double _d) => { return(1.0f - _d); }); return(result); } ); return(t); }
// Create the default technique instance for the algorithm: RADISH public static Technique <Digest, RadishComparativeData> createTechniqueRadish() { // Local variables Technique <Digest, RadishComparativeData> t = null; // Create technique t = new Technique <Digest, RadishComparativeData>(TechniqueID.RADISH, (Technique _t, ImageSource _image, string[] _dumpToDiskPathes) => { // Local variables Digest hash = new Digest(); HashComputationTimings timings = new HashComputationTimings(); IntPtr hashUnmanaged = IntPtr.Zero; HashData <Digest> result = null; decimal attGamma = 1.0m; decimal attSigma = 1.0m; decimal attAngles = 180m; // Extract attributes if (_t.isAttributeAvailable(Technique.ATT_RADISH_GAMMA) == true) { _t.getAttribute <decimal>(Technique.ATT_RADISH_GAMMA, out attGamma); } if (_t.isAttributeAvailable(Technique.ATT_RADISH_SIGMA) == true) { _t.getAttribute <decimal>(Technique.ATT_RADISH_SIGMA, out attSigma); } if (_t.isAttributeAvailable(Technique.ATT_RADISH_NUM_ANGLES) == true) { _t.getAttribute <decimal>(Technique.ATT_RADISH_NUM_ANGLES, out attAngles); } // Dump to disk? if (_dumpToDiskPathes != null && _dumpToDiskPathes.Length == DumpTechniqueStepsToDisk.RADISH_PATH_COUNT) { if (PHash.dumpRadialHashToDisk(_image.FilePath, Convert.ToSingle(attSigma), Convert.ToSingle(attGamma), (int)(Convert.ToSingle(attAngles)), _dumpToDiskPathes[0], _dumpToDiskPathes[1], _dumpToDiskPathes[2], _dumpToDiskPathes[3], _dumpToDiskPathes[4]) != 0) { return(null); } return(new HashData <Digest>(null, null)); } else { // Convert managed to unmanaged hashUnmanaged = Utility.convertSimpleStructureToUnmanagedPtr <Digest>(hash); // Comnpute hash PHash.computeRadialHash(_image.FilePath, Convert.ToSingle(attSigma), Convert.ToSingle(attGamma), hashUnmanaged, timings, (int)(Convert.ToSingle(attAngles))); // Convert unmanaged to managed Utility.convertUnmanagedPtrToSimpleStructure <Digest>(hashUnmanaged, ref hash); // Store result result = new HashData <Digest>(hash, (Digest _data) => { return(Utility.toHexString(_data.m_coeffs, _data.m_size)); }, new HashDataTimings(timings.m_imageLoadingTimeMS, timings.m_hashComputationTimeMS)); return(result); } }, (Technique _t, HashData <Digest> _h0, HashData <Digest> _h1) => { // Local variables RadishComparativeData result = null; int isSame = 0; double peak = 0.0; decimal threshold = 90m; IntPtr h0 = IntPtr.Zero; IntPtr h1 = IntPtr.Zero; // Extract attributes if (_t.isAttributeAvailable(Technique.ATT_GENERAL_THRESHOLD) == true) { _t.getAttribute <decimal>(Technique.ATT_GENERAL_THRESHOLD, out threshold); } // Compute cross correlation h0 = Utility.convertSimpleStructureToUnmanagedPtr <Digest>(_h0.Data); h1 = Utility.convertSimpleStructureToUnmanagedPtr <Digest>(_h1.Data); isSame = PHash.computeCrossCorrelation(h0, h1, ref peak, Convert.ToSingle(threshold) / 100.0); // Store result result = new RadishComparativeData(); result.m_crossCorrelationPeak = peak; result.m_isDifferent = isSame == 1 ? false : true; return(new ComparativeData <RadishComparativeData>(result, isSame == 1 ? true : false, (RadishComparativeData _data) => { return "Match rate: " + _data.m_crossCorrelationPeak.ToString("#0.0000"); // return "Peak: " + _data.m_crossCorrelationPeak.ToString("#0.0000"); }, (RadishComparativeData _data) => { return _data.m_crossCorrelationPeak; })); } ); return(t); }
// Constructor protected ViewWithTechniqueSelection(TabPage _tabPage, string _nameControlTechniqueSelection) : base(_tabPage) { // Extract technique selection m_controlTechniqueSelection = _tabPage.Controls.Find(_nameControlTechniqueSelection, true)[0] as TechniqueSelection; // Create techniques m_techniqueRadish = Technique.createTechniqueRadish(); m_techniqueDCT = Technique.createTechniqueDCT(); m_techniqueWavelet = Technique.createTechniqueWavelet(); m_techniqueBMB = Technique.createTechniqueBMB(); // Set default values for: general m_techniqueDCT.addAttribute(Technique.ATT_GENERAL_THRESHOLD, m_controlTechniqueSelection.Threshold); m_techniqueRadish.addAttribute(Technique.ATT_GENERAL_THRESHOLD, m_controlTechniqueSelection.Threshold); m_techniqueWavelet.addAttribute(Technique.ATT_GENERAL_THRESHOLD, m_controlTechniqueSelection.Threshold); m_techniqueBMB.addAttribute(Technique.ATT_GENERAL_THRESHOLD, m_controlTechniqueSelection.Threshold); // Set default values for: RADISH m_techniqueRadish.addAttribute(Technique.ATT_RADISH_GAMMA, m_controlTechniqueSelection.RadishGamma); m_techniqueRadish.addAttribute(Technique.ATT_RADISH_SIGMA, m_controlTechniqueSelection.RadishSigma); m_techniqueRadish.addAttribute(Technique.ATT_RADISH_NUM_ANGLES, m_controlTechniqueSelection.RadishNumberOfAngles); // Set default values for: wavelet m_techniqueWavelet.addAttribute(Technique.ATT_WAVELET_ALPHA, m_controlTechniqueSelection.WaveletAlpha); m_techniqueWavelet.addAttribute(Technique.ATT_WAVELET_LEVEL, m_controlTechniqueSelection.WaveletLevel); // Set default values for: BMB m_techniqueBMB.addAttribute(Technique.ATT_BMB_METHOD, m_controlTechniqueSelection.BMBMethod); // Set current technique if (m_controlTechniqueSelection.OperationMode == TechniqueSelection.eMode.SINGLE) { if (m_controlTechniqueSelection.CurrentTechniqueIDs == TechniqueID.RADISH) { m_singleTechnique = m_techniqueRadish; } else if (m_controlTechniqueSelection.CurrentTechniqueIDs == TechniqueID.WAVELET) { m_singleTechnique = m_techniqueWavelet; } else if (m_controlTechniqueSelection.CurrentTechniqueIDs == TechniqueID.DCT) { m_singleTechnique = m_techniqueDCT; } else { m_singleTechnique = m_techniqueBMB; } } else { m_multipleTechniques.Clear(); if ((m_controlTechniqueSelection.CurrentTechniqueIDs & TechniqueID.DCT) == TechniqueID.DCT) { m_multipleTechniques.Add(m_techniqueDCT); } if ((m_controlTechniqueSelection.CurrentTechniqueIDs & TechniqueID.RADISH) == TechniqueID.RADISH) { m_multipleTechniques.Add(m_techniqueRadish); } if ((m_controlTechniqueSelection.CurrentTechniqueIDs & TechniqueID.WAVELET) == TechniqueID.WAVELET) { m_multipleTechniques.Add(m_techniqueWavelet); } if ((m_controlTechniqueSelection.CurrentTechniqueIDs & TechniqueID.BMB) == TechniqueID.BMB) { m_multipleTechniques.Add(m_techniqueBMB); } } // Set attribute events m_controlTechniqueSelection.OnTechniqueIDsChanged += (TechniqueID _id) => { if (m_controlTechniqueSelection.OperationMode == TechniqueSelection.eMode.SINGLE) { if (_id == TechniqueID.RADISH) { m_singleTechnique = m_techniqueRadish; } else if (_id == TechniqueID.WAVELET) { m_singleTechnique = m_techniqueWavelet; } else if (_id == TechniqueID.DCT) { m_singleTechnique = m_techniqueDCT; } else { m_singleTechnique = m_techniqueBMB; } } else { m_multipleTechniques.Clear(); if ((_id & TechniqueID.DCT) == TechniqueID.DCT) { m_multipleTechniques.Add(m_techniqueDCT); } if ((_id & TechniqueID.RADISH) == TechniqueID.RADISH) { m_multipleTechniques.Add(m_techniqueRadish); } if ((_id & TechniqueID.WAVELET) == TechniqueID.WAVELET) { m_multipleTechniques.Add(m_techniqueWavelet); } if ((_id & TechniqueID.BMB) == TechniqueID.BMB) { m_multipleTechniques.Add(m_techniqueBMB); } } }; m_controlTechniqueSelection.OnGeneralThresholdChanged += (decimal _v) => { m_techniqueDCT.addAttribute(Technique.ATT_GENERAL_THRESHOLD, m_controlTechniqueSelection.Threshold); m_techniqueRadish.addAttribute(Technique.ATT_GENERAL_THRESHOLD, m_controlTechniqueSelection.Threshold); m_techniqueWavelet.addAttribute(Technique.ATT_GENERAL_THRESHOLD, m_controlTechniqueSelection.Threshold); m_techniqueBMB.addAttribute(Technique.ATT_GENERAL_THRESHOLD, m_controlTechniqueSelection.Threshold); }; m_controlTechniqueSelection.OnRadishGammaChanged += (decimal _v) => { m_techniqueRadish.addAttribute(Technique.ATT_RADISH_GAMMA, m_controlTechniqueSelection.RadishGamma); }; m_controlTechniqueSelection.OnRadishSigmaChanged += (decimal _v) => { m_techniqueRadish.addAttribute(Technique.ATT_RADISH_SIGMA, m_controlTechniqueSelection.RadishSigma); }; m_controlTechniqueSelection.OnRadishNumberOfAnglesChanged += (decimal _v) => { m_techniqueRadish.addAttribute(Technique.ATT_RADISH_NUM_ANGLES, m_controlTechniqueSelection.RadishNumberOfAngles); }; m_controlTechniqueSelection.OnWaveletAlphaChanged += (decimal _v) => { m_techniqueWavelet.addAttribute(Technique.ATT_WAVELET_ALPHA, m_controlTechniqueSelection.WaveletAlpha); }; m_controlTechniqueSelection.OnWaveletLevelChanged += (decimal _v) => { m_techniqueWavelet.addAttribute(Technique.ATT_WAVELET_LEVEL, m_controlTechniqueSelection.WaveletLevel); }; m_controlTechniqueSelection.OnBMBMethodChanged += (int _v) => { m_techniqueBMB.addAttribute(Technique.ATT_BMB_METHOD, m_controlTechniqueSelection.BMBMethod); }; }