Commit 76bf186b919b7e30b014d2d0798f3ebfff02342e

Authored by jklontz
2 parents 7d36de07 a6cd8369

Merge pull request #48 from biometrics/ltp

Local Ternary Pattern Transform Descriptor
Showing 1 changed file with 118 additions and 0 deletions
openbr/plugins/ltp.cpp 0 → 100644
  1 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2 + * Copyright 2012 The MITRE Corporation *
  3 + * *
  4 + * Licensed under the Apache License, Version 2.0 (the "License"); *
  5 + * you may not use this file except in compliance with the License. *
  6 + * You may obtain a copy of the License at *
  7 + * *
  8 + * http://www.apache.org/licenses/LICENSE-2.0 *
  9 + * *
  10 + * Unless required by applicable law or agreed to in writing, software *
  11 + * distributed under the License is distributed on an "AS IS" BASIS, *
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
  13 + * See the License for the specific language governing permissions and *
  14 + * limitations under the License. *
  15 + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  16 +
  17 +#include <opencv2/imgproc/imgproc.hpp>
  18 +#include <limits>
  19 +#include "openbr_internal.h"
  20 +
  21 +using namespace cv;
  22 +
  23 +namespace br
  24 +{
  25 +
  26 +/*!
  27 + * \ingroup transforms
  28 + * \brief Tan, Xiaoyang, and Bill Triggs. "Enhanced local texture feature sets for face recognition under difficult lighting conditions." Analysis and Modeling of Faces and Gestures. Springer Berlin Heidelberg, 2007. 168-182.
  29 + * \author Brendan Klare \cite bklare
  30 + * \author Josh Klontz \cite jklontz
  31 + */
  32 +class LTPTransform : public UntrainableTransform
  33 +{
  34 + Q_OBJECT
  35 + Q_PROPERTY(int radius READ get_radius WRITE set_radius RESET reset_radius STORED false)
  36 + Q_PROPERTY(float threshold READ get_threshold WRITE set_threshold RESET reset_threshold STORED false)
  37 + BR_PROPERTY(int, radius, 1)
  38 + BR_PROPERTY(float, threshold, 0.1F)
  39 +
  40 + unsigned short lut[8][3];
  41 + uchar null;
  42 +
  43 + void init()
  44 + {
  45 + unsigned short cnt = 0;
  46 + for (int i = 0; i < 8; i++) {
  47 + for (int j = 0; j < 3; j++)
  48 + lut[i][j] = cnt++;
  49 + cnt++; //we skip the 4th number (only three patterns)
  50 + }
  51 + }
  52 +
  53 + void project(const Template &src, Template &dst) const
  54 + {
  55 + Mat m; src.m().convertTo(m, CV_32F); assert(m.isContinuous() && (m.channels() == 1));
  56 +
  57 + Mat n(m.rows, m.cols, CV_16U);
  58 + n = null;
  59 + float thresholdNeg = -1.0 * threshold; //compute once (can move to init)
  60 +
  61 + const float *p = (const float*)m.ptr();
  62 + float diff;
  63 + for (int r=radius; r<m.rows-radius; r++) {
  64 + for (int c=radius; c<m.cols-radius; c++) {
  65 + const float cval = (p[(r+0*radius)*m.cols+c+0*radius]);
  66 +
  67 + diff = p[(r-1*radius)*m.cols+c-1*radius] - cval;
  68 + if (diff > threshold) n.at<unsigned short>(r,c) = lut[0][0];
  69 + else if (diff < thresholdNeg) n.at<unsigned short>(r,c) = lut[0][1];
  70 + else n.at<unsigned short>(r,c) = lut[0][2];
  71 +
  72 + diff = p[(r-1*radius)*m.cols+c+0*radius] - cval;
  73 + if (diff > threshold) n.at<unsigned short>(r,c) += lut[1][0];
  74 + else if (diff < thresholdNeg) n.at<unsigned short>(r,c) += lut[1][1];
  75 + else n.at<unsigned short>(r,c) += lut[1][2];
  76 +
  77 + diff = p[(r-1*radius)*m.cols+c+1*radius] - cval;
  78 + if (diff > threshold) n.at<unsigned short>(r,c) += lut[2][0];
  79 + else if (diff < thresholdNeg) n.at<unsigned short>(r,c) += lut[2][1];
  80 + else n.at<unsigned short>(r,c) += lut[2][2];
  81 +
  82 + diff = p[(r+0*radius)*m.cols+c+1*radius] - cval;
  83 + if (diff > threshold) n.at<unsigned short>(r,c) += lut[3][0];
  84 + else if (diff < thresholdNeg) n.at<unsigned short>(r,c) += lut[3][1];
  85 + else n.at<unsigned short>(r,c) += lut[3][2];
  86 +
  87 + diff = p[(r+1*radius)*m.cols+c+1*radius] - cval;
  88 + if (diff > threshold) n.at<unsigned short>(r,c) += lut[4][0];
  89 + else if (diff < thresholdNeg) n.at<unsigned short>(r,c) += lut[4][1];
  90 + else n.at<unsigned short>(r,c) += lut[4][2];
  91 +
  92 + diff = p[(r+1*radius)*m.cols+c+0*radius] - cval;
  93 + if (diff > threshold) n.at<unsigned short>(r,c) += lut[5][0];
  94 + else if (diff < thresholdNeg) n.at<unsigned short>(r,c) += lut[5][1];
  95 + else n.at<unsigned short>(r,c) += lut[5][2];
  96 +
  97 + diff = p[(r+1*radius)*m.cols+c-1*radius] - cval;
  98 + if (diff > threshold) n.at<unsigned short>(r,c) += lut[6][0];
  99 + else if (diff < thresholdNeg) n.at<unsigned short>(r,c) += lut[6][1];
  100 + else n.at<unsigned short>(r,c) += lut[6][2];
  101 +
  102 + diff = p[(r+0*radius)*m.cols+c-1*radius] - cval;
  103 + if (diff > threshold) n.at<unsigned short>(r,c) += lut[7][0];
  104 + else if (diff < thresholdNeg) n.at<unsigned short>(r,c) += lut[7][1];
  105 + else n.at<unsigned short>(r,c) += lut[7][2];
  106 + }
  107 + }
  108 +
  109 + dst += n;
  110 + }
  111 +};
  112 +
  113 +BR_REGISTER(Transform, LTPTransform)
  114 +
  115 +
  116 +} // namespace br
  117 +
  118 +#include "ltp.moc"
... ...