Пример #1
0
        // 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);
        }
Пример #2
0
        // 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);
        }
Пример #3
0
        // 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);
        }
Пример #4
0
        // 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();
        }
Пример #5
0
        // 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);
        }
Пример #6
0
 // 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));
 }
Пример #7
0
 // 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));
 }
Пример #8
0
        // 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);
        }
Пример #9
0
        // 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);
        }
Пример #10
0
        // 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);
        }
Пример #11
0
        // 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);
        }
Пример #12
0
        // 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); };
        }