From 3048ffa036c16e2f44ede04e92477b05285f19f6 Mon Sep 17 00:00:00 2001 From: Josh Klontz Date: Tue, 2 Apr 2013 15:12:07 -0400 Subject: [PATCH] implemented Hellinger normalization --- openbr/plugins/algorithms.cpp | 2 +- openbr/plugins/normalize.cpp | 47 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/openbr/plugins/algorithms.cpp b/openbr/plugins/algorithms.cpp index 0615792..ab8bc33 100644 --- a/openbr/plugins/algorithms.cpp +++ b/openbr/plugins/algorithms.cpp @@ -42,7 +42,7 @@ class AlgorithmsInitializer : public Initializer Globals->abbreviations.insert("OpenBR", "FaceRecognition"); Globals->abbreviations.insert("GenderEstimation", "GenderClassification"); Globals->abbreviations.insert("AgeEstimation", "AgeRegression"); - Globals->abbreviations.insert("FaceRecognitionHoG", "{PP5Register+Affine(128,128,0.25,0.35)+Cvt(Gray)}+Gradient+Bin(0,360,9,true)+Merge+Integral+RecursiveIntegralSampler(4,2,8,LDA(.95)+Normalize(L1)+Div(3)+ProductQuantization(3,L1,true)[fraction=0.2]):ProductQuantization(true)"); + Globals->abbreviations.insert("FaceRecognitionHoG", "{PP5Register+Affine(128,128,0.25,0.35)+Cvt(Gray)}+Gradient+Bin(0,360,9,true)+Merge+Integral+RecursiveIntegralSampler(4,2,8,Center(Hellinger)+LDA(.95)+Normalize(L1)+Div(3)+ProductQuantization(3,L1,true)[fraction=0.2]):RecursiveProductQuantization"); // Generic Image Processing Globals->abbreviations.insert("SIFT", "Open+KeyPointDetector(SIFT)+KeyPointDescriptor(SIFT):KeyPointMatcher(BruteForce)"); diff --git a/openbr/plugins/normalize.cpp b/openbr/plugins/normalize.cpp index 6e03463..11c3f88 100644 --- a/openbr/plugins/normalize.cpp +++ b/openbr/plugins/normalize.cpp @@ -90,28 +90,31 @@ public: /*!< */ enum Method { Mean, Median, - Range }; + Range, + Hellinger }; private: BR_PROPERTY(Method, method, Mean) Mat a, b; // dst = (src - b) / a - static void _train(Method method, const cv::Mat &m, Mat *ca, Mat *cb, int i) + static void _train(Method method, const cv::Mat &m, const QList &labels, double *ca, double *cb) { double A = 1, B = 0; - if (method == Mean) mean(m.col(i), &A, &B); - else if (method == Median) median(m.col(i), &A, &B); - else if (method == Range) range(m.col(i), &A, &B); - else qFatal("Invalid method."); - ca->at(0, i) = A; - cb->at(0, i) = B; + if (method == Mean) mean(m, &A, &B); + else if (method == Median) median(m, &A, &B); + else if (method == Range) range(m, &A, &B); + else if (method == Hellinger) hellinger(m, labels, &A, &B); + else qFatal("Invalid method."); + *ca = A; + *cb = B; } void train(const TemplateList &data) { Mat m; OpenCVUtils::toMat(data.data()).convertTo(m, CV_64F); + const QList labels = data.labels(); const int dims = m.cols; vector mv, av, bv; @@ -125,8 +128,8 @@ private: const bool parallel = (data.size() > 1000) && Globals->parallelism; for (size_t c = 0; c < mv.size(); c++) { for (int i=0; i(0, i), &bv[c].at(0, i))); + else _train (method, mv[c].col(i), labels, &av[c].at(0, i), &bv[c].at(0, i)); av[c] = av[c].reshape(1, data.first().m().rows); bv[c] = bv[c].reshape(1, data.first().m().rows); } @@ -181,6 +184,30 @@ private: *a = max - min; *b = min; } + + static void hellinger(const Mat &src, const QList &labels, double *a, double *b) + { + const QList vals = OpenCVUtils::matrixToVector(src); + if (vals.size() != labels.size()) + qFatal("Logic error."); + + QVector genuineScores; genuineScores.reserve(vals.size()); + QVector impostorScores; impostorScores.reserve(vals.size()*vals.size()/2); + for (int i=0; i