Commit 56ca9fa09995df1d9b393fcebbc0fcd52aec103b
Merge pull request #353 from biometrics/emd_distance
Emd distance
Showing
1 changed file
with
62 additions
and
0 deletions
openbr/plugins/distance/emd.cpp
0 → 100644
| 1 | +#include <openbr/plugins/openbr_internal.h> | ||
| 2 | +#include <opencv2/imgproc/imgproc.hpp> | ||
| 3 | + | ||
| 4 | +using namespace cv; | ||
| 5 | + | ||
| 6 | +namespace br | ||
| 7 | +{ | ||
| 8 | + | ||
| 9 | +/*! | ||
| 10 | + * \ingroup distances | ||
| 11 | + * \brief Computes Earth Mover's Distance | ||
| 12 | + * \author Scott Klum \cite sklum | ||
| 13 | + * \brief https://www.cs.duke.edu/~tomasi/papers/rubner/rubnerTr98.pdf | ||
| 14 | + */ | ||
| 15 | +class EMDDistance : public UntrainableDistance | ||
| 16 | +{ | ||
| 17 | + Q_OBJECT | ||
| 18 | + | ||
| 19 | + Q_ENUMS(Metric) | ||
| 20 | + Q_PROPERTY(Metric metric READ get_metric WRITE set_metric RESET reset_metric STORED false) | ||
| 21 | + | ||
| 22 | +public: | ||
| 23 | + enum Metric { L1 = CV_DIST_L1, | ||
| 24 | + L2 = CV_DIST_L2, | ||
| 25 | + C = CV_DIST_C }; | ||
| 26 | + | ||
| 27 | +private: | ||
| 28 | + BR_PROPERTY(Metric, metric, L2) | ||
| 29 | + | ||
| 30 | + float compare(const Template &a, const Template &b) const | ||
| 31 | + { | ||
| 32 | + const int dims_a = a.m().rows > 1 ? 3 : 2; | ||
| 33 | + const int dims_b = b.m().rows > 1 ? 3 : 2; | ||
| 34 | + | ||
| 35 | + Mat sig_a(a.m().cols, dims_a, CV_32FC1); | ||
| 36 | + Mat sig_b(b.m().cols, dims_b, CV_32FC1); | ||
| 37 | + | ||
| 38 | + for (int i=0; i<a.m().rows; i++) { | ||
| 39 | + for (int j=0; j<a.m().cols; j++) { | ||
| 40 | + sig_a.at<float>(i*a.m().cols+j,0) = a.m().at<float>(i,j); | ||
| 41 | + sig_a.at<float>(i*a.m().cols+j,1) = j; | ||
| 42 | + if (dims_a == 3) sig_a.at<float>(i*a.m().cols+j,2) = i; | ||
| 43 | + } | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + for (int i=0; i<b.m().rows; i++) { | ||
| 47 | + for (int j=0; j<b.m().cols; j++) { | ||
| 48 | + sig_b.at<float>(i*b.m().cols+j,0) = b.m().at<float>(i,j); | ||
| 49 | + sig_b.at<float>(i*b.m().cols+j,1) = j; | ||
| 50 | + if (dims_b == 3) sig_a.at<float>(i*b.m().cols+j,2) = i; | ||
| 51 | + } | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + return EMD(sig_a,sig_b,metric); | ||
| 55 | + } | ||
| 56 | +}; | ||
| 57 | + | ||
| 58 | +BR_REGISTER(Distance, EMDDistance) | ||
| 59 | + | ||
| 60 | +} // namespace br | ||
| 61 | + | ||
| 62 | +#include "distance/emd.moc" |