Commit b34029cc89b22994e6464b16479488ee7a775525

Authored by Jordan Cheney
1 parent f645840e

Incremental progress for plugins reorg

Showing 113 changed files with 5111 additions and 4674 deletions

Too many changes.

To preserve performance only 100 of 113 files are displayed.

openbr/plugins/ebif.cpp renamed to openbr/plugins/classification/ebif.cpp
1 1 #include <opencv2/imgproc/imgproc.hpp>
2 2  
3   -#include "openbr_internal.h"
4   -#include "openbr/core/common.h"
5   -#include "openbr/core/opencvutils.h"
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +#include <openbr/core/common.h>
  5 +#include <openbr/core/opencvutils.h>
6 6  
7 7 using namespace cv;
8 8  
... ...
openbr/plugins/cluster/collectnn.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Collect nearest neighbors and append them to metadata.
  9 + * \author Charles Otto \cite caotto
  10 + */
  11 +class CollectNNTransform : public UntrainableMetaTransform
  12 +{
  13 + Q_OBJECT
  14 +
  15 + Q_PROPERTY(int keep READ get_keep WRITE set_keep RESET reset_keep STORED false)
  16 + BR_PROPERTY(int, keep, 20)
  17 +
  18 + void project(const Template &src, Template &dst) const
  19 + {
  20 + dst.file = src.file;
  21 + dst.clear();
  22 + dst.m() = cv::Mat();
  23 + Neighbors neighbors;
  24 + for (int i=0; i < src.m().cols;i++) {
  25 + // skip self compares
  26 + if (i == src.file.get<int>("FrameNumber"))
  27 + continue;
  28 + neighbors.append(Neighbor(i, src.m().at<float>(0,i)));
  29 + }
  30 + int actuallyKeep = std::min(keep, neighbors.size());
  31 + std::partial_sort(neighbors.begin(), neighbors.begin()+actuallyKeep, neighbors.end(), compareNeighbors);
  32 +
  33 + Neighbors selected = neighbors.mid(0, actuallyKeep);
  34 + dst.file.set("neighbors", QVariant::fromValue(selected));
  35 + }
  36 +};
  37 +
  38 +BR_REGISTER(Transform, CollectNNTransform)
  39 +
  40 +} // namespace br
  41 +
  42 +#include "collectnn.moc"
... ...
openbr/plugins/cluster/kmeans.cpp 0 → 100644
  1 +#include <opencv2/flann/flann.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +#include <openbr/core/opencvutils.h>
  5 +
  6 +using namespace cv;
  7 +
  8 +namespace br
  9 +{
  10 +
  11 +/*!
  12 + * \ingroup transforms
  13 + * \brief Wraps OpenCV kmeans and flann.
  14 + * \author Josh Klontz \cite jklontz
  15 + */
  16 +class KMeansTransform : public Transform
  17 +{
  18 + Q_OBJECT
  19 + Q_PROPERTY(int kTrain READ get_kTrain WRITE set_kTrain RESET reset_kTrain STORED false)
  20 + Q_PROPERTY(int kSearch READ get_kSearch WRITE set_kSearch RESET reset_kSearch STORED false)
  21 + BR_PROPERTY(int, kTrain, 256)
  22 + BR_PROPERTY(int, kSearch, 1)
  23 +
  24 + Mat centers;
  25 + mutable QScopedPointer<flann::Index> index;
  26 + mutable QMutex mutex;
  27 +
  28 + void reindex()
  29 + {
  30 + index.reset(new flann::Index(centers, flann::LinearIndexParams()));
  31 + }
  32 +
  33 + void train(const TemplateList &data)
  34 + {
  35 + Mat bestLabels;
  36 + const double compactness = kmeans(OpenCVUtils::toMatByRow(data.data()), kTrain, bestLabels, TermCriteria(TermCriteria::MAX_ITER, 10, 0), 3, KMEANS_PP_CENTERS, centers);
  37 + qDebug("KMeans compactness = %f", compactness);
  38 + reindex();
  39 + }
  40 +
  41 + void project(const Template &src, Template &dst) const
  42 + {
  43 + QMutexLocker locker(&mutex);
  44 + Mat dists, indicies;
  45 + index->knnSearch(src, indicies, dists, kSearch);
  46 + dst = indicies.reshape(1, 1);
  47 + }
  48 +
  49 + void load(QDataStream &stream)
  50 + {
  51 + stream >> centers;
  52 + reindex();
  53 + }
  54 +
  55 + void store(QDataStream &stream) const
  56 + {
  57 + stream << centers;
  58 + }
  59 +};
  60 +
  61 +BR_REGISTER(Transform, KMeansTransform)
  62 +
  63 +} // namespace br
  64 +
  65 +#include "kmeans.moc"
... ...
openbr/plugins/cluster.cpp renamed to openbr/plugins/cluster/knn.cpp
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/flann/flann.hpp>
18   -
19   -#include "openbr_internal.h"
20   -#include "openbr/core/common.h"
21   -#include "openbr/core/opencvutils.h"
22   -#include <fstream>
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/common.h>
23 3  
24 4 using namespace cv;
25 5  
... ... @@ -28,58 +8,6 @@ namespace br
28 8  
29 9 /*!
30 10 * \ingroup transforms
31   - * \brief Wraps OpenCV kmeans and flann.
32   - * \author Josh Klontz \cite jklontz
33   - */
34   -class KMeansTransform : public Transform
35   -{
36   - Q_OBJECT
37   - Q_PROPERTY(int kTrain READ get_kTrain WRITE set_kTrain RESET reset_kTrain STORED false)
38   - Q_PROPERTY(int kSearch READ get_kSearch WRITE set_kSearch RESET reset_kSearch STORED false)
39   - BR_PROPERTY(int, kTrain, 256)
40   - BR_PROPERTY(int, kSearch, 1)
41   -
42   - Mat centers;
43   - mutable QScopedPointer<flann::Index> index;
44   - mutable QMutex mutex;
45   -
46   - void reindex()
47   - {
48   - index.reset(new flann::Index(centers, flann::LinearIndexParams()));
49   - }
50   -
51   - void train(const TemplateList &data)
52   - {
53   - Mat bestLabels;
54   - const double compactness = kmeans(OpenCVUtils::toMatByRow(data.data()), kTrain, bestLabels, TermCriteria(TermCriteria::MAX_ITER, 10, 0), 3, KMEANS_PP_CENTERS, centers);
55   - qDebug("KMeans compactness = %f", compactness);
56   - reindex();
57   - }
58   -
59   - void project(const Template &src, Template &dst) const
60   - {
61   - QMutexLocker locker(&mutex);
62   - Mat dists, indicies;
63   - index->knnSearch(src, indicies, dists, kSearch);
64   - dst = indicies.reshape(1, 1);
65   - }
66   -
67   - void load(QDataStream &stream)
68   - {
69   - stream >> centers;
70   - reindex();
71   - }
72   -
73   - void store(QDataStream &stream) const
74   - {
75   - stream << centers;
76   - }
77   -};
78   -
79   -BR_REGISTER(Transform, KMeansTransform)
80   -
81   -/*!
82   - * \ingroup transforms
83 11 * \brief K nearest neighbors classifier.
84 12 * \author Josh Klontz \cite jklontz
85 13 */
... ... @@ -151,148 +79,6 @@ class KNNTransform : public Transform
151 79  
152 80 BR_REGISTER(Transform, KNNTransform)
153 81  
154   -/*!
155   - * \ingroup transforms
156   - * \brief Chooses k random points to be centroids.
157   - * \author Austin Blanton \cite imaus10
158   - * \see KMeansTransform
159   - */
160   -class RandomCentroidsTransform : public Transform
161   -{
162   - Q_OBJECT
163   - Q_PROPERTY(int kTrain READ get_kTrain WRITE set_kTrain RESET reset_kTrain STORED false)
164   - Q_PROPERTY(int kSearch READ get_kSearch WRITE set_kSearch RESET reset_kSearch STORED false)
165   - BR_PROPERTY(int, kTrain, 256)
166   - BR_PROPERTY(int, kSearch, 1)
167   -
168   - Mat centers;
169   - mutable QScopedPointer<flann::Index> index;
170   - mutable QMutex mutex;
171   -
172   - void reindex()
173   - {
174   - index.reset(new flann::Index(centers, flann::LinearIndexParams()));
175   - }
176   -
177   - void train(const TemplateList &data)
178   - {
179   - Mat flat = OpenCVUtils::toMatByRow(data.data());
180   - QList<int> sample = Common::RandSample(kTrain, flat.rows, 0, true);
181   - foreach (const int &idx, sample)
182   - centers.push_back(flat.row(idx));
183   - reindex();
184   - }
185   -
186   - void project(const Template &src, Template &dst) const
187   - {
188   - QMutexLocker locker(&mutex);
189   - Mat dists, indicies;
190   - index->knnSearch(src, indicies, dists, kSearch);
191   - dst = indicies.reshape(1, 1);
192   - }
193   -
194   - void load(QDataStream &stream)
195   - {
196   - stream >> centers;
197   - reindex();
198   - }
199   -
200   - void store(QDataStream &stream) const
201   - {
202   - stream << centers;
203   - }
204   -};
205   -
206   -BR_REGISTER(Transform, RandomCentroidsTransform)
207   -
208   -class RegInitializer : public Initializer
209   -{
210   - Q_OBJECT
211   -
212   - void initialize() const
213   - {
214   - qRegisterMetaType<br::Neighbors>();
215   - }
216   -};
217   -BR_REGISTER(Initializer, RegInitializer)
218   -
219   -class CollectNNTransform : public UntrainableMetaTransform
220   -{
221   - Q_OBJECT
222   -
223   - Q_PROPERTY(int keep READ get_keep WRITE set_keep RESET reset_keep STORED false)
224   - BR_PROPERTY(int, keep, 20)
225   -
226   - void project(const Template &src, Template &dst) const
227   - {
228   - dst.file = src.file;
229   - dst.clear();
230   - dst.m() = cv::Mat();
231   - Neighbors neighbors;
232   - for (int i=0; i < src.m().cols;i++) {
233   - // skip self compares
234   - if (i == src.file.get<int>("FrameNumber"))
235   - continue;
236   - neighbors.append(Neighbor(i, src.m().at<float>(0,i)));
237   - }
238   - int actuallyKeep = std::min(keep, neighbors.size());
239   - std::partial_sort(neighbors.begin(), neighbors.begin()+actuallyKeep, neighbors.end(), compareNeighbors);
240   -
241   - Neighbors selected = neighbors.mid(0, actuallyKeep);
242   - dst.file.set("neighbors", QVariant::fromValue(selected));
243   - }
244   -};
245   -BR_REGISTER(Transform, CollectNNTransform)
246   -
247   -class LogNNTransform : public TimeVaryingTransform
248   -{
249   - Q_OBJECT
250   -
251   - Q_PROPERTY(QString fileName READ get_fileName WRITE set_fileName RESET reset_fileName STORED false)
252   - BR_PROPERTY(QString, fileName, "")
253   -
254   - std::fstream fout;
255   -
256   - void projectUpdate(const Template &src, Template &dst)
257   - {
258   - dst = src;
259   -
260   - if (!dst.file.contains("neighbors")) {
261   - fout << std::endl;
262   - return;
263   - }
264   -
265   - Neighbors neighbors = dst.file.get<Neighbors>("neighbors");
266   - if (neighbors.isEmpty() ) {
267   - fout << std::endl;
268   - return;
269   - }
270   -
271   - QString aLine;
272   - aLine.append(QString::number(neighbors[0].first)+":"+QString::number(neighbors[0].second));
273   - for (int i=1; i < neighbors.size();i++)
274   - aLine.append(","+QString::number(neighbors[i].first)+":"+QString::number(neighbors[i].second));
275   -
276   - fout << qPrintable(aLine) << std::endl;
277   - }
278   -
279   - void init()
280   - {
281   - if (!fileName.isEmpty())
282   - fout.open(qPrintable(fileName), std::ios_base::out);
283   - }
284   -
285   - void finalize(TemplateList &output)
286   - {
287   - (void) output;
288   - fout.close();
289   - }
290   -
291   -public:
292   - LogNNTransform() : TimeVaryingTransform(false, false) {}
293   -};
294   -BR_REGISTER(Transform, LogNNTransform)
295   -
296 82 } // namespace br
297 83  
298   -#include "cluster.moc"
  84 +#include "knn.moc"
... ...
openbr/plugins/cluster/lognn.cpp 0 → 100644
  1 +#include <fstream>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Log nearest neighbors to specified file.
  11 + * \author Charles Otto \cite caotto
  12 + */
  13 +class LogNNTransform : public TimeVaryingTransform
  14 +{
  15 + Q_OBJECT
  16 +
  17 + Q_PROPERTY(QString fileName READ get_fileName WRITE set_fileName RESET reset_fileName STORED false)
  18 + BR_PROPERTY(QString, fileName, "")
  19 +
  20 + std::fstream fout;
  21 +
  22 + void projectUpdate(const Template &src, Template &dst)
  23 + {
  24 + dst = src;
  25 +
  26 + if (!dst.file.contains("neighbors")) {
  27 + fout << std::endl;
  28 + return;
  29 + }
  30 +
  31 + Neighbors neighbors = dst.file.get<Neighbors>("neighbors");
  32 + if (neighbors.isEmpty() ) {
  33 + fout << std::endl;
  34 + return;
  35 + }
  36 +
  37 + QString aLine;
  38 + aLine.append(QString::number(neighbors[0].first)+":"+QString::number(neighbors[0].second));
  39 + for (int i=1; i < neighbors.size();i++)
  40 + aLine.append(","+QString::number(neighbors[i].first)+":"+QString::number(neighbors[i].second));
  41 +
  42 + fout << qPrintable(aLine) << std::endl;
  43 + }
  44 +
  45 + void init()
  46 + {
  47 + if (!fileName.isEmpty())
  48 + fout.open(qPrintable(fileName), std::ios_base::out);
  49 + }
  50 +
  51 + void finalize(TemplateList &output)
  52 + {
  53 + (void) output;
  54 + fout.close();
  55 + }
  56 +
  57 +public:
  58 + LogNNTransform() : TimeVaryingTransform(false, false) {}
  59 +};
  60 +
  61 +BR_REGISTER(Transform, LogNNTransform)
  62 +
  63 +} // namespace br
  64 +
  65 +#include "lognn.moc"
... ...
openbr/plugins/cluster/randomcentroids.cpp 0 → 100644
  1 +#include <opencv2/flann/flann.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +#include <openbr/core/common.h>
  5 +#include <openbr/core/opencvutils.h>
  6 +
  7 +using namespace cv;
  8 +
  9 +namespace br
  10 +{
  11 +
  12 +/*!
  13 + * \ingroup transforms
  14 + * \brief Chooses k random points to be centroids.
  15 + * \author Austin Blanton \cite imaus10
  16 + * \see KMeansTransform
  17 + */
  18 +class RandomCentroidsTransform : public Transform
  19 +{
  20 + Q_OBJECT
  21 + Q_PROPERTY(int kTrain READ get_kTrain WRITE set_kTrain RESET reset_kTrain STORED false)
  22 + Q_PROPERTY(int kSearch READ get_kSearch WRITE set_kSearch RESET reset_kSearch STORED false)
  23 + BR_PROPERTY(int, kTrain, 256)
  24 + BR_PROPERTY(int, kSearch, 1)
  25 +
  26 + Mat centers;
  27 + mutable QScopedPointer<flann::Index> index;
  28 + mutable QMutex mutex;
  29 +
  30 + void reindex()
  31 + {
  32 + index.reset(new flann::Index(centers, flann::LinearIndexParams()));
  33 + }
  34 +
  35 + void train(const TemplateList &data)
  36 + {
  37 + Mat flat = OpenCVUtils::toMatByRow(data.data());
  38 + QList<int> sample = Common::RandSample(kTrain, flat.rows, 0, true);
  39 + foreach (const int &idx, sample)
  40 + centers.push_back(flat.row(idx));
  41 + reindex();
  42 + }
  43 +
  44 + void project(const Template &src, Template &dst) const
  45 + {
  46 + QMutexLocker locker(&mutex);
  47 + Mat dists, indicies;
  48 + index->knnSearch(src, indicies, dists, kSearch);
  49 + dst = indicies.reshape(1, 1);
  50 + }
  51 +
  52 + void load(QDataStream &stream)
  53 + {
  54 + stream >> centers;
  55 + reindex();
  56 + }
  57 +
  58 + void store(QDataStream &stream) const
  59 + {
  60 + stream << centers;
  61 + }
  62 +};
  63 +
  64 +BR_REGISTER(Transform, RandomCentroidsTransform)
  65 +
  66 +} //namespace br
  67 +
  68 +#include "randomcentroids.moc"
... ...
openbr/plugins/algorithms.cpp renamed to openbr/plugins/core/algorithms.cpp
... ... @@ -14,7 +14,7 @@
14 14 * limitations under the License. *
15 15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 16  
17   -#include "openbr_internal.h"
  17 +#include <openbr/plugins/openbr_internal.h>
18 18  
19 19 namespace br
20 20 {
... ...
openbr/plugins/independent.cpp renamed to openbr/plugins/core/downsample.cpp
1   -#include <QFutureSynchronizer>
2   -#include <QtConcurrentRun>
3   -
4   -#include "openbr_internal.h"
5   -#include "openbr/core/common.h"
6   -
7   -using namespace cv;
  1 +#include <openbr/plugins/openbr_internal.h>
8 2  
9 3 namespace br
10 4 {
... ... @@ -103,10 +97,10 @@ class DownsampleTrainingTransform : public Transform
103 97  
104 98 void project(const Template &src, Template &dst) const
105 99 {
106   - transform->project(src,dst);
  100 + transform->project(src,dst);
107 101 }
108   -
109   -
  102 +
  103 +
110 104 void train(const TemplateList &data)
111 105 {
112 106 if (!transform || !transform->trainable)
... ... @@ -117,274 +111,9 @@ class DownsampleTrainingTransform : public Transform
117 111 transform->train(downsampled);
118 112 }
119 113 };
120   -BR_REGISTER(Transform, DownsampleTrainingTransform)
121   -
122   -/*!
123   - * \ingroup transforms
124   - * \brief Clones the transform so that it can be applied independently.
125   - * \author Josh Klontz \cite jklontz
126   - * \em Independent transforms expect single-matrix templates.
127   - */
128   -class IndependentTransform : public MetaTransform
129   -{
130   - Q_OBJECT
131   - Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
132   - BR_PROPERTY(br::Transform*, transform, NULL)
133   -
134   - QList<Transform*> transforms;
135   -
136   - QString description(bool expanded) const
137   - {
138   - return transform->description(expanded);
139   - }
140   -
141   - // can't use general setPropertyRecursive because of transforms oddness
142   - bool setPropertyRecursive(const QString &name, QVariant value)
143   - {
144   - if (br::Object::setExistingProperty(name, value))
145   - return true;
146   -
147   - if (!transform->setPropertyRecursive(name, value))
148   - return false;
149   -
150   - for (int i=0;i < transforms.size();i++)
151   - transforms[i]->setPropertyRecursive(name, value);
152   -
153   - return true;
154   - }
155   -
156   - Transform *simplify(bool &newTransform)
157   - {
158   - newTransform = false;
159   - bool newChild = false;
160   - Transform *temp = transform->simplify(newChild);
161   - if (temp == transform) {
162   - return this;
163   - }
164   - IndependentTransform* indep = new IndependentTransform();
165   - indep->transform = temp;
166   -
167   - IndependentTransform *test = dynamic_cast<IndependentTransform *> (temp);
168   - if (test) {
169   - // child was independent? this changes things...
170   - indep->transform = test->transform;
171   - for (int i=0; i < transforms.size(); i++) {
172   - bool newThing = false;
173   - IndependentTransform *probe = dynamic_cast<IndependentTransform *> (transforms[i]->simplify(newThing));
174   - indep->transforms.append(probe->transform);
175   - if (newThing)
176   - probe->setParent(indep);
177   - }
178   - indep->file = indep->transform->file;
179   - indep->trainable = indep->transform->trainable;
180   - indep->setObjectName(indep->transform->objectName());
181   -
182   - return indep;
183   - }
184   -
185   - if (newChild)
186   - indep->transform->setParent(indep);
187   -
188   - for (int i=0; i < transforms.size();i++) {
189   - bool subTform = false;
190   - indep->transforms.append(transforms[i]->simplify(subTform));
191   - if (subTform)
192   - indep->transforms[i]->setParent(indep);
193   - }
194 114  
195   - indep->file = indep->transform->file;
196   - indep->trainable = indep->transform->trainable;
197   - indep->setObjectName(indep->transform->objectName());
198   -
199   - return indep;
200   - }
201   -
202   - void init()
203   - {
204   - transforms.clear();
205   - if (transform == NULL)
206   - return;
207   -
208   - transform->setParent(this);
209   - transforms.append(transform);
210   - file = transform->file;
211   - trainable = transform->trainable;
212   - setObjectName(transform->objectName());
213   - }
214   -
215   - Transform *clone() const
216   - {
217   - IndependentTransform *independentTransform = new IndependentTransform();
218   - independentTransform->transform = transform->clone();
219   - independentTransform->init();
220   - return independentTransform;
221   - }
222   -
223   - bool timeVarying() const { return transform->timeVarying(); }
224   -
225   - static void _train(Transform *transform, const TemplateList *data)
226   - {
227   - transform->train(*data);
228   - }
229   -
230   - void train(const TemplateList &data)
231   - {
232   - // Don't bother if the transform is untrainable
233   - if (!trainable) return;
234   -
235   - QList<TemplateList> templatesList;
236   - foreach (const Template &t, data) {
237   - if ((templatesList.size() != t.size()) && !templatesList.isEmpty())
238   - qWarning("Independent::train (%s) template %s of size %d differs from expected size %d.", qPrintable(objectName()), qPrintable(t.file.name), t.size(), templatesList.size());
239   - while (templatesList.size() < t.size())
240   - templatesList.append(TemplateList());
241   - for (int i=0; i<t.size(); i++)
242   - templatesList[i].append(Template(t.file, t[i]));
243   - }
244   -
245   - while (transforms.size() < templatesList.size())
246   - transforms.append(transform->clone());
247   -
248   - QFutureSynchronizer<void> futures;
249   - for (int i=0; i<templatesList.size(); i++)
250   - futures.addFuture(QtConcurrent::run(_train, transforms[i], &templatesList[i]));
251   - futures.waitForFinished();
252   - }
253   -
254   - void project(const Template &src, Template &dst) const
255   - {
256   - dst.file = src.file;
257   - QList<Mat> mats;
258   - for (int i=0; i<src.size(); i++) {
259   - transforms[i%transforms.size()]->project(Template(src.file, src[i]), dst);
260   - mats.append(dst);
261   - dst.clear();
262   - }
263   - dst.append(mats);
264   - }
265   -
266   - void projectUpdate(const Template &src, Template &dst)
267   - {
268   - dst.file = src.file;
269   - QList<Mat> mats;
270   - for (int i=0; i<src.size(); i++) {
271   - transforms[i%transforms.size()]->projectUpdate(Template(src.file, src[i]), dst);
272   - mats.append(dst);
273   - dst.clear();
274   - }
275   - dst.append(mats);
276   - }
277   -
278   - void finalize(TemplateList &out)
279   - {
280   - if (transforms.empty())
281   - return;
282   -
283   - transforms[0]->finalize(out);
284   - for (int i=1; i < transforms.size(); i++) {
285   - TemplateList temp;
286   - transforms[i]->finalize(temp);
287   -
288   - for (int j=0; j < out.size(); j++)
289   - out[j].append(temp[j]);
290   - }
291   - }
292   -
293   - void projectUpdate(const TemplateList &src, TemplateList &dst)
294   - {
295   - dst.reserve(src.size());
296   - foreach (const Template &t, src) {
297   - dst.append(Template());
298   - projectUpdate(t, dst.last());
299   - }
300   - }
301   -
302   - void store(QDataStream &stream) const
303   - {
304   - const int size = transforms.size();
305   - stream << size;
306   - for (int i=0; i<size; i++)
307   - transforms[i]->store(stream);
308   - }
309   -
310   - void load(QDataStream &stream)
311   - {
312   - int size;
313   - stream >> size;
314   - while (transforms.size() < size)
315   - transforms.append(transform->clone());
316   - for (int i=0; i<size; i++)
317   - transforms[i]->load(stream);
318   - }
319   -};
320   -
321   -BR_REGISTER(Transform, IndependentTransform)
322   -
323   -/*!
324   - * \ingroup transforms
325   - * \brief A globally shared transform.
326   - * \author Josh Klontz \cite jklontz
327   - */
328   -class SingletonTransform : public MetaTransform
329   -{
330   - Q_OBJECT
331   - Q_PROPERTY(QString description READ get_description WRITE set_description RESET reset_description STORED false)
332   - BR_PROPERTY(QString, description, "Identity")
333   -
334   - static QMutex mutex;
335   - static QHash<QString,Transform*> transforms;
336   - static QHash<QString,int> trainingReferenceCounts;
337   - static QHash<QString,TemplateList> trainingData;
338   -
339   - Transform *transform;
340   -
341   - void init()
342   - {
343   - QMutexLocker locker(&mutex);
344   - if (!transforms.contains(description)) {
345   - transforms.insert(description, make(description));
346   - trainingReferenceCounts.insert(description, 0);
347   - }
348   -
349   - transform = transforms[description];
350   - trainingReferenceCounts[description]++;
351   - }
352   -
353   - void train(const TemplateList &data)
354   - {
355   - QMutexLocker locker(&mutex);
356   - trainingData[description].append(data);
357   - trainingReferenceCounts[description]--;
358   - if (trainingReferenceCounts[description] > 0) return;
359   - transform->train(trainingData[description]);
360   - trainingData[description].clear();
361   - }
362   -
363   - void project(const Template &src, Template &dst) const
364   - {
365   - transform->project(src, dst);
366   - }
367   -
368   - void store(QDataStream &stream) const
369   - {
370   - if (transform->parent() == this)
371   - transform->store(stream);
372   - }
373   -
374   - void load(QDataStream &stream)
375   - {
376   - if (transform->parent() == this)
377   - transform->load(stream);
378   - }
379   -};
380   -
381   -QMutex SingletonTransform::mutex;
382   -QHash<QString,Transform*> SingletonTransform::transforms;
383   -QHash<QString,int> SingletonTransform::trainingReferenceCounts;
384   -QHash<QString,TemplateList> SingletonTransform::trainingData;
385   -
386   -BR_REGISTER(Transform, SingletonTransform)
  115 +BR_REGISTER(Transform, DownsampleTrainingTransform)
387 116  
388 117 } // namespace br
389 118  
390   -#include "independent.moc"
  119 +#include "downsample.moc"
... ...
openbr/plugins/core/independent.cpp 0 → 100644
  1 +#include <QtConcurrent>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Clones the transform so that it can be applied independently.
  13 + * \author Josh Klontz \cite jklontz
  14 + * \em Independent transforms expect single-matrix templates.
  15 + */
  16 +class IndependentTransform : public MetaTransform
  17 +{
  18 + Q_OBJECT
  19 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
  20 + BR_PROPERTY(br::Transform*, transform, NULL)
  21 +
  22 + QList<Transform*> transforms;
  23 +
  24 + QString description(bool expanded) const
  25 + {
  26 + return transform->description(expanded);
  27 + }
  28 +
  29 + // can't use general setPropertyRecursive because of transforms oddness
  30 + bool setPropertyRecursive(const QString &name, QVariant value)
  31 + {
  32 + if (br::Object::setExistingProperty(name, value))
  33 + return true;
  34 +
  35 + if (!transform->setPropertyRecursive(name, value))
  36 + return false;
  37 +
  38 + for (int i=0;i < transforms.size();i++)
  39 + transforms[i]->setPropertyRecursive(name, value);
  40 +
  41 + return true;
  42 + }
  43 +
  44 + Transform *simplify(bool &newTransform)
  45 + {
  46 + newTransform = false;
  47 + bool newChild = false;
  48 + Transform *temp = transform->simplify(newChild);
  49 + if (temp == transform) {
  50 + return this;
  51 + }
  52 + IndependentTransform* indep = new IndependentTransform();
  53 + indep->transform = temp;
  54 +
  55 + IndependentTransform *test = dynamic_cast<IndependentTransform *> (temp);
  56 + if (test) {
  57 + // child was independent? this changes things...
  58 + indep->transform = test->transform;
  59 + for (int i=0; i < transforms.size(); i++) {
  60 + bool newThing = false;
  61 + IndependentTransform *probe = dynamic_cast<IndependentTransform *> (transforms[i]->simplify(newThing));
  62 + indep->transforms.append(probe->transform);
  63 + if (newThing)
  64 + probe->setParent(indep);
  65 + }
  66 + indep->file = indep->transform->file;
  67 + indep->trainable = indep->transform->trainable;
  68 + indep->setObjectName(indep->transform->objectName());
  69 +
  70 + return indep;
  71 + }
  72 +
  73 + if (newChild)
  74 + indep->transform->setParent(indep);
  75 +
  76 + for (int i=0; i < transforms.size();i++) {
  77 + bool subTform = false;
  78 + indep->transforms.append(transforms[i]->simplify(subTform));
  79 + if (subTform)
  80 + indep->transforms[i]->setParent(indep);
  81 + }
  82 +
  83 + indep->file = indep->transform->file;
  84 + indep->trainable = indep->transform->trainable;
  85 + indep->setObjectName(indep->transform->objectName());
  86 +
  87 + return indep;
  88 + }
  89 +
  90 + void init()
  91 + {
  92 + transforms.clear();
  93 + if (transform == NULL)
  94 + return;
  95 +
  96 + transform->setParent(this);
  97 + transforms.append(transform);
  98 + file = transform->file;
  99 + trainable = transform->trainable;
  100 + setObjectName(transform->objectName());
  101 + }
  102 +
  103 + Transform *clone() const
  104 + {
  105 + IndependentTransform *independentTransform = new IndependentTransform();
  106 + independentTransform->transform = transform->clone();
  107 + independentTransform->init();
  108 + return independentTransform;
  109 + }
  110 +
  111 + bool timeVarying() const { return transform->timeVarying(); }
  112 +
  113 + static void _train(Transform *transform, const TemplateList *data)
  114 + {
  115 + transform->train(*data);
  116 + }
  117 +
  118 + void train(const TemplateList &data)
  119 + {
  120 + // Don't bother if the transform is untrainable
  121 + if (!trainable) return;
  122 +
  123 + QList<TemplateList> templatesList;
  124 + foreach (const Template &t, data) {
  125 + if ((templatesList.size() != t.size()) && !templatesList.isEmpty())
  126 + qWarning("Independent::train (%s) template %s of size %d differs from expected size %d.", qPrintable(objectName()), qPrintable(t.file.name), t.size(), templatesList.size());
  127 + while (templatesList.size() < t.size())
  128 + templatesList.append(TemplateList());
  129 + for (int i=0; i<t.size(); i++)
  130 + templatesList[i].append(Template(t.file, t[i]));
  131 + }
  132 +
  133 + while (transforms.size() < templatesList.size())
  134 + transforms.append(transform->clone());
  135 +
  136 + QFutureSynchronizer<void> futures;
  137 + for (int i=0; i<templatesList.size(); i++)
  138 + futures.addFuture(QtConcurrent::run(_train, transforms[i], &templatesList[i]));
  139 + futures.waitForFinished();
  140 + }
  141 +
  142 + void project(const Template &src, Template &dst) const
  143 + {
  144 + dst.file = src.file;
  145 + QList<Mat> mats;
  146 + for (int i=0; i<src.size(); i++) {
  147 + transforms[i%transforms.size()]->project(Template(src.file, src[i]), dst);
  148 + mats.append(dst);
  149 + dst.clear();
  150 + }
  151 + dst.append(mats);
  152 + }
  153 +
  154 + void projectUpdate(const Template &src, Template &dst)
  155 + {
  156 + dst.file = src.file;
  157 + QList<Mat> mats;
  158 + for (int i=0; i<src.size(); i++) {
  159 + transforms[i%transforms.size()]->projectUpdate(Template(src.file, src[i]), dst);
  160 + mats.append(dst);
  161 + dst.clear();
  162 + }
  163 + dst.append(mats);
  164 + }
  165 +
  166 + void finalize(TemplateList &out)
  167 + {
  168 + if (transforms.empty())
  169 + return;
  170 +
  171 + transforms[0]->finalize(out);
  172 + for (int i=1; i < transforms.size(); i++) {
  173 + TemplateList temp;
  174 + transforms[i]->finalize(temp);
  175 +
  176 + for (int j=0; j < out.size(); j++)
  177 + out[j].append(temp[j]);
  178 + }
  179 + }
  180 +
  181 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  182 + {
  183 + dst.reserve(src.size());
  184 + foreach (const Template &t, src) {
  185 + dst.append(Template());
  186 + projectUpdate(t, dst.last());
  187 + }
  188 + }
  189 +
  190 + void store(QDataStream &stream) const
  191 + {
  192 + const int size = transforms.size();
  193 + stream << size;
  194 + for (int i=0; i<size; i++)
  195 + transforms[i]->store(stream);
  196 + }
  197 +
  198 + void load(QDataStream &stream)
  199 + {
  200 + int size;
  201 + stream >> size;
  202 + while (transforms.size() < size)
  203 + transforms.append(transform->clone());
  204 + for (int i=0; i<size; i++)
  205 + transforms[i]->load(stream);
  206 + }
  207 +};
  208 +
  209 +BR_REGISTER(Transform, IndependentTransform)
  210 +
  211 +} // namespace br
  212 +
  213 +#include "independent.moc"
... ...
openbr/plugins/core/singleton.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief A globally shared transform.
  9 + * \author Josh Klontz \cite jklontz
  10 + */
  11 +class SingletonTransform : public MetaTransform
  12 +{
  13 + Q_OBJECT
  14 + Q_PROPERTY(QString description READ get_description WRITE set_description RESET reset_description STORED false)
  15 + BR_PROPERTY(QString, description, "Identity")
  16 +
  17 + static QMutex mutex;
  18 + static QHash<QString,Transform*> transforms;
  19 + static QHash<QString,int> trainingReferenceCounts;
  20 + static QHash<QString,TemplateList> trainingData;
  21 +
  22 + Transform *transform;
  23 +
  24 + void init()
  25 + {
  26 + QMutexLocker locker(&mutex);
  27 + if (!transforms.contains(description)) {
  28 + transforms.insert(description, make(description));
  29 + trainingReferenceCounts.insert(description, 0);
  30 + }
  31 +
  32 + transform = transforms[description];
  33 + trainingReferenceCounts[description]++;
  34 + }
  35 +
  36 + void train(const TemplateList &data)
  37 + {
  38 + QMutexLocker locker(&mutex);
  39 + trainingData[description].append(data);
  40 + trainingReferenceCounts[description]--;
  41 + if (trainingReferenceCounts[description] > 0) return;
  42 + transform->train(trainingData[description]);
  43 + trainingData[description].clear();
  44 + }
  45 +
  46 + void project(const Template &src, Template &dst) const
  47 + {
  48 + transform->project(src, dst);
  49 + }
  50 +
  51 + void store(QDataStream &stream) const
  52 + {
  53 + if (transform->parent() == this)
  54 + transform->store(stream);
  55 + }
  56 +
  57 + void load(QDataStream &stream)
  58 + {
  59 + if (transform->parent() == this)
  60 + transform->load(stream);
  61 + }
  62 +};
  63 +
  64 +QMutex SingletonTransform::mutex;
  65 +QHash<QString,Transform*> SingletonTransform::transforms;
  66 +QHash<QString,int> SingletonTransform::trainingReferenceCounts;
  67 +QHash<QString,TemplateList> SingletonTransform::trainingData;
  68 +
  69 +BR_REGISTER(Transform, SingletonTransform)
  70 +
  71 +} // namespace br
  72 +
  73 +#include "singleton.moc"
... ...
openbr/plugins/crop.cpp deleted
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 "openbr_internal.h"
19   -
20   -#include "openbr/core/opencvutils.h"
21   -
22   -using namespace cv;
23   -
24   -namespace br
25   -{
26   -
27   -/*!
28   - * \ingroup transforms
29   - * \brief Crops about the specified region of interest.
30   - * \author Josh Klontz \cite jklontz
31   - */
32   -class CropTransform : public UntrainableTransform
33   -{
34   - Q_OBJECT
35   - Q_PROPERTY(int x READ get_x WRITE set_x RESET reset_x STORED false)
36   - Q_PROPERTY(int y READ get_y WRITE set_y RESET reset_y STORED false)
37   - Q_PROPERTY(int width READ get_width WRITE set_width RESET reset_width STORED false)
38   - Q_PROPERTY(int height READ get_height WRITE set_height RESET reset_height STORED false)
39   - BR_PROPERTY(int, x, 0)
40   - BR_PROPERTY(int, y, 0)
41   - BR_PROPERTY(int, width, -1)
42   - BR_PROPERTY(int, height, -1)
43   -
44   - void project(const Template &src, Template &dst) const
45   - {
46   - dst = Mat(src, Rect(x, y, width < 1 ? src.m().cols-x-abs(width) : width, height < 1 ? src.m().rows-y-abs(height) : height));
47   - }
48   -};
49   -
50   -BR_REGISTER(Transform, CropTransform)
51   -
52   -/*!
53   - * \ingroup transforms
54   - * \brief Crops the rectangular regions of interest.
55   - * \author Josh Klontz \cite jklontz
56   - */
57   -class ROITransform : public UntrainableTransform
58   -{
59   - Q_OBJECT
60   - Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false)
61   - BR_PROPERTY(QString, propName, "")
62   -
63   - void project(const Template &src, Template &dst) const
64   - {
65   - if (!propName.isEmpty()) {
66   - QRectF rect = src.file.get<QRectF>(propName);
67   - dst += src.m()(OpenCVUtils::toRect(rect));
68   - } else if (!src.file.rects().empty()) {
69   - foreach (const QRectF &rect, src.file.rects())
70   - dst += src.m()(OpenCVUtils::toRect(rect));
71   - } else if (src.file.contains(QStringList() << "X" << "Y" << "Width" << "Height")) {
72   - dst += src.m()(Rect(src.file.get<int>("X"),
73   - src.file.get<int>("Y"),
74   - src.file.get<int>("Width"),
75   - src.file.get<int>("Height")));
76   - } else {
77   - dst = src;
78   - if (Globals->verbose)
79   - qWarning("No rects present in file.");
80   - }
81   - }
82   -};
83   -
84   -BR_REGISTER(Transform, ROITransform)
85   -
86   -/*!
87   - * \ingroup transforms
88   - * \brief Crops the rectangular regions of interest from given points and sizes.
89   - * \author Austin Blanton \cite imaus10
90   - */
91   -class ROIFromPtsTransform : public UntrainableTransform
92   -{
93   - Q_OBJECT
94   - Q_PROPERTY(int width READ get_width WRITE set_width RESET reset_width STORED false)
95   - Q_PROPERTY(int height READ get_height WRITE set_height RESET reset_height STORED false)
96   - BR_PROPERTY(int, width, 1)
97   - BR_PROPERTY(int, height, 1)
98   -
99   - void project(const Template &src, Template &dst) const
100   - {
101   - foreach (const QPointF &pt, src.file.points()) {
102   - int x = pt.x() - (width/2);
103   - int y = pt.y() - (height/2);
104   - dst += src.m()(Rect(x, y, width, height));
105   - }
106   - }
107   -};
108   -
109   -BR_REGISTER(Transform, ROIFromPtsTransform)
110   -
111   -/*!
112   - * \ingroup transforms
113   - * \brief Resize the template
114   - * \author Josh Klontz \cite jklontz
115   - * \note Method: Area should be used for shrinking an image, Cubic for slow but accurate enlargment, Bilin for fast enlargement.
116   - * \param preserveAspect If true, the image will be sized per specification, but
117   - * a border will be applied to preserve aspect ratio.
118   - */
119   -class ResizeTransform : public UntrainableTransform
120   -{
121   - Q_OBJECT
122   - Q_ENUMS(Method)
123   -
124   -public:
125   - /*!< */
126   - enum Method { Near = INTER_NEAREST,
127   - Area = INTER_AREA,
128   - Bilin = INTER_LINEAR,
129   - Cubic = INTER_CUBIC,
130   - Lanczo = INTER_LANCZOS4};
131   -
132   -private:
133   - Q_PROPERTY(int rows READ get_rows WRITE set_rows RESET reset_rows STORED false)
134   - Q_PROPERTY(int columns READ get_columns WRITE set_columns RESET reset_columns STORED false)
135   - Q_PROPERTY(Method method READ get_method WRITE set_method RESET reset_method STORED false)
136   - Q_PROPERTY(bool preserveAspect READ get_preserveAspect WRITE set_preserveAspect RESET reset_preserveAspect STORED false)
137   - BR_PROPERTY(int, rows, -1)
138   - BR_PROPERTY(int, columns, -1)
139   - BR_PROPERTY(Method, method, Bilin)
140   - BR_PROPERTY(bool, preserveAspect, false)
141   -
142   - void project(const Template &src, Template &dst) const
143   - {
144   - if (!preserveAspect)
145   - resize(src, dst, Size((columns == -1) ? src.m().cols*rows/src.m().rows : columns, rows), 0, 0, method);
146   - else {
147   - float inRatio = (float) src.m().rows / src.m().cols;
148   - float outRatio = (float) rows / columns;
149   - dst = Mat::zeros(rows, columns, src.m().type());
150   - if (outRatio > inRatio) {
151   - float heightAR = src.m().rows * inRatio / outRatio;
152   - Mat buffer;
153   - resize(src, buffer, Size(columns, heightAR), 0, 0, method);
154   - buffer.copyTo(dst.m()(Rect(0, (rows - heightAR) / 2, columns, heightAR)));
155   - } else {
156   - float widthAR = src.m().cols / inRatio * outRatio;
157   - Mat buffer;
158   - resize(src, buffer, Size(widthAR, rows), 0, 0, method);
159   - buffer.copyTo(dst.m()(Rect((columns - widthAR) / 2, 0, widthAR, rows)));
160   - }
161   - }
162   - }
163   -};
164   -
165   -BR_REGISTER(Transform, ResizeTransform)
166   -
167   -/*!
168   - * \ingroup transforms
169   - * \brief Limit the size of the template
170   - * \author Josh Klontz \cite jklontz
171   - */
172   -class LimitSizeTransform : public UntrainableTransform
173   -{
174   - Q_OBJECT
175   - Q_PROPERTY(int max READ get_max WRITE set_max RESET reset_max STORED false)
176   - BR_PROPERTY(int, max, -1)
177   -
178   - void project(const Template &src, Template &dst) const
179   - {
180   - const Mat &m = src;
181   - if (m.rows > m.cols)
182   - if (m.rows > max) resize(m, dst, Size(std::max(1, m.cols * max / m.rows), max));
183   - else dst = m;
184   - else
185   - if (m.cols > max) resize(m, dst, Size(max, std::max(1, m.rows * max / m.cols)));
186   - else dst = m;
187   - }
188   -};
189   -
190   -BR_REGISTER(Transform, LimitSizeTransform)
191   -
192   -/*!
193   - * \ingroup transforms
194   - * \brief Enforce a multiple of \em n columns.
195   - * \author Josh Klontz \cite jklontz
196   - */
197   -class DivTransform : public UntrainableTransform
198   -{
199   - Q_OBJECT
200   - Q_PROPERTY(int n READ get_n WRITE set_n RESET reset_n STORED false)
201   - BR_PROPERTY(int, n, 1)
202   -
203   - void project(const Template &src, Template &dst) const
204   - {
205   - dst = Mat(src, Rect(0,0,n*(src.m().cols/n),src.m().rows));
206   - }
207   -};
208   -
209   -BR_REGISTER(Transform, DivTransform)
210   -
211   -/*!
212   - * \ingroup transforms
213   - * \brief Crop out black borders
214   - * \author Josh Klontz \cite jklontz
215   - */
216   -class CropBlackTransform : public UntrainableTransform
217   -{
218   - Q_OBJECT
219   -
220   - void project(const Template &src, Template &dst) const
221   - {
222   - Mat gray;
223   - OpenCVUtils::cvtGray(src, gray);
224   -
225   - int xStart = 0;
226   - while (xStart < gray.cols) {
227   - if (mean(gray.col(xStart))[0] >= 1) break;
228   - xStart++;
229   - }
230   -
231   - int xEnd = gray.cols - 1;
232   - while (xEnd >= 0) {
233   - if (mean(gray.col(xEnd))[0] >= 1) break;
234   - xEnd--;
235   - }
236   -
237   - int yStart = 0;
238   - while (yStart < gray.rows) {
239   - if (mean(gray.col(yStart))[0] >= 1) break;
240   - yStart++;
241   - }
242   -
243   - int yEnd = gray.rows - 1;
244   - while (yEnd >= 0) {
245   - if (mean(gray.col(yEnd))[0] >= 1) break;
246   - yEnd--;
247   - }
248   -
249   - dst = src.m()(Rect(xStart, yStart, xEnd-xStart, yEnd-yStart));
250   - }
251   -};
252   -
253   -BR_REGISTER(Transform, CropBlackTransform)
254   -
255   -/*!
256   - * \ingroup transforms
257   - * \brief Divide the matrix into 4 smaller matricies of equal size.
258   - * \author Josh Klontz \cite jklontz
259   - */
260   -class SubdivideTransform : public UntrainableTransform
261   -{
262   - Q_OBJECT
263   -
264   - void project(const Template &src, Template &dst) const
265   - {
266   - const Mat &m = src;
267   - const int subrows = m.rows/2;
268   - const int subcolumns = m.cols/2;
269   - dst.append(Mat(m,Rect(0, 0, subcolumns, subrows)).clone());
270   - dst.append(Mat(m,Rect(subcolumns, 0, subcolumns, subrows)).clone());
271   - dst.append(Mat(m,Rect(0, subrows, subcolumns, subrows)).clone());
272   - dst.append(Mat(m,Rect(subcolumns, subrows, subcolumns, subrows)).clone());
273   - }
274   -};
275   -
276   -BR_REGISTER(Transform, SubdivideTransform)
277   -
278   -/*!
279   - * \ingroup transforms
280   - * \brief Trim the image so the width and the height are the same size.
281   - * \author Josh Klontz \cite jklontz
282   - */
283   -class CropSquareTransform : public UntrainableTransform
284   -{
285   - Q_OBJECT
286   -
287   - void project(const Template &src, Template &dst) const
288   - {
289   - const Mat &m = src;
290   - const int newSize = min(m.rows, m.cols);
291   - dst = Mat(m, Rect((m.cols-newSize)/2, (m.rows-newSize)/2, newSize, newSize));
292   - }
293   -};
294   -
295   -BR_REGISTER(Transform, CropSquareTransform)
296   -
297   -} // namespace br
298   -
299   -#include "crop.moc"
openbr/plugins/cvt.cpp deleted
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_c.h>
18   -#include <opencv2/imgproc/imgproc.hpp>
19   -#include "openbr_internal.h"
20   -#include "openbr/core/opencvutils.h"
21   -
22   -using namespace cv;
23   -
24   -namespace br
25   -{
26   -
27   -/*!
28   - * \ingroup transforms
29   - * \brief Colorspace conversion.
30   - * \author Josh Klontz \cite jklontz
31   - */
32   -class CvtTransform : public UntrainableTransform
33   -{
34   - Q_OBJECT
35   - Q_ENUMS(ColorSpace)
36   - Q_PROPERTY(ColorSpace colorSpace READ get_colorSpace WRITE set_colorSpace RESET reset_colorSpace STORED false)
37   - Q_PROPERTY(int channel READ get_channel WRITE set_channel RESET reset_channel STORED false)
38   -
39   -public:
40   - enum ColorSpace { Gray = CV_BGR2GRAY,
41   - RGBGray = CV_RGB2GRAY,
42   - HLS = CV_BGR2HLS,
43   - HSV = CV_BGR2HSV,
44   - Lab = CV_BGR2Lab,
45   - Luv = CV_BGR2Luv,
46   - RGB = CV_BGR2RGB,
47   - XYZ = CV_BGR2XYZ,
48   - YCrCb = CV_BGR2YCrCb,
49   - Color = CV_GRAY2BGR };
50   -
51   -private:
52   - BR_PROPERTY(ColorSpace, colorSpace, Gray)
53   - BR_PROPERTY(int, channel, -1)
54   -
55   - void project(const Template &src, Template &dst) const
56   - {
57   - if (src.m().channels() > 1 || colorSpace == CV_GRAY2BGR) cvtColor(src, dst, colorSpace);
58   - else dst = src;
59   -
60   - if (channel != -1) {
61   - std::vector<Mat> mv;
62   - split(dst, mv);
63   - dst = mv[channel % (int)mv.size()];
64   - }
65   - }
66   -};
67   -
68   -BR_REGISTER(Transform, CvtTransform)
69   -
70   -/*!
71   - * \ingroup transforms
72   - * \brief Convert to floating point format.
73   - * \author Josh Klontz \cite jklontz
74   - */
75   -class CvtFloatTransform : public UntrainableTransform
76   -{
77   - Q_OBJECT
78   -
79   - void project(const Template &src, Template &dst) const
80   - {
81   - src.m().convertTo(dst, CV_32F);
82   - }
83   -};
84   -
85   -BR_REGISTER(Transform, CvtFloatTransform)
86   -
87   -/*!
88   - * \ingroup transforms
89   - * \brief Convert to uchar format
90   - * \author Josh Klontz \cite jklontz
91   - */
92   -class CvtUCharTransform : public UntrainableTransform
93   -{
94   - Q_OBJECT
95   -
96   - void project(const Template &src, Template &dst) const
97   - {
98   - OpenCVUtils::cvtUChar(src, dst);
99   - }
100   -};
101   -
102   -BR_REGISTER(Transform, CvtUCharTransform)
103   -
104   -/*!
105   - * \ingroup transforms
106   - * \brief Scales using the given factor
107   - * \author Scott Klum \cite sklum
108   - */
109   -class ScaleTransform : public UntrainableTransform
110   -{
111   - Q_OBJECT
112   -
113   - Q_PROPERTY(float scaleFactor READ get_scaleFactor WRITE set_scaleFactor RESET reset_scaleFactor STORED false)
114   - BR_PROPERTY(float, scaleFactor, 1.)
115   -
116   - void project(const Template &src, Template &dst) const
117   - {
118   - resize(src, dst, Size(src.m().cols*scaleFactor,src.m().rows*scaleFactor));
119   - }
120   -};
121   -
122   -BR_REGISTER(Transform, ScaleTransform)
123   -
124   -/*!
125   - * \ingroup transforms
126   - * \brief Split a multi-channel matrix into several single-channel matrices.
127   - * \author Josh Klontz \cite jklontz
128   - */
129   -class SplitChannelsTransform : public UntrainableTransform
130   -{
131   - Q_OBJECT
132   -
133   - void project(const Template &src, Template &dst) const
134   - {
135   - std::vector<Mat> mv;
136   - split(src, mv);
137   - foreach (const Mat &m, mv)
138   - dst += m;
139   - }
140   -};
141   -
142   -BR_REGISTER(Transform, SplitChannelsTransform)
143   -
144   -/*!
145   - * \ingroup transforms
146   - * \brief Enforce the matrix has a certain number of channels by adding or removing channels.
147   - * \author Josh Klontz \cite jklontz
148   - */
149   -class EnsureChannelsTransform : public UntrainableTransform
150   -{
151   - Q_OBJECT
152   - Q_PROPERTY(int n READ get_n WRITE set_n RESET reset_n STORED false)
153   - BR_PROPERTY(int, n, 1)
154   -
155   - void project(const Template &src, Template &dst) const
156   - {
157   - if (src.m().channels() == n) {
158   - dst = src;
159   - } else {
160   - std::vector<Mat> mv;
161   - split(src, mv);
162   -
163   - // Add extra channels
164   - while ((int)mv.size() < n) {
165   - for (int i=0; i<src.m().channels(); i++) {
166   - mv.push_back(mv[i]);
167   - if ((int)mv.size() == n)
168   - break;
169   - }
170   - }
171   -
172   - // Remove extra channels
173   - while ((int)mv.size() > n)
174   - mv.pop_back();
175   -
176   - merge(mv, dst);
177   - }
178   - }
179   -};
180   -
181   -BR_REGISTER(Transform, EnsureChannelsTransform)
182   -
183   -/*!
184   - * \ingroup transforms
185   - * \brief Drop the alpha channel (if exists).
186   - * \author Austin Blanton \cite imaus10
187   - */
188   -class DiscardAlphaTransform : public UntrainableTransform
189   -{
190   - Q_OBJECT
191   -
192   - void project(const Template &src, Template &dst) const
193   - {
194   - if (src.m().channels() > 4 || src.m().channels() == 2) {
195   - dst.file.fte = true;
196   - return;
197   - }
198   -
199   - dst = src;
200   - if (src.m().channels() == 4) {
201   - std::vector<Mat> mv;
202   - split(src, mv);
203   - mv.pop_back();
204   - merge(mv, dst);
205   - }
206   - }
207   -};
208   -
209   -BR_REGISTER(Transform, DiscardAlphaTransform)
210   -
211   -/*!
212   - * \ingroup transforms
213   - * \brief Normalized RG color space.
214   - * \author Josh Klontz \cite jklontz
215   - */
216   -class RGTransform : public UntrainableTransform
217   -{
218   - Q_OBJECT
219   -
220   - void project(const Template &src, Template &dst) const
221   - {
222   - if (src.m().type() != CV_8UC3)
223   - qFatal("Expected CV_8UC3 images.");
224   -
225   - const Mat &m = src.m();
226   - Mat R(m.size(), CV_8UC1); // R / (R+G+B)
227   - Mat G(m.size(), CV_8UC1); // G / (R+G+B)
228   -
229   - for (int i=0; i<m.rows; i++)
230   - for (int j=0; j<m.cols; j++) {
231   - Vec3b v = m.at<Vec3b>(i,j);
232   - const int b = v[0];
233   - const int g = v[1];
234   - const int r = v[2];
235   - const int sum = b + g + r;
236   - if (sum > 0) {
237   - R.at<uchar>(i, j) = saturate_cast<uchar>(255.0*r/(r+g+b));
238   - G.at<uchar>(i, j) = saturate_cast<uchar>(255.0*g/(r+g+b));
239   - } else {
240   - R.at<uchar>(i, j) = 0;
241   - G.at<uchar>(i, j) = 0;
242   - }
243   - }
244   -
245   - dst.append(R);
246   - dst.append(G);
247   - }
248   -};
249   -
250   -BR_REGISTER(Transform, RGTransform)
251   -
252   -/*!
253   - * \ingroup transforms
254   - * \brief dst = a*src+b
255   - * \author Josh Klontz \cite jklontz
256   - */
257   -class MAddTransform : public UntrainableTransform
258   -{
259   - Q_OBJECT
260   - Q_PROPERTY(double a READ get_a WRITE set_a RESET reset_a STORED false)
261   - Q_PROPERTY(double b READ get_b WRITE set_b RESET reset_b STORED false)
262   - BR_PROPERTY(double, a, 1)
263   - BR_PROPERTY(double, b, 0)
264   -
265   - void project(const Template &src, Template &dst) const
266   - {
267   - src.m().convertTo(dst.m(), src.m().depth(), a, b);
268   - }
269   -};
270   -
271   -BR_REGISTER(Transform, MAddTransform)
272   -
273   -/*!
274   - * \ingroup transforms
275   - * \brief Computes the absolute value of each element.
276   - * \author Josh Klontz \cite jklontz
277   - */
278   -class AbsTransform : public UntrainableTransform
279   -{
280   - Q_OBJECT
281   -
282   - void project(const Template &src, Template &dst) const
283   - {
284   - dst = abs(src);
285   - }
286   -};
287   -
288   -BR_REGISTER(Transform, AbsTransform)
289   -
290   -} // namespace br
291   -
292   -#include "cvt.moc"
openbr/plugins/cascade.cpp renamed to openbr/plugins/detection/cascade.cpp
... ... @@ -15,7 +15,7 @@
15 15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 16  
17 17 #include <opencv2/objdetect/objdetect.hpp>
18   -#include "openbr_internal.h"
  18 +#include <openbr/plugins/openbr_internal.h>
19 19 #include "openbr/core/opencvutils.h"
20 20 #include "openbr/core/resource.h"
21 21 #include "openbr/core/qtutils.h"
... ...
openbr/plugins/eyes.cpp renamed to openbr/plugins/detection/eyes.cpp
... ... @@ -35,8 +35,9 @@
35 35  
36 36 #include <opencv2/imgproc/imgproc.hpp>
37 37 #include <opencv2/imgproc/imgproc_c.h>
38   -#include "openbr_internal.h"
39   -#include "openbr/core/opencvutils.h"
  38 +
  39 +#include <openbr/plugins/openbr_internal.h>
  40 +#include <openbr/core/opencvutils.h>
40 41  
41 42 using namespace cv;
42 43  
... ...
openbr/plugins/detection/keypointdetector.cpp 0 → 100644
  1 +#include <opencv2/features2d/features2d.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +#include <openbr/core/opencvutils.h>
  5 +
  6 +using namespace cv;
  7 +
  8 +namespace br
  9 +{
  10 +
  11 +/*!
  12 + * \ingroup transforms
  13 + * \brief Wraps OpenCV Key Point Detector
  14 + * \author Josh Klontz \cite jklontz
  15 + */
  16 +class KeyPointDetectorTransform : public UntrainableTransform
  17 +{
  18 + Q_OBJECT
  19 + Q_PROPERTY(QString detector READ get_detector WRITE set_detector RESET reset_detector STORED false)
  20 + BR_PROPERTY(QString, detector, "SIFT")
  21 +
  22 + Ptr<FeatureDetector> featureDetector;
  23 +
  24 + void init()
  25 + {
  26 + featureDetector = FeatureDetector::create(detector.toStdString());
  27 + if (featureDetector.empty())
  28 + qFatal("Failed to create KeyPointDetector: %s", qPrintable(detector));
  29 + }
  30 +
  31 + void project(const Template &src, Template &dst) const
  32 + {
  33 + dst = src;
  34 +
  35 + std::vector<KeyPoint> keyPoints;
  36 + try {
  37 + featureDetector->detect(src, keyPoints);
  38 + } catch (...) {
  39 + qWarning("Key point detection failed for file %s", qPrintable(src.file.name));
  40 + dst.file.fte = true;
  41 + }
  42 +
  43 + QList<Rect> rects;
  44 + foreach (const KeyPoint &keyPoint, keyPoints)
  45 + rects.append(Rect(keyPoint.pt.x-keyPoint.size/2, keyPoint.pt.y-keyPoint.size/2, keyPoint.size, keyPoint.size));
  46 + dst.file.setRects(OpenCVUtils::fromRects(rects));
  47 + }
  48 +};
  49 +
  50 +BR_REGISTER(Transform, KeyPointDetectorTransform)
  51 +
  52 +} // namespace br
  53 +
  54 +#include "keypointdetector.moc"
... ...
openbr/plugins/distance.cpp deleted
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 <QFutureSynchronizer>
18   -#include <QtConcurrentRun>
19   -#include <numeric>
20   -#include <opencv2/imgproc/imgproc.hpp>
21   -#include <opencv2/imgproc/imgproc_c.h>
22   -#include "openbr_internal.h"
23   -
24   -#include "openbr/core/distance_sse.h"
25   -#include "openbr/core/qtutils.h"
26   -#include "openbr/core/opencvutils.h"
27   -
28   -using namespace cv;
29   -
30   -namespace br
31   -{
32   -
33   -/*!
34   - * \ingroup distances
35   - * \brief Standard distance metrics
36   - * \author Josh Klontz \cite jklontz
37   - */
38   -class DistDistance : public UntrainableDistance
39   -{
40   - Q_OBJECT
41   - Q_ENUMS(Metric)
42   - Q_PROPERTY(Metric metric READ get_metric WRITE set_metric RESET reset_metric STORED false)
43   - Q_PROPERTY(bool negLogPlusOne READ get_negLogPlusOne WRITE set_negLogPlusOne RESET reset_negLogPlusOne STORED false)
44   -
45   -public:
46   - /*!< */
47   - enum Metric { Correlation,
48   - ChiSquared,
49   - Intersection,
50   - Bhattacharyya,
51   - INF,
52   - L1,
53   - L2,
54   - Cosine,
55   - Dot};
56   -
57   -private:
58   - BR_PROPERTY(Metric, metric, L2)
59   - BR_PROPERTY(bool, negLogPlusOne, true)
60   -
61   - float compare(const Mat &a, const Mat &b) const
62   - {
63   - if ((a.size != b.size) ||
64   - (a.type() != b.type()))
65   - return -std::numeric_limits<float>::max();
66   -
67   -// TODO: this max value is never returned based on the switch / default
68   - float result = std::numeric_limits<float>::max();
69   - switch (metric) {
70   - case Correlation:
71   - return compareHist(a, b, CV_COMP_CORREL);
72   - case ChiSquared:
73   - result = compareHist(a, b, CV_COMP_CHISQR);
74   - break;
75   - case Intersection:
76   - result = compareHist(a, b, CV_COMP_INTERSECT);
77   - break;
78   - case Bhattacharyya:
79   - result = compareHist(a, b, CV_COMP_BHATTACHARYYA);
80   - break;
81   - case INF:
82   - result = norm(a, b, NORM_INF);
83   - break;
84   - case L1:
85   - result = norm(a, b, NORM_L1);
86   - break;
87   - case L2:
88   - result = norm(a, b, NORM_L2);
89   - break;
90   - case Cosine:
91   - return cosine(a, b);
92   - case Dot:
93   - return a.dot(b);
94   - default:
95   - qFatal("Invalid metric");
96   - }
97   -
98   - if (result != result)
99   - qFatal("NaN result.");
100   -
101   - return negLogPlusOne ? -log(result+1) : result;
102   - }
103   -
104   - static float cosine(const Mat &a, const Mat &b)
105   - {
106   - float dot = 0;
107   - float magA = 0;
108   - float magB = 0;
109   -
110   - for (int row=0; row<a.rows; row++) {
111   - for (int col=0; col<a.cols; col++) {
112   - const float target = a.at<float>(row,col);
113   - const float query = b.at<float>(row,col);
114   - dot += target * query;
115   - magA += target * target;
116   - magB += query * query;
117   - }
118   - }
119   -
120   - return dot / (sqrt(magA)*sqrt(magB));
121   - }
122   -};
123   -
124   -BR_REGISTER(Distance, DistDistance)
125   -
126   -/*!
127   - * \ingroup distances
128   - * \brief DistDistance wrapper.
129   - * \author Josh Klontz \cite jklontz
130   - */
131   -class DefaultDistance : public UntrainableDistance
132   -{
133   - Q_OBJECT
134   - Distance *distance;
135   -
136   - void init()
137   - {
138   - distance = Distance::make("Dist("+file.suffix()+")");
139   - }
140   -
141   - float compare(const cv::Mat &a, const cv::Mat &b) const
142   - {
143   - return distance->compare(a, b);
144   - }
145   -};
146   -
147   -BR_REGISTER(Distance, DefaultDistance)
148   -
149   -/*!
150   - * \ingroup distances
151   - * \brief Distances in series.
152   - * \author Josh Klontz \cite jklontz
153   - *
154   - * The templates are compared using each br::Distance in order.
155   - * If the result of the comparison with any given distance is -FLOAT_MAX then this result is returned early.
156   - * Otherwise the returned result is the value of comparing the templates using the last br::Distance.
157   - */
158   -class PipeDistance : public Distance
159   -{
160   - Q_OBJECT
161   - Q_PROPERTY(QList<br::Distance*> distances READ get_distances WRITE set_distances RESET reset_distances)
162   - BR_PROPERTY(QList<br::Distance*>, distances, QList<br::Distance*>())
163   -
164   - void train(const TemplateList &data)
165   - {
166   - QFutureSynchronizer<void> futures;
167   - foreach (br::Distance *distance, distances)
168   - futures.addFuture(QtConcurrent::run(distance, &Distance::train, data));
169   - futures.waitForFinished();
170   - }
171   -
172   - float compare(const Template &a, const Template &b) const
173   - {
174   - float result = -std::numeric_limits<float>::max();
175   - foreach (br::Distance *distance, distances) {
176   - result = distance->compare(a, b);
177   - if (result == -std::numeric_limits<float>::max())
178   - return result;
179   - }
180   - return result;
181   - }
182   -};
183   -
184   -BR_REGISTER(Distance, PipeDistance)
185   -
186   -/*!
187   - * \ingroup distances
188   - * \brief Fuses similarity scores across multiple matrices of compared templates
189   - * \author Scott Klum \cite sklum
190   - * \note Operation: Mean, sum, min, max are supported.
191   - */
192   -class FuseDistance : public Distance
193   -{
194   - Q_OBJECT
195   - Q_ENUMS(Operation)
196   - Q_PROPERTY(QString description READ get_description WRITE set_description RESET reset_description STORED false)
197   - Q_PROPERTY(Operation operation READ get_operation WRITE set_operation RESET reset_operation STORED false)
198   - Q_PROPERTY(QList<float> weights READ get_weights WRITE set_weights RESET reset_weights STORED false)
199   -
200   - QList<br::Distance*> distances;
201   -
202   -public:
203   - /*!< */
204   - enum Operation {Mean, Sum, Max, Min};
205   -
206   -private:
207   - BR_PROPERTY(QString, description, "L2")
208   - BR_PROPERTY(Operation, operation, Mean)
209   - BR_PROPERTY(QList<float>, weights, QList<float>())
210   -
211   - void train(const TemplateList &src)
212   - {
213   - // Partition the templates by matrix
214   - QList<int> split;
215   - for (int i=0; i<src.at(0).size(); i++) split.append(1);
216   -
217   - QList<TemplateList> partitionedSrc = src.partition(split);
218   -
219   - while (distances.size() < partitionedSrc.size())
220   - distances.append(make(description));
221   -
222   - // Train on each of the partitions
223   - for (int i=0; i<distances.size(); i++)
224   - distances[i]->train(partitionedSrc[i]);
225   - }
226   -
227   - float compare(const Template &a, const Template &b) const
228   - {
229   - if (a.size() != b.size()) qFatal("Comparison size mismatch");
230   -
231   - QList<float> scores;
232   - for (int i=0; i<distances.size(); i++) {
233   - float weight;
234   - weights.isEmpty() ? weight = 1. : weight = weights[i];
235   - scores.append(weight*distances[i]->compare(Template(a.file, a[i]),Template(b.file, b[i])));
236   - }
237   -
238   - switch (operation) {
239   - case Mean:
240   - return std::accumulate(scores.begin(),scores.end(),0.0)/(float)scores.size();
241   - break;
242   - case Sum:
243   - return std::accumulate(scores.begin(),scores.end(),0.0);
244   - break;
245   - case Min:
246   - return *std::min_element(scores.begin(),scores.end());
247   - break;
248   - case Max:
249   - return *std::max_element(scores.begin(),scores.end());
250   - break;
251   - default:
252   - qFatal("Invalid operation.");
253   - }
254   - return 0;
255   - }
256   -
257   - void store(QDataStream &stream) const
258   - {
259   - stream << distances.size();
260   - foreach (Distance *distance, distances)
261   - distance->store(stream);
262   - }
263   -
264   - void load(QDataStream &stream)
265   - {
266   - int numDistances;
267   - stream >> numDistances;
268   - while (distances.size() < numDistances)
269   - distances.append(make(description));
270   - foreach (Distance *distance, distances)
271   - distance->load(stream);
272   - }
273   -};
274   -
275   -BR_REGISTER(Distance, FuseDistance)
276   -
277   -/*!
278   - * \ingroup distances
279   - * \brief Fast 8-bit L1 distance
280   - * \author Josh Klontz \cite jklontz
281   - */
282   -class ByteL1Distance : public UntrainableDistance
283   -{
284   - Q_OBJECT
285   -
286   - float compare(const unsigned char *a, const unsigned char *b, size_t size) const
287   - {
288   - return l1(a, b, size);
289   - }
290   -};
291   -
292   -BR_REGISTER(Distance, ByteL1Distance)
293   -
294   -/*!
295   - * \ingroup distances
296   - * \brief Fast 4-bit L1 distance
297   - * \author Josh Klontz \cite jklontz
298   - */
299   -class HalfByteL1Distance : public UntrainableDistance
300   -{
301   - Q_OBJECT
302   -
303   - float compare(const Mat &a, const Mat &b) const
304   - {
305   - return packed_l1(a.data, b.data, a.total());
306   - }
307   -};
308   -
309   -BR_REGISTER(Distance, HalfByteL1Distance)
310   -
311   -/*!
312   - * \ingroup distances
313   - * \brief Returns -log(distance(a,b)+1)
314   - * \author Josh Klontz \cite jklontz
315   - */
316   -class NegativeLogPlusOneDistance : public UntrainableDistance
317   -{
318   - Q_OBJECT
319   - Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
320   - BR_PROPERTY(br::Distance*, distance, NULL)
321   -
322   - void train(const TemplateList &src)
323   - {
324   - distance->train(src);
325   - }
326   -
327   - float compare(const Template &a, const Template &b) const
328   - {
329   - return -log(distance->compare(a,b)+1);
330   - }
331   -
332   - void store(QDataStream &stream) const
333   - {
334   - distance->store(stream);
335   - }
336   -
337   - void load(QDataStream &stream)
338   - {
339   - distance->load(stream);
340   - }
341   -};
342   -
343   -BR_REGISTER(Distance, NegativeLogPlusOneDistance)
344   -
345   -/*!
346   - * \ingroup distances
347   - * \brief Returns \c true if the templates are identical, \c false otherwise.
348   - * \author Josh Klontz \cite jklontz
349   - */
350   -class IdenticalDistance : public UntrainableDistance
351   -{
352   - Q_OBJECT
353   -
354   - float compare(const Mat &a, const Mat &b) const
355   - {
356   - const size_t size = a.total() * a.elemSize();
357   - if (size != b.total() * b.elemSize()) return 0;
358   - for (size_t i=0; i<size; i++)
359   - if (a.data[i] != b.data[i]) return 0;
360   - return 1;
361   - }
362   -};
363   -
364   -BR_REGISTER(Distance, IdenticalDistance)
365   -
366   -/*!
367   - * \ingroup distances
368   - * \brief Online distance metric to attenuate match scores across multiple frames
369   - * \author Brendan klare \cite bklare
370   - */
371   -class OnlineDistance : public UntrainableDistance
372   -{
373   - Q_OBJECT
374   - Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
375   - Q_PROPERTY(float alpha READ get_alpha WRITE set_alpha RESET reset_alpha STORED false)
376   - BR_PROPERTY(br::Distance*, distance, NULL)
377   - BR_PROPERTY(float, alpha, 0.1f)
378   -
379   - mutable QHash<QString,float> scoreHash;
380   - mutable QMutex mutex;
381   -
382   - float compare(const Template &target, const Template &query) const
383   - {
384   - float currentScore = distance->compare(target, query);
385   -
386   - QMutexLocker mutexLocker(&mutex);
387   - return scoreHash[target.file.name] = (1.0- alpha) * scoreHash[target.file.name] + alpha * currentScore;
388   - }
389   -};
390   -
391   -BR_REGISTER(Distance, OnlineDistance)
392   -
393   -/*!
394   - * \ingroup distances
395   - * \brief Attenuation function based distance from attributes
396   - * \author Scott Klum \cite sklum
397   - */
398   -class AttributeDistance : public UntrainableDistance
399   -{
400   - Q_OBJECT
401   - Q_PROPERTY(QString attribute READ get_attribute WRITE set_attribute RESET reset_attribute STORED false)
402   - BR_PROPERTY(QString, attribute, QString())
403   -
404   - float compare(const Template &target, const Template &query) const
405   - {
406   - float queryValue = query.file.get<float>(attribute);
407   - float targetValue = target.file.get<float>(attribute);
408   -
409   - // TODO: Set this magic number to something meaningful
410   - float stddev = 1;
411   -
412   - if (queryValue == targetValue) return 1;
413   - else return 1/(stddev*sqrt(2*CV_PI))*exp(-0.5*pow((targetValue-queryValue)/stddev, 2));
414   - }
415   -};
416   -
417   -BR_REGISTER(Distance, AttributeDistance)
418   -
419   -/*!
420   - * \ingroup distances
421   - * \brief Sum match scores across multiple distances
422   - * \author Scott Klum \cite sklum
423   - */
424   -class SumDistance : public UntrainableDistance
425   -{
426   - Q_OBJECT
427   - Q_PROPERTY(QList<br::Distance*> distances READ get_distances WRITE set_distances RESET reset_distances)
428   - BR_PROPERTY(QList<br::Distance*>, distances, QList<br::Distance*>())
429   -
430   - void train(const TemplateList &data)
431   - {
432   - QFutureSynchronizer<void> futures;
433   - foreach (br::Distance *distance, distances)
434   - futures.addFuture(QtConcurrent::run(distance, &Distance::train, data));
435   - futures.waitForFinished();
436   - }
437   -
438   - float compare(const Template &target, const Template &query) const
439   - {
440   - float result = 0;
441   -
442   - foreach (br::Distance *distance, distances) {
443   - result += distance->compare(target, query);
444   -
445   - if (result == -std::numeric_limits<float>::max())
446   - return result;
447   - }
448   -
449   - return result;
450   - }
451   -};
452   -
453   -BR_REGISTER(Distance, SumDistance)
454   -
455   -/*!
456   - * \ingroup transforms
457   - * \brief Compare each template to a fixed gallery (with name = galleryName), using the specified distance.
458   - * dst will contain a 1 by n vector of scores.
459   - * \author Charles Otto \cite caotto
460   - */
461   -class GalleryCompareTransform : public Transform
462   -{
463   - Q_OBJECT
464   - Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance STORED true)
465   - Q_PROPERTY(QString galleryName READ get_galleryName WRITE set_galleryName RESET reset_galleryName STORED false)
466   - BR_PROPERTY(br::Distance*, distance, NULL)
467   - BR_PROPERTY(QString, galleryName, "")
468   -
469   - TemplateList gallery;
470   -
471   - void project(const Template &src, Template &dst) const
472   - {
473   - dst = src;
474   - if (gallery.isEmpty())
475   - return;
476   -
477   - QList<float> line = distance->compare(gallery, src);
478   - dst.m() = OpenCVUtils::toMat(line, 1);
479   - }
480   -
481   - void init()
482   - {
483   - if (!galleryName.isEmpty())
484   - gallery = TemplateList::fromGallery(galleryName);
485   - }
486   -
487   - void train(const TemplateList &data)
488   - {
489   - gallery = data;
490   - }
491   -
492   - void store(QDataStream &stream) const
493   - {
494   - br::Object::store(stream);
495   - stream << gallery;
496   - }
497   -
498   - void load(QDataStream &stream)
499   - {
500   - br::Object::load(stream);
501   - stream >> gallery;
502   - }
503   -
504   -public:
505   - GalleryCompareTransform() : Transform(false, true) {}
506   -};
507   -
508   -BR_REGISTER(Transform, GalleryCompareTransform)
509   -
510   -
511   -} // namespace br
512   -#include "distance.moc"
openbr/plugins/distance/L2.cpp 0 → 100644
  1 +#include <Eigen/Dense>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup distances
  10 + * \brief L2 distance computed using eigen.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class L2Distance : public UntrainableDistance
  14 +{
  15 + Q_OBJECT
  16 +
  17 + float compare(const cv::Mat &a, const cv::Mat &b) const
  18 + {
  19 + const int size = a.rows * a.cols;
  20 + Eigen::Map<Eigen::VectorXf> aMap((float*)a.data, size);
  21 + Eigen::Map<Eigen::VectorXf> bMap((float*)b.data, size);
  22 + return (aMap-bMap).squaredNorm();
  23 + }
  24 +};
  25 +
  26 +BR_REGISTER(Distance, L2Distance)
  27 +
  28 +} // namespace br
  29 +
  30 +#include "L2.moc"
... ...
openbr/plugins/distance/attribute.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup distances
  8 + * \brief Attenuation function based distance from attributes
  9 + * \author Scott Klum \cite sklum
  10 + */
  11 +class AttributeDistance : public UntrainableDistance
  12 +{
  13 + Q_OBJECT
  14 + Q_PROPERTY(QString attribute READ get_attribute WRITE set_attribute RESET reset_attribute STORED false)
  15 + BR_PROPERTY(QString, attribute, QString())
  16 +
  17 + float compare(const Template &target, const Template &query) const
  18 + {
  19 + float queryValue = query.file.get<float>(attribute);
  20 + float targetValue = target.file.get<float>(attribute);
  21 +
  22 + // TODO: Set this magic number to something meaningful
  23 + float stddev = 1;
  24 +
  25 + if (queryValue == targetValue) return 1;
  26 + else return 1/(stddev*sqrt(2*CV_PI))*exp(-0.5*pow((targetValue-queryValue)/stddev, 2));
  27 + }
  28 +};
  29 +
  30 +BR_REGISTER(Distance, AttributeDistance)
  31 +
  32 +} // namespace br
  33 +
  34 +#include "attribute.moc"
... ...
openbr/plugins/distance/byteL1.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/distance_sse.h>
  3 +
  4 +namespace br
  5 +{
  6 +
  7 +/*!
  8 + * \ingroup distances
  9 + * \brief Fast 8-bit L1 distance
  10 + * \author Josh Klontz \cite jklontz
  11 + */
  12 +class ByteL1Distance : public UntrainableDistance
  13 +{
  14 + Q_OBJECT
  15 +
  16 + float compare(const unsigned char *a, const unsigned char *b, size_t size) const
  17 + {
  18 + return l1(a, b, size);
  19 + }
  20 +};
  21 +
  22 +BR_REGISTER(Distance, ByteL1Distance)
  23 +
  24 +} // namespace br
  25 +
  26 +#include "byteL1.moc"
... ...
openbr/plugins/distance/default.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup distances
  8 + * \brief DistDistance wrapper.
  9 + * \author Josh Klontz \cite jklontz
  10 + */
  11 +class DefaultDistance : public UntrainableDistance
  12 +{
  13 + Q_OBJECT
  14 + Distance *distance;
  15 +
  16 + void init()
  17 + {
  18 + distance = Distance::make("Dist("+file.suffix()+")");
  19 + }
  20 +
  21 + float compare(const cv::Mat &a, const cv::Mat &b) const
  22 + {
  23 + return distance->compare(a, b);
  24 + }
  25 +};
  26 +
  27 +BR_REGISTER(Distance, DefaultDistance)
  28 +
  29 +} // namespace br
  30 +
  31 +#include "default.moc"
... ...
openbr/plugins/distance/dist.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +#include <openbr/plugins/openbr_internal.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup distances
  11 + * \brief Standard distance metrics
  12 + * \author Josh Klontz \cite jklontz
  13 + */
  14 +class DistDistance : public UntrainableDistance
  15 +{
  16 + Q_OBJECT
  17 + Q_ENUMS(Metric)
  18 + Q_PROPERTY(Metric metric READ get_metric WRITE set_metric RESET reset_metric STORED false)
  19 + Q_PROPERTY(bool negLogPlusOne READ get_negLogPlusOne WRITE set_negLogPlusOne RESET reset_negLogPlusOne STORED false)
  20 +
  21 +public:
  22 + /*!< */
  23 + enum Metric { Correlation,
  24 + ChiSquared,
  25 + Intersection,
  26 + Bhattacharyya,
  27 + INF,
  28 + L1,
  29 + L2,
  30 + Cosine,
  31 + Dot};
  32 +
  33 +private:
  34 + BR_PROPERTY(Metric, metric, L2)
  35 + BR_PROPERTY(bool, negLogPlusOne, true)
  36 +
  37 + float compare(const Mat &a, const Mat &b) const
  38 + {
  39 + if ((a.size != b.size) ||
  40 + (a.type() != b.type()))
  41 + return -std::numeric_limits<float>::max();
  42 +
  43 +// TODO: this max value is never returned based on the switch / default
  44 + float result = std::numeric_limits<float>::max();
  45 + switch (metric) {
  46 + case Correlation:
  47 + return compareHist(a, b, CV_COMP_CORREL);
  48 + case ChiSquared:
  49 + result = compareHist(a, b, CV_COMP_CHISQR);
  50 + break;
  51 + case Intersection:
  52 + result = compareHist(a, b, CV_COMP_INTERSECT);
  53 + break;
  54 + case Bhattacharyya:
  55 + result = compareHist(a, b, CV_COMP_BHATTACHARYYA);
  56 + break;
  57 + case INF:
  58 + result = norm(a, b, NORM_INF);
  59 + break;
  60 + case L1:
  61 + result = norm(a, b, NORM_L1);
  62 + break;
  63 + case L2:
  64 + result = norm(a, b, NORM_L2);
  65 + break;
  66 + case Cosine:
  67 + return cosine(a, b);
  68 + case Dot:
  69 + return a.dot(b);
  70 + default:
  71 + qFatal("Invalid metric");
  72 + }
  73 +
  74 + if (result != result)
  75 + qFatal("NaN result.");
  76 +
  77 + return negLogPlusOne ? -log(result+1) : result;
  78 + }
  79 +
  80 + static float cosine(const Mat &a, const Mat &b)
  81 + {
  82 + float dot = 0;
  83 + float magA = 0;
  84 + float magB = 0;
  85 +
  86 + for (int row=0; row<a.rows; row++) {
  87 + for (int col=0; col<a.cols; col++) {
  88 + const float target = a.at<float>(row,col);
  89 + const float query = b.at<float>(row,col);
  90 + dot += target * query;
  91 + magA += target * target;
  92 + magB += query * query;
  93 + }
  94 + }
  95 +
  96 + return dot / (sqrt(magA)*sqrt(magB));
  97 + }
  98 +};
  99 +
  100 +BR_REGISTER(Distance, DistDistance)
  101 +
  102 +} // namespace br
  103 +
  104 +#include "dist.moc"
... ...
openbr/plugins/distance/fuse.cpp 0 → 100644
  1 +#include <numeric>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup distances
  10 + * \brief Fuses similarity scores across multiple matrices of compared templates
  11 + * \author Scott Klum \cite sklum
  12 + * \note Operation: Mean, sum, min, max are supported.
  13 + */
  14 +class FuseDistance : public Distance
  15 +{
  16 + Q_OBJECT
  17 + Q_ENUMS(Operation)
  18 + Q_PROPERTY(QString description READ get_description WRITE set_description RESET reset_description STORED false)
  19 + Q_PROPERTY(Operation operation READ get_operation WRITE set_operation RESET reset_operation STORED false)
  20 + Q_PROPERTY(QList<float> weights READ get_weights WRITE set_weights RESET reset_weights STORED false)
  21 +
  22 + QList<br::Distance*> distances;
  23 +
  24 +public:
  25 + /*!< */
  26 + enum Operation {Mean, Sum, Max, Min};
  27 +
  28 +private:
  29 + BR_PROPERTY(QString, description, "L2")
  30 + BR_PROPERTY(Operation, operation, Mean)
  31 + BR_PROPERTY(QList<float>, weights, QList<float>())
  32 +
  33 + void train(const TemplateList &src)
  34 + {
  35 + // Partition the templates by matrix
  36 + QList<int> split;
  37 + for (int i=0; i<src.at(0).size(); i++) split.append(1);
  38 +
  39 + QList<TemplateList> partitionedSrc = src.partition(split);
  40 +
  41 + while (distances.size() < partitionedSrc.size())
  42 + distances.append(make(description));
  43 +
  44 + // Train on each of the partitions
  45 + for (int i=0; i<distances.size(); i++)
  46 + distances[i]->train(partitionedSrc[i]);
  47 + }
  48 +
  49 + float compare(const Template &a, const Template &b) const
  50 + {
  51 + if (a.size() != b.size()) qFatal("Comparison size mismatch");
  52 +
  53 + QList<float> scores;
  54 + for (int i=0; i<distances.size(); i++) {
  55 + float weight;
  56 + weights.isEmpty() ? weight = 1. : weight = weights[i];
  57 + scores.append(weight*distances[i]->compare(Template(a.file, a[i]),Template(b.file, b[i])));
  58 + }
  59 +
  60 + switch (operation) {
  61 + case Mean:
  62 + return std::accumulate(scores.begin(),scores.end(),0.0)/(float)scores.size();
  63 + break;
  64 + case Sum:
  65 + return std::accumulate(scores.begin(),scores.end(),0.0);
  66 + break;
  67 + case Min:
  68 + return *std::min_element(scores.begin(),scores.end());
  69 + break;
  70 + case Max:
  71 + return *std::max_element(scores.begin(),scores.end());
  72 + break;
  73 + default:
  74 + qFatal("Invalid operation.");
  75 + }
  76 + return 0;
  77 + }
  78 +
  79 + void store(QDataStream &stream) const
  80 + {
  81 + stream << distances.size();
  82 + foreach (Distance *distance, distances)
  83 + distance->store(stream);
  84 + }
  85 +
  86 + void load(QDataStream &stream)
  87 + {
  88 + int numDistances;
  89 + stream >> numDistances;
  90 + while (distances.size() < numDistances)
  91 + distances.append(make(description));
  92 + foreach (Distance *distance, distances)
  93 + distance->load(stream);
  94 + }
  95 +};
  96 +
  97 +BR_REGISTER(Distance, FuseDistance)
  98 +
  99 +} // namespace br
  100 +
  101 +#include "fuse.moc"
... ...
openbr/plugins/distance/gallerycompare.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
  3 +
  4 +namespace br
  5 +{
  6 +
  7 +/*!
  8 + * \ingroup transforms
  9 + * \brief Compare each template to a fixed gallery (with name = galleryName), using the specified distance.
  10 + * dst will contain a 1 by n vector of scores.
  11 + * \author Charles Otto \cite caotto
  12 + */
  13 +class GalleryCompareTransform : public Transform
  14 +{
  15 + Q_OBJECT
  16 + Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance STORED true)
  17 + Q_PROPERTY(QString galleryName READ get_galleryName WRITE set_galleryName RESET reset_galleryName STORED false)
  18 + BR_PROPERTY(br::Distance*, distance, NULL)
  19 + BR_PROPERTY(QString, galleryName, "")
  20 +
  21 + TemplateList gallery;
  22 +
  23 + void project(const Template &src, Template &dst) const
  24 + {
  25 + dst = src;
  26 + if (gallery.isEmpty())
  27 + return;
  28 +
  29 + QList<float> line = distance->compare(gallery, src);
  30 + dst.m() = OpenCVUtils::toMat(line, 1);
  31 + }
  32 +
  33 + void init()
  34 + {
  35 + if (!galleryName.isEmpty())
  36 + gallery = TemplateList::fromGallery(galleryName);
  37 + }
  38 +
  39 + void train(const TemplateList &data)
  40 + {
  41 + gallery = data;
  42 + }
  43 +
  44 + void store(QDataStream &stream) const
  45 + {
  46 + br::Object::store(stream);
  47 + stream << gallery;
  48 + }
  49 +
  50 + void load(QDataStream &stream)
  51 + {
  52 + br::Object::load(stream);
  53 + stream >> gallery;
  54 + }
  55 +
  56 +public:
  57 + GalleryCompareTransform() : Transform(false, true) {}
  58 +};
  59 +
  60 +BR_REGISTER(Transform, GalleryCompareTransform)
  61 +
  62 +} // namespace br
  63 +
  64 +#include "gallerycompare.moc"
... ...
openbr/plugins/distance/halfbyteL1.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/distance_sse.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup distances
  11 + * \brief Fast 4-bit L1 distance
  12 + * \author Josh Klontz \cite jklontz
  13 + */
  14 +class HalfByteL1Distance : public UntrainableDistance
  15 +{
  16 + Q_OBJECT
  17 +
  18 + float compare(const Mat &a, const Mat &b) const
  19 + {
  20 + return packed_l1(a.data, b.data, a.total());
  21 + }
  22 +};
  23 +
  24 +BR_REGISTER(Distance, HalfByteL1Distance)
  25 +
  26 +
  27 +} // namespace br
  28 +
  29 +#include "halfbyteL1.moc"
... ...
openbr/plugins/distance/identical.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup distances
  10 + * \brief Returns \c true if the templates are identical, \c false otherwise.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class IdenticalDistance : public UntrainableDistance
  14 +{
  15 + Q_OBJECT
  16 +
  17 + float compare(const Mat &a, const Mat &b) const
  18 + {
  19 + const size_t size = a.total() * a.elemSize();
  20 + if (size != b.total() * b.elemSize()) return 0;
  21 + for (size_t i=0; i<size; i++)
  22 + if (a.data[i] != b.data[i]) return 0;
  23 + return 1;
  24 + }
  25 +};
  26 +
  27 +BR_REGISTER(Distance, IdenticalDistance)
  28 +
  29 +} // namespace br
  30 +
  31 +#include "identical.moc"
... ...
openbr/plugins/distance/keypointmatcher.cpp 0 → 100644
  1 +#include <opencv2/features2d/features2d.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Wraps OpenCV Key Point Matcher
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class KeyPointMatcherDistance : public UntrainableDistance
  16 +{
  17 + Q_OBJECT
  18 + Q_PROPERTY(QString matcher READ get_matcher WRITE set_matcher RESET reset_matcher STORED false)
  19 + Q_PROPERTY(float maxRatio READ get_maxRatio WRITE set_maxRatio RESET reset_maxRatio STORED false)
  20 + BR_PROPERTY(QString, matcher, "BruteForce")
  21 + BR_PROPERTY(float, maxRatio, 0.8)
  22 +
  23 + Ptr<DescriptorMatcher> descriptorMatcher;
  24 +
  25 + void init()
  26 + {
  27 + descriptorMatcher = DescriptorMatcher::create(matcher.toStdString());
  28 + if (descriptorMatcher.empty())
  29 + qFatal("Failed to create DescriptorMatcher: %s", qPrintable(matcher));
  30 + }
  31 +
  32 + float compare(const Mat &a, const Mat &b) const
  33 + {
  34 + if ((a.rows < 2) || (b.rows < 2)) return 0;
  35 +
  36 + std::vector< std::vector<DMatch> > matches;
  37 + if (a.rows < b.rows) descriptorMatcher->knnMatch(a, b, matches, 2);
  38 + else descriptorMatcher->knnMatch(b, a, matches, 2);
  39 +
  40 + QList<float> distances;
  41 + foreach (const std::vector<DMatch> &match, matches) {
  42 + if (match[0].distance / match[1].distance > maxRatio) continue;
  43 + distances.append(match[0].distance);
  44 + }
  45 + qSort(distances);
  46 +
  47 + float similarity = 0;
  48 + for (int i=0; i<distances.size(); i++)
  49 + similarity += 1.f/(1+distances[i])/(i+1);
  50 + return similarity;
  51 + }
  52 +};
  53 +
  54 +BR_REGISTER(Distance, KeyPointMatcherDistance)
  55 +
  56 +} // namespace br
  57 +
  58 +#include "keypointmatcher.moc"
... ...
openbr/plugins/distance/l1.cpp 0 → 100644
  1 +#include <Eigen/Dense>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup distances
  10 + * \brief L1 distance computed using eigen.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class L1Distance : public UntrainableDistance
  14 +{
  15 + Q_OBJECT
  16 +
  17 + float compare(const cv::Mat &a, const cv::Mat &b) const
  18 + {
  19 + const int size = a.rows * a.cols;
  20 + Eigen::Map<Eigen::VectorXf> aMap((float*)a.data, size);
  21 + Eigen::Map<Eigen::VectorXf> bMap((float*)b.data, size);
  22 + return (aMap-bMap).cwiseAbs().sum();
  23 + }
  24 +};
  25 +
  26 +BR_REGISTER(Distance, L1Distance)
  27 +
  28 +} // namespace br
  29 +
  30 +#include "L1.moc"
... ...
openbr/plugins/distance/neglogplusone.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup distances
  8 + * \brief Returns -log(distance(a,b)+1)
  9 + * \author Josh Klontz \cite jklontz
  10 + */
  11 +class NegativeLogPlusOneDistance : public UntrainableDistance
  12 +{
  13 + Q_OBJECT
  14 + Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
  15 + BR_PROPERTY(br::Distance*, distance, NULL)
  16 +
  17 + void train(const TemplateList &src)
  18 + {
  19 + distance->train(src);
  20 + }
  21 +
  22 + float compare(const Template &a, const Template &b) const
  23 + {
  24 + return -log(distance->compare(a,b)+1);
  25 + }
  26 +
  27 + void store(QDataStream &stream) const
  28 + {
  29 + distance->store(stream);
  30 + }
  31 +
  32 + void load(QDataStream &stream)
  33 + {
  34 + distance->load(stream);
  35 + }
  36 +};
  37 +
  38 +BR_REGISTER(Distance, NegativeLogPlusOneDistance)
  39 +
  40 +} // namespace br
  41 +
  42 +#include "neglogplusone.moc"
... ...
openbr/plugins/distance/online.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup distances
  8 + * \brief Online distance metric to attenuate match scores across multiple frames
  9 + * \author Brendan klare \cite bklare
  10 + */
  11 +class OnlineDistance : public UntrainableDistance
  12 +{
  13 + Q_OBJECT
  14 + Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
  15 + Q_PROPERTY(float alpha READ get_alpha WRITE set_alpha RESET reset_alpha STORED false)
  16 + BR_PROPERTY(br::Distance*, distance, NULL)
  17 + BR_PROPERTY(float, alpha, 0.1f)
  18 +
  19 + mutable QHash<QString,float> scoreHash;
  20 + mutable QMutex mutex;
  21 +
  22 + float compare(const Template &target, const Template &query) const
  23 + {
  24 + float currentScore = distance->compare(target, query);
  25 +
  26 + QMutexLocker mutexLocker(&mutex);
  27 + return scoreHash[target.file.name] = (1.0- alpha) * scoreHash[target.file.name] + alpha * currentScore;
  28 + }
  29 +};
  30 +
  31 +BR_REGISTER(Distance, OnlineDistance)
  32 +
  33 +} // namespace br
  34 +
  35 +#include "online.moc"
... ...
openbr/plugins/distance/pipe.cpp 0 → 100644
  1 +#include <QtConcurrent>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup distances
  10 + * \brief Distances in series.
  11 + * \author Josh Klontz \cite jklontz
  12 + *
  13 + * The templates are compared using each br::Distance in order.
  14 + * If the result of the comparison with any given distance is -FLOAT_MAX then this result is returned early.
  15 + * Otherwise the returned result is the value of comparing the templates using the last br::Distance.
  16 + */
  17 +class PipeDistance : public Distance
  18 +{
  19 + Q_OBJECT
  20 + Q_PROPERTY(QList<br::Distance*> distances READ get_distances WRITE set_distances RESET reset_distances)
  21 + BR_PROPERTY(QList<br::Distance*>, distances, QList<br::Distance*>())
  22 +
  23 + void train(const TemplateList &data)
  24 + {
  25 + QFutureSynchronizer<void> futures;
  26 + foreach (br::Distance *distance, distances)
  27 + futures.addFuture(QtConcurrent::run(distance, &Distance::train, data));
  28 + futures.waitForFinished();
  29 + }
  30 +
  31 + float compare(const Template &a, const Template &b) const
  32 + {
  33 + float result = -std::numeric_limits<float>::max();
  34 + foreach (br::Distance *distance, distances) {
  35 + result = distance->compare(a, b);
  36 + if (result == -std::numeric_limits<float>::max())
  37 + return result;
  38 + }
  39 + return result;
  40 + }
  41 +};
  42 +
  43 +BR_REGISTER(Distance, PipeDistance)
  44 +
  45 +} // namespace br
  46 +
  47 +#include "pipe.moc"
... ...
openbr/plugins/distance/sum.cpp 0 → 100644
  1 +#include <QtConcurrent>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup distances
  10 + * \brief Sum match scores across multiple distances
  11 + * \author Scott Klum \cite sklum
  12 + */
  13 +class SumDistance : public UntrainableDistance
  14 +{
  15 + Q_OBJECT
  16 + Q_PROPERTY(QList<br::Distance*> distances READ get_distances WRITE set_distances RESET reset_distances)
  17 + BR_PROPERTY(QList<br::Distance*>, distances, QList<br::Distance*>())
  18 +
  19 + void train(const TemplateList &data)
  20 + {
  21 + QFutureSynchronizer<void> futures;
  22 + foreach (br::Distance *distance, distances)
  23 + futures.addFuture(QtConcurrent::run(distance, &Distance::train, data));
  24 + futures.waitForFinished();
  25 + }
  26 +
  27 + float compare(const Template &target, const Template &query) const
  28 + {
  29 + float result = 0;
  30 +
  31 + foreach (br::Distance *distance, distances) {
  32 + result += distance->compare(target, query);
  33 +
  34 + if (result == -std::numeric_limits<float>::max())
  35 + return result;
  36 + }
  37 +
  38 + return result;
  39 + }
  40 +};
  41 +
  42 +BR_REGISTER(Distance, SumDistance)
  43 +
  44 +} // namespace br
  45 +
  46 +#include "sum.moc"
... ...
openbr/plugins/draw.cpp deleted
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/highgui/highgui.hpp>
18   -#include <opencv2/highgui/highgui_c.h>
19   -#include <opencv2/imgproc/imgproc.hpp>
20   -#include <vector>
21   -#include "openbr_internal.h"
22   -#include "openbr/core/opencvutils.h"
23   -
24   -using namespace cv;
25   -
26   -namespace br
27   -{
28   -
29   -/*!
30   - * \ingroup transforms
31   - * \brief Renders metadata onto the image.
32   - *
33   - * The inPlace argument controls whether or not the image is cloned before the metadata is drawn.
34   - *
35   - * \author Josh Klontz \cite jklontz
36   - */
37   -class DrawTransform : public UntrainableTransform
38   -{
39   - Q_OBJECT
40   - Q_PROPERTY(bool verbose READ get_verbose WRITE set_verbose RESET reset_verbose STORED false)
41   - Q_PROPERTY(bool points READ get_points WRITE set_points RESET reset_points STORED false)
42   - Q_PROPERTY(bool rects READ get_rects WRITE set_rects RESET reset_rects STORED false)
43   - Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false)
44   - Q_PROPERTY(int lineThickness READ get_lineThickness WRITE set_lineThickness RESET reset_lineThickness STORED false)
45   - Q_PROPERTY(bool named READ get_named WRITE set_named RESET reset_named STORED false)
46   - Q_PROPERTY(bool location READ get_location WRITE set_location RESET reset_location STORED false)
47   - BR_PROPERTY(bool, verbose, false)
48   - BR_PROPERTY(bool, points, true)
49   - BR_PROPERTY(bool, rects, true)
50   - BR_PROPERTY(bool, inPlace, false)
51   - BR_PROPERTY(int, lineThickness, 1)
52   - BR_PROPERTY(bool, named, true)
53   - BR_PROPERTY(bool, location, true)
54   -
55   - void project(const Template &src, Template &dst) const
56   - {
57   - const Scalar color(0,255,0);
58   - const Scalar verboseColor(255, 255, 0);
59   - dst.m() = inPlace ? src.m() : src.m().clone();
60   -
61   - if (points) {
62   - const QList<Point2f> pointsList = (named) ? OpenCVUtils::toPoints(src.file.points()+src.file.namedPoints()) : OpenCVUtils::toPoints(src.file.points());
63   - for (int i=0; i<pointsList.size(); i++) {
64   - const Point2f &point = pointsList[i];
65   - circle(dst, point, 3, color, -1);
66   - QString label = (location) ? QString("%1,(%2,%3)").arg(QString::number(i),QString::number(point.x),QString::number(point.y)) : QString("%1").arg(QString::number(i));
67   - if (verbose) putText(dst, label.toStdString(), point, FONT_HERSHEY_SIMPLEX, 0.5, verboseColor, 1);
68   - }
69   - }
70   - if (rects) {
71   - foreach (const Rect &rect, OpenCVUtils::toRects(src.file.namedRects() + src.file.rects()))
72   - rectangle(dst, rect, color, lineThickness);
73   - }
74   - }
75   -};
76   -
77   -BR_REGISTER(Transform, DrawTransform)
78   -
79   -
80   -/*!
81   - * \ingroup transforms
82   - * \brief Draw the value of the specified property at the specified point on the image
83   - *
84   - * The inPlace argument controls whether or not the image is cloned before it is drawn on.
85   - *
86   - * \author Charles Otto \cite caotto
87   - */
88   -class DrawPropertyPointTransform : public UntrainableTransform
89   -{
90   - Q_OBJECT
91   - Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false)
92   - Q_PROPERTY(QString pointName READ get_pointName WRITE set_pointName RESET reset_pointName STORED false)
93   - Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false)
94   - BR_PROPERTY(QString, propName, "")
95   - BR_PROPERTY(QString, pointName, "")
96   - BR_PROPERTY(bool, inPlace, false)
97   -
98   -
99   - void project(const Template &src, Template &dst) const
100   - {
101   - dst = src;
102   - if (propName.isEmpty() || pointName.isEmpty())
103   - return;
104   -
105   - dst.m() = inPlace ? src.m() : src.m().clone();
106   -
107   - const Scalar textColor(255, 255, 0);
108   -
109   - QVariant prop = dst.file.value(propName);
110   -
111   -
112   - if (!prop.canConvert(QVariant::String))
113   - return;
114   - QString propString = prop.toString();
115   -
116   - QVariant point = dst.file.value(pointName);
117   -
118   - if (!point.canConvert(QVariant::PointF))
119   - return;
120   -
121   - QPointF targetPoint = point.toPointF();
122   -
123   - Point2f cvPoint =OpenCVUtils::toPoint(targetPoint);
124   -
125   - std::string text = propName.toStdString() + ": " + propString.toStdString();
126   - putText(dst, text, cvPoint, FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1);
127   - }
128   -
129   -};
130   -BR_REGISTER(Transform, DrawPropertyPointTransform)
131   -
132   -/*!
133   - * \ingroup transforms
134   - * \brief Draw the values of a list of properties at the specified point on the image
135   - *
136   - * The inPlace argument controls whether or not the image is cloned before it is drawn on.
137   - *
138   - * \author Charles Otto \cite caotto
139   - */
140   -class DrawPropertiesPointTransform : public UntrainableTransform
141   -{
142   - Q_OBJECT
143   - Q_PROPERTY(QStringList propNames READ get_propNames WRITE set_propNames RESET reset_propNames STORED false)
144   - Q_PROPERTY(QString pointName READ get_pointName WRITE set_pointName RESET reset_pointName STORED false)
145   - Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false)
146   - BR_PROPERTY(QStringList, propNames, QStringList())
147   - BR_PROPERTY(QString, pointName, "")
148   - BR_PROPERTY(bool, inPlace, false)
149   -
150   - void project(const Template &src, Template &dst) const
151   - {
152   - dst = src;
153   - if (propNames.isEmpty() || pointName.isEmpty())
154   - return;
155   -
156   - dst.m() = inPlace ? src.m() : src.m().clone();
157   -
158   - QVariant point = dst.file.value(pointName);
159   -
160   - if (!point.canConvert(QVariant::PointF))
161   - return;
162   -
163   - QPointF targetPoint = point.toPointF();
164   -
165   - Point2f cvPoint =OpenCVUtils::toPoint(targetPoint);
166   -
167   -
168   - const Scalar textColor(255, 255, 0);
169   -
170   - std::string outString = "";
171   - foreach (const QString &propName, propNames)
172   - {
173   - QVariant prop = dst.file.value(propName);
174   -
175   - if (!prop.canConvert(QVariant::String))
176   - continue;
177   - QString propString = prop.toString();
178   - outString += propName.toStdString() + ": " + propString.toStdString() + " ";
179   -
180   - }
181   - if (outString.empty())
182   - return;
183   -
184   - putText(dst, outString, cvPoint, FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1);
185   - }
186   -
187   -};
188   -BR_REGISTER(Transform, DrawPropertiesPointTransform)
189   -
190   -
191   -/*!
192   - * \ingroup transforms
193   - * \brief Draws a grid on the image
194   - * \author Josh Klontz \cite jklontz
195   - */
196   -class DrawGridTransform : public UntrainableTransform
197   -{
198   - Q_OBJECT
199   - Q_PROPERTY(int rows READ get_rows WRITE set_rows RESET reset_rows STORED false)
200   - Q_PROPERTY(int columns READ get_columns WRITE set_columns RESET reset_columns STORED false)
201   - Q_PROPERTY(int r READ get_r WRITE set_r RESET reset_r STORED false)
202   - Q_PROPERTY(int g READ get_g WRITE set_g RESET reset_g STORED false)
203   - Q_PROPERTY(int b READ get_b WRITE set_b RESET reset_b STORED false)
204   - BR_PROPERTY(int, rows, 0)
205   - BR_PROPERTY(int, columns, 0)
206   - BR_PROPERTY(int, r, 196)
207   - BR_PROPERTY(int, g, 196)
208   - BR_PROPERTY(int, b, 196)
209   -
210   - void project(const Template &src, Template &dst) const
211   - {
212   - Mat m = src.m().clone();
213   - float rowStep = 1.f * m.rows / (rows+1);
214   - float columnStep = 1.f * m.cols / (columns+1);
215   - int thickness = qMin(m.rows, m.cols) / 256;
216   - for (float row = rowStep/2; row < m.rows; row += rowStep)
217   - line(m, Point(0, row), Point(m.cols, row), Scalar(r, g, b), thickness, CV_AA);
218   - for (float column = columnStep/2; column < m.cols; column += columnStep)
219   - line(m, Point(column, 0), Point(column, m.rows), Scalar(r, g, b), thickness, CV_AA);
220   - dst = m;
221   - }
222   -};
223   -
224   -BR_REGISTER(Transform, DrawGridTransform)
225   -
226   -/*!
227   - * \ingroup transforms
228   - * \brief Computes the mean of a set of templates.
229   - * \note Suitable for visualization only as it sets every projected template to the mean template.
230   - * \author Scott Klum \cite sklum
231   - */
232   -class MeanTransform : public Transform
233   -{
234   - Q_OBJECT
235   -
236   - Mat mean;
237   -
238   - void train(const TemplateList &data)
239   - {
240   - mean = Mat::zeros(data[0].m().rows,data[0].m().cols,CV_32F);
241   -
242   - for (int i = 0; i < data.size(); i++) {
243   - Mat converted;
244   - data[i].m().convertTo(converted, CV_32F);
245   - mean += converted;
246   - }
247   -
248   - mean /= data.size();
249   - }
250   -
251   - void project(const Template &src, Template &dst) const
252   - {
253   - dst = src;
254   - dst.m() = mean;
255   - }
256   -
257   -};
258   -
259   -BR_REGISTER(Transform, MeanTransform)
260   -
261   -/*!
262   - * \ingroup transforms
263   - * \brief Load the image named in the specified property, draw it on the current matrix adjacent to the rect specified in the other property.
264   - * \author Charles Otto \cite caotto
265   - */
266   -class AdjacentOverlayTransform : public Transform
267   -{
268   - Q_OBJECT
269   -
270   - Q_PROPERTY(QString imgName READ get_imgName WRITE set_imgName RESET reset_imgName STORED false)
271   - Q_PROPERTY(QString targetName READ get_targetName WRITE set_targetName RESET reset_targetName STORED false)
272   - BR_PROPERTY(QString, imgName, "")
273   - BR_PROPERTY(QString, targetName, "")
274   -
275   - QSharedPointer<Transform> opener;
276   - void project(const Template &src, Template &dst) const
277   - {
278   - dst = src;
279   -
280   - if (imgName.isEmpty() || targetName.isEmpty() || !dst.file.contains(imgName) || !dst.file.contains(targetName))
281   - return;
282   -
283   - QVariant temp = src.file.value(imgName);
284   - cv::Mat im;
285   - // is this a filename?
286   - if (temp.canConvert<QString>()) {
287   - QString im_name = temp.toString();
288   - Template temp_im;
289   - opener->project(File(im_name), temp_im);
290   - im = temp_im.m();
291   - }
292   - // a cv::Mat ?
293   - else if (temp.canConvert<cv::Mat>())
294   - im = src.file.get<cv::Mat>(imgName);
295   - else
296   - qDebug() << "Unrecognized property type " << imgName << "for" << src.file.name;
297   -
298   - // Location of detected face in source image
299   - QRectF target_location = src.file.get<QRectF>(targetName);
300   -
301   - // match width with target region
302   - qreal target_width = target_location.width();
303   - qreal current_width = im.cols;
304   - qreal current_height = im.rows;
305   -
306   - qreal aspect_ratio = current_height / current_width;
307   - qreal target_height = target_width * aspect_ratio;
308   -
309   - cv::resize(im, im, cv::Size(target_width, target_height));
310   -
311   - // ROI used to maybe crop the matched image
312   - cv::Rect clip_roi;
313   - clip_roi.x = 0;
314   - clip_roi.y = 0;
315   - clip_roi.width = im.cols;
316   - clip_roi.height= im.rows <= dst.m().rows ? im.rows : dst.m().rows;
317   -
318   - int half_width = src.m().cols / 2;
319   - int out_x = 0;
320   -
321   - // place in the source image we will copy the matched image to.
322   - cv::Rect target_roi;
323   - bool left_side = false;
324   - int width_adjust = 0;
325   - // Place left
326   - if (target_location.center().rx() > half_width) {
327   - out_x = target_location.left() - im.cols;
328   - if (out_x < 0) {
329   - width_adjust = abs(out_x);
330   - out_x = 0;
331   - }
332   - left_side = true;
333   - }
334   - // place right
335   - else {
336   - out_x = target_location.right();
337   - int high = out_x + im.cols;
338   - if (high >= src.m().cols) {
339   - width_adjust = abs(high - src.m().cols + 1);
340   - }
341   - }
342   -
343   - cv::Mat outIm;
344   - if (width_adjust)
345   - {
346   - outIm.create(dst.m().rows, dst.m().cols + width_adjust, CV_8UC3);
347   - memset(outIm.data, 127, outIm.rows * outIm.cols * outIm.channels());
348   -
349   - Rect temp;
350   -
351   - if (left_side)
352   - temp = Rect(abs(width_adjust), 0, dst.m().cols, dst.m().rows);
353   -
354   - else
355   - temp = Rect(0, 0, dst.m().cols, dst.m().rows);
356   -
357   - dst.m().copyTo(outIm(temp));
358   -
359   - }
360   - else
361   - outIm = dst.m();
362   -
363   - if (clip_roi.height + target_location.top() >= outIm.rows)
364   - {
365   - clip_roi.height -= abs(outIm.rows - (clip_roi.height + target_location.top() ));
366   - }
367   - if (clip_roi.x + clip_roi.width >= im.cols) {
368   - clip_roi.width -= abs(im.cols - (clip_roi.x + clip_roi.width + 1));
369   - if (clip_roi.width < 0)
370   - clip_roi.width = 1;
371   - }
372   -
373   - if (clip_roi.y + clip_roi.height >= im.rows) {
374   - clip_roi.height -= abs(im.rows - (clip_roi.y + clip_roi.height + 1));
375   - }
376   - if (clip_roi.x < 0)
377   - clip_roi.x = 0;
378   - if (clip_roi.y < 0)
379   - clip_roi.y = 0;
380   -
381   - if (clip_roi.height < 0)
382   - clip_roi.height = 0;
383   -
384   - if (clip_roi.width < 0)
385   - clip_roi.width = 0;
386   -
387   -
388   - if (clip_roi.y + clip_roi.height >= im.rows)
389   - {
390   - qDebug() << "Bad clip y" << clip_roi.y + clip_roi.height << im.rows;
391   - }
392   - if (clip_roi.x + clip_roi.width >= im.cols)
393   - {
394   - qDebug() << "Bad clip x" << clip_roi.x + clip_roi.width << im.cols;
395   - }
396   -
397   - if (clip_roi.y < 0 || clip_roi.height < 0)
398   - {
399   - qDebug() << "bad clip y, low" << clip_roi.y << clip_roi.height;
400   - qFatal("die");
401   - }
402   - if (clip_roi.x < 0 || clip_roi.width < 0)
403   - {
404   - qDebug() << "bad clip x, low" << clip_roi.x << clip_roi.width;
405   - qFatal("die");
406   - }
407   -
408   - target_roi.x = out_x;
409   - target_roi.width = clip_roi.width;
410   - target_roi.y = target_location.top();
411   - target_roi.height = clip_roi.height;
412   -
413   -
414   - im = im(clip_roi);
415   -
416   - if (target_roi.x < 0 || target_roi.x >= outIm.cols)
417   - {
418   - qDebug() << "Bad xdim in targetROI!" << target_roi.x << " out im x: " << outIm.cols;
419   - qFatal("die");
420   - }
421   -
422   - if (target_roi.x + target_roi.width < 0 || (target_roi.x + target_roi.width) >= outIm.cols)
423   - {
424   - qDebug() << "Bad xdim in targetROI!" << target_roi.x + target_roi.width;
425   - qFatal("die");
426   - }
427   -
428   - if (target_roi.y < 0 || target_roi.y >= outIm.rows)
429   - {
430   - qDebug() << "Bad ydim in targetROI!" << target_roi.y;
431   - qFatal("die");
432   - }
433   -
434   - if ((target_roi.y + target_roi.height) < 0 || (target_roi.y + target_roi.height) > outIm.rows)
435   - {
436   - qDebug() << "Bad ydim in targetROI!" << target_roi.y + target_roi.height;
437   - qDebug() << "target_roi.y: " << target_roi.y << " height: " << target_roi.height;
438   - qFatal("die");
439   - }
440   -
441   -
442   - std::vector<cv::Mat> channels;
443   - cv::split(outIm, channels);
444   -
445   - std::vector<cv::Mat> patch_channels;
446   - cv::split(im, patch_channels);
447   -
448   - for (size_t i=0; i < channels.size(); i++)
449   - {
450   - cv::addWeighted(channels[i](target_roi), 0, patch_channels[i % patch_channels.size()], 1, 0,channels[i](target_roi));
451   - }
452   - cv::merge(channels, outIm);
453   - dst.m() = outIm;
454   -
455   - }
456   -
457   - void init()
458   - {
459   - opener = QSharedPointer<br::Transform>(br::Transform::make("Cache(Open)", NULL));
460   - }
461   -
462   -};
463   -
464   -BR_REGISTER(Transform, AdjacentOverlayTransform)
465   -
466   -/*!
467   - * \ingroup transforms
468   - * \brief Draw a line representing the direction and magnitude of optical flow at the specified points.
469   - * \author Austin Blanton \cite imaus10
470   - */
471   -class DrawOpticalFlow : public UntrainableTransform
472   -{
473   - Q_OBJECT
474   - Q_PROPERTY(QString original READ get_original WRITE set_original RESET reset_original STORED false)
475   - BR_PROPERTY(QString, original, "original")
476   -
477   - void project(const Template &src, Template &dst) const
478   - {
479   - const Scalar color(0,255,0);
480   - Mat flow = src.m();
481   - dst = src;
482   - if (!dst.file.contains(original)) qFatal("The original img must be saved in the metadata with SaveMat.");
483   - dst.m() = dst.file.get<Mat>(original);
484   - dst.file.remove(original);
485   - foreach (const Point2f &pt, OpenCVUtils::toPoints(dst.file.points())) {
486   - Point2f dxy = flow.at<Point2f>(pt.y, pt.x);
487   - Point2f newPt(pt.x+dxy.x, pt.y+dxy.y);
488   - line(dst, pt, newPt, color);
489   - }
490   - }
491   -};
492   -BR_REGISTER(Transform, DrawOpticalFlow)
493   -
494   -/*!
495   - * \ingroup transforms
496   - * \brief Fill in the segmentations or draw a line between intersecting segments.
497   - * \author Austin Blanton \cite imaus10
498   - */
499   -class DrawSegmentation : public UntrainableTransform
500   -{
501   - Q_OBJECT
502   - Q_PROPERTY(bool fillSegment READ get_fillSegment WRITE set_fillSegment RESET reset_fillSegment STORED false)
503   - BR_PROPERTY(bool, fillSegment, true)
504   -
505   - void project(const Template &src, Template &dst) const
506   - {
507   - if (!src.file.contains("SegmentsMask") || !src.file.contains("NumSegments")) qFatal("Must supply a Contours object in the metadata to drawContours.");
508   - Mat segments = src.file.get<Mat>("SegmentsMask");
509   - int numSegments = src.file.get<int>("NumSegments");
510   -
511   - dst.file = src.file;
512   - Mat drawn = fillSegment ? Mat(segments.size(), CV_8UC3, Scalar::all(0)) : src.m();
513   -
514   - for (int i=1; i<numSegments+1; i++) {
515   - Mat mask = segments == i;
516   - if (fillSegment) { // color the whole segment
517   - // set to a random color - get ready for a craaaazy acid trip
518   - int b = theRNG().uniform(0, 255);
519   - int g = theRNG().uniform(0, 255);
520   - int r = theRNG().uniform(0, 255);
521   - drawn.setTo(Scalar(r,g,b), mask);
522   - } else { // draw lines where there's a color change
523   - vector<vector<Point> > contours;
524   - Scalar color(0,255,0);
525   - findContours(mask, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
526   - drawContours(drawn, contours, -1, color);
527   - }
528   - }
529   -
530   - dst.m() = drawn;
531   - }
532   -};
533   -BR_REGISTER(Transform, DrawSegmentation)
534   -
535   -/*!
536   - * \ingroup transforms
537   - * \brief Write all mats to disk as images.
538   - * \author Brendan Klare \cite bklare
539   - */
540   -class WriteImageTransform : public TimeVaryingTransform
541   -{
542   - Q_OBJECT
543   - Q_PROPERTY(QString outputDirectory READ get_outputDirectory WRITE set_outputDirectory RESET reset_outputDirectory STORED false)
544   - Q_PROPERTY(QString imageName READ get_imageName WRITE set_imageName RESET reset_imageName STORED false)
545   - Q_PROPERTY(QString imgExtension READ get_imgExtension WRITE set_imgExtension RESET reset_imgExtension STORED false)
546   - BR_PROPERTY(QString, outputDirectory, "Temp")
547   - BR_PROPERTY(QString, imageName, "image")
548   - BR_PROPERTY(QString, imgExtension, "jpg")
549   -
550   - int cnt;
551   -
552   - void init() {
553   - cnt = 0;
554   - if (! QDir(outputDirectory).exists())
555   - QDir().mkdir(outputDirectory);
556   - }
557   -
558   - void projectUpdate(const Template &src, Template &dst)
559   - {
560   - dst = src;
561   - OpenCVUtils::saveImage(dst.m(), QString("%1/%2_%3.%4").arg(outputDirectory).arg(imageName).arg(cnt++, 5, 10, QChar('0')).arg(imgExtension));
562   - }
563   -
564   -};
565   -BR_REGISTER(Transform, WriteImageTransform)
566   -
567   -
568   -/**
569   - * @brief The MeanImageTransform class computes the average template/image
570   - * and save the result as an encoded image.
571   - */
572   -class MeanImageTransform : public TimeVaryingTransform
573   -{
574   - Q_OBJECT
575   -
576   - Q_PROPERTY(QString imgname READ get_imgname WRITE set_imgname RESET reset_imgname STORED false)
577   - Q_PROPERTY(QString ext READ get_ext WRITE set_ext RESET reset_ext STORED false)
578   -
579   - BR_PROPERTY(QString, imgname, "average")
580   - BR_PROPERTY(QString, ext, "jpg")
581   -
582   - Mat average;
583   - int cnt;
584   -
585   - void init()
586   - {
587   - cnt = 0;
588   - }
589   -
590   - void projectUpdate(const Template &src, Template &dst)
591   - {
592   - dst = src;
593   - if (cnt == 0) {
594   - if (src.m().channels() == 1)
595   - average = Mat::zeros(dst.m().size(),CV_64FC1);
596   - else if (src.m().channels() == 3)
597   - average = Mat::zeros(dst.m().size(),CV_64FC3);
598   - else
599   - qFatal("Unsupported number of channels");
600   - }
601   -
602   - Mat temp;
603   - if (src.m().channels() == 1) {
604   - src.m().convertTo(temp, CV_64FC1);
605   - average += temp;
606   - } else if (src.m().channels() == 3) {
607   - src.m().convertTo(temp, CV_64FC3);
608   - average += temp;
609   - } else
610   - qFatal("Unsupported number of channels");
611   -
612   - cnt++;
613   - }
614   -
615   - virtual void finalize(TemplateList &output)
616   - {
617   - average /= float(cnt);
618   - imwrite(QString("%1.%2").arg(imgname).arg(ext).toStdString(), average);
619   - output = TemplateList();
620   - }
621   -
622   -
623   -public:
624   - MeanImageTransform() : TimeVaryingTransform(false, false) {}
625   -};
626   -
627   -BR_REGISTER(Transform, MeanImageTransform)
628   -
629   -
630   -// TODO: re-implement EditTransform using Qt
631   -#if 0
632   -/*!
633   - * \ingroup transforms
634   - * \brief Remove landmarks.
635   - * \author Josh Klontz \cite jklontz
636   - */
637   -class EditTransform : public UntrainableTransform
638   -{
639   - Q_OBJECT
640   -
641   - Transform *draw;
642   - static Template currentTemplate;
643   - static QMutex currentTemplateLock;
644   -
645   - void init()
646   - {
647   - draw = make("Draw");
648   - Globals->setProperty("parallelism", "0"); // Can only work in single threaded mode
649   - }
650   -
651   - void project(const Template &src, Template &dst) const
652   - {
653   - dst = src;
654   -
655   - if (Globals->parallelism) {
656   - qWarning("Edit::project() only works in single threaded mode.");
657   - return;
658   - }
659   -
660   - currentTemplateLock.lock();
661   - currentTemplate = src;
662   - OpenCVUtils::showImage(src, "Edit", false);
663   - setMouseCallback("Edit", mouseCallback, (void*)this);
664   - mouseEvent(0, 0, 0, 0);
665   - waitKey(-1);
666   - dst = currentTemplate;
667   - currentTemplateLock.unlock();
668   - }
669   -
670   - static void mouseCallback(int event, int x, int y, int flags, void *userdata)
671   - {
672   - ((const EditTransform*)userdata)->mouseEvent(event, x, y, flags);
673   - }
674   -
675   - void mouseEvent(int event, int x, int y, int flags) const
676   - {
677   - (void) event;
678   - if (flags) {
679   - QList<QRectF> rects = currentTemplate.file.rects();
680   - for (int i=rects.size()-1; i>=0; i--)
681   - if (rects[i].contains(x,y))
682   - rects.removeAt(i);
683   - currentTemplate.file.setRects(rects);
684   - }
685   -
686   - Template temp;
687   - draw->project(currentTemplate, temp);
688   - OpenCVUtils::showImage(temp, "Edit", false);
689   - }
690   -};
691   -
692   -Template EditTransform::currentTemplate;
693   -QMutex EditTransform::currentTemplateLock;
694   -
695   -BR_REGISTER(Transform, EditTransform)
696   -#endif
697   -
698   -} // namespace br
699   -
700   -#include "draw.moc"
openbr/plugins/eigen3.cpp
... ... @@ -652,46 +652,6 @@ class SparseLDATransform : public Transform
652 652  
653 653 BR_REGISTER(Transform, SparseLDATransform)
654 654  
655   -/*!
656   - * \ingroup distances
657   - * \brief L1 distance computed using eigen.
658   - * \author Josh Klontz \cite jklontz
659   - */
660   -class L1Distance : public UntrainableDistance
661   -{
662   - Q_OBJECT
663   -
664   - float compare(const cv::Mat &a, const cv::Mat &b) const
665   - {
666   - const int size = a.rows * a.cols;
667   - Eigen::Map<Eigen::VectorXf> aMap((float*)a.data, size);
668   - Eigen::Map<Eigen::VectorXf> bMap((float*)b.data, size);
669   - return (aMap-bMap).cwiseAbs().sum();
670   - }
671   -};
672   -
673   -BR_REGISTER(Distance, L1Distance)
674   -
675   -/*!
676   - * \ingroup distances
677   - * \brief L2 distance computed using eigen.
678   - * \author Josh Klontz \cite jklontz
679   - */
680   -class L2Distance : public UntrainableDistance
681   -{
682   - Q_OBJECT
683   -
684   - float compare(const cv::Mat &a, const cv::Mat &b) const
685   - {
686   - const int size = a.rows * a.cols;
687   - Eigen::Map<Eigen::VectorXf> aMap((float*)a.data, size);
688   - Eigen::Map<Eigen::VectorXf> bMap((float*)b.data, size);
689   - return (aMap-bMap).squaredNorm();
690   - }
691   -};
692   -
693   -BR_REGISTER(Distance, L2Distance)
694   -
695 655 } // namespace br
696 656  
697 657 #include "eigen3.moc"
... ...
openbr/plugins/fill.cpp deleted
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/photo/photo.hpp>
18   -#include "openbr_internal.h"
19   -
20   -using namespace cv;
21   -
22   -namespace br
23   -{
24   -
25   -/*!
26   - * \ingroup transforms
27   - * \brief Wraps OpenCV inpainting
28   - * \author Josh Klontz \cite jklontz
29   - */
30   -class InpaintTransform : public UntrainableTransform
31   -{
32   - Q_OBJECT
33   - Q_ENUMS(Method)
34   - Q_PROPERTY(int radius READ get_radius WRITE set_radius RESET reset_radius STORED false)
35   - Q_PROPERTY(Method method READ get_method WRITE set_method RESET reset_method STORED false)
36   -
37   -public:
38   - /*!< */
39   - enum Method { NavierStokes = INPAINT_NS,
40   - Telea = INPAINT_TELEA };
41   -
42   -private:
43   - BR_PROPERTY(int, radius, 1)
44   - BR_PROPERTY(Method, method, NavierStokes)
45   - Transform *cvtGray;
46   -
47   - void init()
48   - {
49   - cvtGray = make("Cvt(Gray)");
50   - }
51   -
52   - void project(const Template &src, Template &dst) const
53   - {
54   - inpaint(src, (*cvtGray)(src)<5, dst, radius, method);
55   - }
56   -};
57   -
58   -BR_REGISTER(Transform, InpaintTransform)
59   -
60   -/*!
61   - * \ingroup transforms
62   - * \brief Fill 0 pixels with the mean of non-0 pixels.
63   - * \author Josh Klontz \cite jklontz
64   - */
65   -class MeanFillTransform : public UntrainableTransform
66   -{
67   - Q_OBJECT
68   -
69   - void project(const Template &src, Template &dst) const
70   - {
71   - dst = src.m().clone();
72   - dst.m().setTo(mean(dst, dst.m()!=0), dst.m()==0);
73   - }
74   -};
75   -
76   -BR_REGISTER(Transform, MeanFillTransform)
77   -
78   -/*!
79   - * \ingroup transforms
80   - * \brief Fill black pixels with the specified color.
81   - * \author Josh Klontz \cite jklontz
82   - */
83   -class FloodTransform : public UntrainableTransform
84   -{
85   - Q_OBJECT
86   - Q_PROPERTY(int r READ get_r WRITE set_r RESET reset_r STORED false)
87   - Q_PROPERTY(int g READ get_g WRITE set_g RESET reset_g STORED false)
88   - Q_PROPERTY(int b READ get_b WRITE set_b RESET reset_b STORED false)
89   - Q_PROPERTY(bool all READ get_all WRITE set_all RESET reset_all STORED false)
90   - BR_PROPERTY(int, r, 0)
91   - BR_PROPERTY(int, g, 0)
92   - BR_PROPERTY(int, b, 0)
93   - BR_PROPERTY(bool, all, false)
94   -
95   - void project(const Template &src, Template &dst) const
96   - {
97   - dst = src.m().clone();
98   - dst.m().setTo(Scalar(r, g, b), all ? Mat() : dst.m()==0);
99   - }
100   -};
101   -
102   -BR_REGISTER(Transform, FloodTransform)
103   -
104   -/*!
105   - * \ingroup transforms
106   - * \brief Alpha-blend two matrices
107   - * \author Josh Klontz \cite jklontz
108   - */
109   -class BlendTransform : public UntrainableMetaTransform
110   -{
111   - Q_OBJECT
112   - Q_PROPERTY(float alpha READ get_alpha WRITE set_alpha RESET reset_alpha STORED false)
113   - BR_PROPERTY(float, alpha, 0.5)
114   -
115   - void project(const Template &src, Template &dst) const
116   - {
117   - if (src.size() != 2) qFatal("Expected two source matrices.");
118   - addWeighted(src[0], alpha, src[1], 1-alpha, 0, dst);
119   - }
120   -};
121   -
122   -BR_REGISTER(Transform, BlendTransform)
123   -
124   -} // namespace br
125   -
126   -#include "fill.moc"
openbr/plugins/filter.cpp deleted
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 "openbr_internal.h"
19   -#include "openbr/core/tanh_sse.h"
20   -
21   -using namespace cv;
22   -
23   -namespace br
24   -{
25   -
26   -/*!
27   - * \ingroup transforms
28   - * \brief Gamma correction
29   - * \author Josh Klontz \cite jklontz
30   - */
31   -class GammaTransform : public UntrainableTransform
32   -{
33   - Q_OBJECT
34   - Q_PROPERTY(float gamma READ get_gamma WRITE set_gamma RESET reset_gamma STORED false)
35   - BR_PROPERTY(float, gamma, 0.2)
36   -
37   - Mat lut;
38   -
39   - void init()
40   - {
41   - lut.create(256, 1, CV_32FC1);
42   - if (gamma == 0) for (int i=0; i<256; i++) lut.at<float>(i,0) = log((float)i);
43   - else for (int i=0; i<256; i++) lut.at<float>(i,0) = pow(i, gamma);
44   - }
45   -
46   - void project(const Template &src, Template &dst) const
47   - {
48   - if (src.m().depth() == CV_8U) LUT(src, lut, dst);
49   - else pow(src, gamma, dst);
50   - }
51   -};
52   -
53   -BR_REGISTER(Transform, GammaTransform)
54   -
55   -/*!
56   - * \ingroup transforms
57   - * \brief Gaussian blur
58   - * \author Josh Klontz \cite jklontz
59   - */
60   -class BlurTransform : public UntrainableTransform
61   -{
62   - Q_OBJECT
63   - Q_PROPERTY(float sigma READ get_sigma WRITE set_sigma RESET reset_sigma STORED false)
64   - Q_PROPERTY(bool ROI READ get_ROI WRITE set_ROI RESET reset_ROI STORED false)
65   - BR_PROPERTY(float, sigma, 1)
66   - BR_PROPERTY(bool, ROI, false)
67   -
68   - void project(const Template &src, Template &dst) const
69   - {
70   - if (!ROI) GaussianBlur(src, dst, Size(0,0), sigma);
71   - else {
72   - dst.m() = src.m();
73   - foreach (const QRectF &rect, src.file.rects()) {
74   - Rect region(rect.x(), rect.y(), rect.width(), rect.height());
75   - Mat input = dst.m();
76   - Mat output = input.clone();
77   - GaussianBlur(input(region), output(region), Size(0,0), sigma);
78   - dst.m() = output;
79   - }
80   - }
81   - }
82   -};
83   -
84   -BR_REGISTER(Transform, BlurTransform)
85   -
86   -/*!
87   - * \ingroup transforms
88   - * \brief Difference of gaussians
89   - * \author Josh Klontz \cite jklontz
90   - */
91   -class DoGTransform : public UntrainableTransform
92   -{
93   - Q_OBJECT
94   - Q_PROPERTY(float sigma0 READ get_sigma0 WRITE set_sigma0 RESET reset_sigma0 STORED false)
95   - Q_PROPERTY(float sigma1 READ get_sigma1 WRITE set_sigma1 RESET reset_sigma1 STORED false)
96   - BR_PROPERTY(float, sigma0, 1)
97   - BR_PROPERTY(float, sigma1, 2)
98   -
99   - Size ksize0, ksize1;
100   -
101   - static Size getKernelSize(double sigma)
102   - {
103   - // Inverts OpenCV's conversion from kernel size to sigma:
104   - // sigma = ((ksize-1)*0.5 - 1)*0.3 + 0.8
105   - // See documentation for cv::getGaussianKernel()
106   - int ksize = ((sigma - 0.8) / 0.3 + 1) * 2 + 1;
107   - if (ksize % 2 == 0) ksize++;
108   - return Size(ksize, ksize);
109   - }
110   -
111   - void init()
112   - {
113   - ksize0 = getKernelSize(sigma0);
114   - ksize1 = getKernelSize(sigma1);
115   - }
116   -
117   - void project(const Template &src, Template &dst) const
118   - {
119   - Mat g0, g1;
120   - GaussianBlur(src, g0, ksize0, 0);
121   - GaussianBlur(src, g1, ksize1, 0);
122   - subtract(g0, g1, dst);
123   - }
124   -};
125   -
126   -BR_REGISTER(Transform, DoGTransform)
127   -
128   -/*!
129   - * \ingroup transforms
130   - * \brief Meyers, E.; Wolf, L.
131   - * “Using biologically inspired features for face processing,”
132   - * Int. Journal of Computer Vision, vol. 76, no. 1, pp 93–104, 2008.
133   - * \author Scott Klum \cite sklum
134   - */
135   -
136   -class CSDNTransform : public UntrainableTransform
137   -{
138   - Q_OBJECT
139   -
140   - Q_PROPERTY(float s READ get_s WRITE set_s RESET reset_s STORED false)
141   - BR_PROPERTY(int, s, 16)
142   -
143   - void project(const Template &src, Template &dst) const
144   - {
145   - if (src.m().channels() != 1) qFatal("Expected single channel source matrix.");
146   -
147   - const int nRows = src.m().rows;
148   - const int nCols = src.m().cols;
149   -
150   - Mat m;
151   - src.m().convertTo(m, CV_32FC1);
152   -
153   - const int surround = s/2;
154   -
155   - for ( int i = 0; i < nRows; i++ ) {
156   - for ( int j = 0; j < nCols; j++ ) {
157   - int width = min( j+surround, nCols ) - max( 0, j-surround );
158   - int height = min( i+surround, nRows ) - max( 0, i-surround );
159   -
160   - Rect_<int> ROI(max(0, j-surround), max(0, i-surround), width, height);
161   -
162   - Scalar_<float> avg = mean(m(ROI));
163   -
164   - m.at<float>(i,j) = m.at<float>(i,j) - avg[0];
165   - }
166   - }
167   -
168   - dst = m;
169   -
170   - }
171   -};
172   -
173   -BR_REGISTER(Transform, CSDNTransform)
174   -
175   -/*!
176   - * \ingroup transforms
177   - * \brief Xiaoyang Tan; Triggs, B.;
178   - * "Enhanced Local Texture Feature Sets for Face Recognition Under Difficult Lighting Conditions,"
179   - * Image Processing, IEEE Transactions on , vol.19, no.6, pp.1635-1650, June 2010
180   - * \author Josh Klontz \cite jklontz
181   - */
182   -class ContrastEqTransform : public UntrainableTransform
183   -{
184   - Q_OBJECT
185   - Q_PROPERTY(float a READ get_a WRITE set_a RESET reset_a STORED false)
186   - Q_PROPERTY(float t READ get_t WRITE set_t RESET reset_t STORED false)
187   - BR_PROPERTY(float, a, 1)
188   - BR_PROPERTY(float, t, 0.1)
189   -
190   - void project(const Template &src, Template &dst) const
191   - {
192   - if (src.m().channels() != 1) qFatal("Expected single channel source matrix.");
193   -
194   - // Stage 1
195   - Mat stage1;
196   - {
197   - Mat abs_dst;
198   - absdiff(src, Scalar(0), abs_dst);
199   - Mat pow_dst;
200   - pow(abs_dst, a, pow_dst);
201   - float denominator = pow((float)mean(pow_dst)[0], 1.f/a);
202   - src.m().convertTo(stage1, CV_32F, 1/denominator);
203   - }
204   -
205   - // Stage 2
206   - Mat stage2;
207   - {
208   - Mat abs_dst;
209   - absdiff(stage1, Scalar(0), abs_dst);
210   - Mat min_dst;
211   - min(abs_dst, t, min_dst);
212   - Mat pow_dst;
213   - pow(min_dst, a, pow_dst);
214   - float denominator = pow((float)mean(pow_dst)[0], 1.f/a);
215   - stage1.convertTo(stage2, CV_32F, 1/denominator);
216   - }
217   -
218   - // Hyperbolic tangent
219   - const int nRows = src.m().rows;
220   - const int nCols = src.m().cols;
221   - const float* p = (const float*)stage2.ptr();
222   - Mat m(nRows, nCols, CV_32FC1);
223   - for (int i=0; i<nRows; i++)
224   - for (int j=0; j<nCols; j++)
225   - m.at<float>(i, j) = fast_tanh(p[i*nCols+j]);
226   - // TODO: m.at<float>(i, j) = t * fast_tanh(p[i*nCols+j] / t);
227   -
228   - dst = m;
229   - }
230   -};
231   -
232   -BR_REGISTER(Transform, ContrastEqTransform)
233   -
234   -/*!
235   - * \ingroup transforms
236   - * \brief Raise each element to the specified power.
237   - * \author Josh Klontz \cite jklontz
238   - */
239   -class PowTransform : public UntrainableTransform
240   -{
241   - Q_OBJECT
242   - Q_PROPERTY(float power READ get_power WRITE set_power RESET reset_power STORED false)
243   - Q_PROPERTY(bool preserveSign READ get_preserveSign WRITE set_preserveSign RESET reset_preserveSign STORED false)
244   - BR_PROPERTY(float, power, 2)
245   - BR_PROPERTY(bool, preserveSign, false)
246   -
247   - void project(const Template &src, Template &dst) const
248   - {
249   - pow(preserveSign ? abs(src) : src.m(), power, dst);
250   - if (preserveSign) subtract(Scalar::all(0), dst, dst, src.m() < 0);
251   - }
252   -};
253   -
254   -BR_REGISTER(Transform, PowTransform)
255   -
256   -} // namespace br
257   -
258   -#include "filter.moc"
openbr/plugins/format.cpp deleted
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 <QDate>
18   -#include <QSize>
19   -#include <QChar>
20   -#ifndef BR_EMBEDDED
21   -#include <QtXml>
22   -#endif // BR_EMBEDDED
23   -#include <QFile>
24   -#include <QFileInfo>
25   -
26   -#include <opencv2/highgui/highgui.hpp>
27   -#include <opencv2/highgui/highgui_c.h>
28   -#include "openbr_internal.h"
29   -
30   -#include "openbr/core/bee.h"
31   -#include "openbr/core/opencvutils.h"
32   -#include "openbr/core/qtutils.h"
33   -
34   -using namespace cv;
35   -
36   -namespace br
37   -{
38   -
39   - /*!
40   - * \ingroup formats
41   - * \brief Read all frames of a video using OpenCV
42   - * \author Charles Otto \cite caotto
43   - */
44   -class videoFormat : public Format
45   -{
46   - Q_OBJECT
47   -
48   -public:
49   - Template read() const
50   - {
51   - if (!file.exists() )
52   - return Template();
53   -
54   - VideoCapture videoSource(file.name.toStdString());
55   - videoSource.open(file.name.toStdString() );
56   -
57   -
58   - Template frames;
59   - if (!videoSource.isOpened()) {
60   - qWarning("video file open failed");
61   - return frames;
62   - }
63   -
64   - bool open = true;
65   - while (open) {
66   - cv::Mat frame;
67   - open = videoSource.read(frame);
68   - if (!open) break;
69   -
70   - frames.append(cv::Mat());
71   - frames.back() = frame.clone();
72   - }
73   -
74   - return frames;
75   - }
76   -
77   - void write(const Template &t) const
78   - {
79   - int fourcc = OpenCVUtils::getFourcc();
80   - VideoWriter videoSink(file.name.toStdString(), fourcc, 30, t.begin()->size());
81   -
82   - // Did we successfully open the output file?
83   - if (!videoSink.isOpened() ) qFatal("Failed to open output file");
84   -
85   - for (Template::const_iterator it = t.begin(); it!= t.end(); ++it) {
86   - videoSink << *it;
87   - }
88   - }
89   -};
90   -
91   -BR_REGISTER(Format, videoFormat)
92   -
93   -/*!
94   - * \ingroup formats
95   - * \brief A simple binary matrix format.
96   - * \author Josh Klontz \cite jklontz
97   - * First 4 bytes indicate the number of rows.
98   - * Second 4 bytes indicate the number of columns.
99   - * The rest of the bytes are 32-bit floating data elements in row-major order.
100   - */
101   -class binFormat : public Format
102   -{
103   - Q_OBJECT
104   - Q_PROPERTY(bool raw READ get_raw WRITE set_raw RESET reset_raw STORED false)
105   - BR_PROPERTY(bool, raw, false)
106   -
107   - Template read() const
108   - {
109   - QByteArray data;
110   - QtUtils::readFile(file, data);
111   - if (raw) {
112   - return Template(file, Mat(1, data.size(), CV_8UC1, data.data()).clone());
113   - } else {
114   - return Template(file, Mat(((quint32*)data.data())[0],
115   - ((quint32*)data.data())[1],
116   - CV_32FC1,
117   - data.data()+8).clone());
118   - }
119   - }
120   -
121   - void write(const Template &t) const
122   - {
123   - QFile f(file);
124   - QtUtils::touchDir(f);
125   - if (!f.open(QFile::WriteOnly))
126   - qFatal("Failed to open %s for writing.", qPrintable(file));
127   -
128   - Mat m;
129   - if (!raw) {
130   - if (t.m().type() != CV_32FC1)
131   - t.m().convertTo(m, CV_32F);
132   - else m = t.m();
133   -
134   - if (m.channels() != 1) qFatal("Only supports single channel matrices.");
135   -
136   - f.write((const char *) &m.rows, 4);
137   - f.write((const char *) &m.cols, 4);
138   - }
139   - else m = t.m();
140   -
141   - qint64 rowSize = m.cols * sizeof(float);
142   - for (int i=0; i < m.rows; i++)
143   - {
144   - f.write((const char *) m.row(i).data, rowSize);
145   - }
146   - f.close();
147   - }
148   -};
149   -
150   -BR_REGISTER(Format, binFormat)
151   -
152   -/*!
153   - * \ingroup formats
154   - * \brief Reads a comma separated value file.
155   - * \author Josh Klontz \cite jklontz
156   - */
157   -class csvFormat : public Format
158   -{
159   - Q_OBJECT
160   -
161   - Template read() const
162   - {
163   - QFile f(file.name);
164   - f.open(QFile::ReadOnly);
165   - QStringList lines(QString(f.readAll()).split(QRegularExpression("[\n|\r\n|\r]"), QString::SkipEmptyParts));
166   - f.close();
167   -
168   - bool isUChar = true;
169   - QList< QList<float> > valsList;
170   - foreach (const QString &line, lines) {
171   - QList<float> vals;
172   - foreach (const QString &word, line.split(QRegExp(" *, *"), QString::SkipEmptyParts)) {
173   - bool ok;
174   - const float val = word.toFloat(&ok);
175   - vals.append(val);
176   - isUChar = isUChar && (val == float(uchar(val)));
177   - }
178   - if (!vals.isEmpty())
179   - valsList.append(vals);
180   - }
181   -
182   - Mat m(valsList.size(), valsList[0].size(), CV_32FC1);
183   - for (int i=0; i<valsList.size(); i++)
184   - for (int j=0; j<valsList[i].size(); j++)
185   - m.at<float>(i,j) = valsList[i][j];
186   -
187   - if (isUChar) m.convertTo(m, CV_8U);
188   - return Template(m);
189   - }
190   -
191   - void write(const Template &t) const
192   - {
193   - const Mat &m = t.m();
194   - if (t.size() != 1) qFatal("Only supports single matrix templates.");
195   - if (m.channels() != 1) qFatal("Only supports single channel matrices.");
196   -
197   - QStringList lines; lines.reserve(m.rows);
198   - for (int r=0; r<m.rows; r++) {
199   - QStringList elements; elements.reserve(m.cols);
200   - for (int c=0; c<m.cols; c++)
201   - elements.append(OpenCVUtils::elemToString(m, r, c));
202   - lines.append(elements.join(","));
203   - }
204   -
205   - QtUtils::writeFile(file, lines);
206   - }
207   -};
208   -
209   -BR_REGISTER(Format, csvFormat)
210   -
211   -/*!
212   - * \ingroup formats
213   - * \brief Reads image files.
214   - * \author Josh Klontz \cite jklontz
215   - */
216   -class DefaultFormat : public Format
217   -{
218   - Q_OBJECT
219   -
220   - Template read() const
221   - {
222   - Template t;
223   -
224   - if (file.name.startsWith("http://") || file.name.startsWith("https://") || file.name.startsWith("www.")) {
225   - if (Factory<Format>::names().contains("url")) {
226   - File urlFile = file;
227   - urlFile.name.append(".url");
228   - QScopedPointer<Format> url(Factory<Format>::make(urlFile));
229   - t = url->read();
230   - }
231   - } else {
232   - Mat m = imread(file.resolved().toStdString());
233   - if (m.data) {
234   - t.append(m);
235   - } else {
236   - videoFormat videoReader;
237   - videoReader.file = file;
238   - t = videoReader.read();
239   - }
240   - }
241   -
242   - return t;
243   - }
244   -
245   - void write(const Template &t) const
246   - {
247   - if (t.size() > 1) {
248   - videoFormat videoWriter;
249   - videoWriter.file = file;
250   - videoWriter.write(t);
251   - } else if (t.size() == 1) {
252   - QtUtils::touchDir(QDir(file.path()));
253   - imwrite(file.name.toStdString(), t);
254   - }
255   - }
256   -};
257   -
258   -BR_REGISTER(Format, DefaultFormat)
259   -
260   -/*!
261   - * \ingroup formats
262   - * \brief Reads a NIST LFFS file.
263   - * \author Josh Klontz \cite jklontz
264   - */
265   -class lffsFormat : public Format
266   -{
267   - Q_OBJECT
268   -
269   - Template read() const
270   - {
271   - QByteArray byteArray;
272   - QtUtils::readFile(file.name, byteArray);
273   - return Mat(1, byteArray.size(), CV_8UC1, byteArray.data()).clone();
274   - }
275   -
276   - void write(const Template &t) const
277   - {
278   - QByteArray byteArray((const char*)t.m().data, t.m().total()*t.m().elemSize());
279   - QtUtils::writeFile(file.name, byteArray);
280   - }
281   -};
282   -
283   -BR_REGISTER(Format, lffsFormat)
284   -
285   -/*!
286   - * \ingroup formats
287   - * \brief Reads a NIST BEE similarity matrix.
288   - * \author Josh Klontz \cite jklontz
289   - */
290   -class mtxFormat : public Format
291   -{
292   - Q_OBJECT
293   -
294   - Template read() const
295   - {
296   - QString target, query;
297   - Template result = BEE::readMatrix(file, &target, &query);
298   - result.file.set("Target", target);
299   - result.file.set("Query", query);
300   - return result;
301   - }
302   -
303   - void write(const Template &t) const
304   - {
305   - BEE::writeMatrix(t, file);
306   - }
307   -};
308   -
309   -BR_REGISTER(Format, mtxFormat)
310   -
311   -/*!
312   - * \ingroup formats
313   - * \brief Reads a NIST BEE mask matrix.
314   - * \author Josh Klontz \cite jklontz
315   - */
316   -class maskFormat : public mtxFormat
317   -{
318   - Q_OBJECT
319   -};
320   -
321   -BR_REGISTER(Format, maskFormat)
322   -
323   -/*!
324   - * \ingroup formats
325   - * \brief MATLAB <tt>.mat</tt> format.
326   - * \author Josh Klontz \cite jklontz
327   - * http://www.mathworks.com/help/pdf_doc/matlab/matfile_format.pdf
328   - * \note matFormat is known not to work with compressed matrices
329   - */
330   -class matFormat : public Format
331   -{
332   - Q_OBJECT
333   -
334   - struct Element
335   - {
336   - // It is always best to cast integers to a Qt integer type, such as qint16 or quint32, when reading and writing.
337   - // This ensures that you always know exactly what size integers you are reading and writing, no matter what the
338   - // underlying platform and architecture the application happens to be running on.
339   - // http://qt-project.org/doc/qt-4.8/datastreamformat.html
340   - quint32 type, bytes;
341   - QByteArray data;
342   - Element() : type(0), bytes(0) {}
343   - Element(QDataStream &stream)
344   - : type(0), bytes(0)
345   - {
346   - // Read first 4 bytes into type (32 bit integer),
347   - // specifying the type of data used
348   - if (stream.readRawData((char*)&type, 4) != 4)
349   - qFatal("Unexpected end of file.");
350   -
351   - if (type >= 1 << 16) {
352   - // Small data format
353   - bytes = type;
354   - type = type & 0x0000FFFF;
355   - bytes = bytes >> 16;
356   - } else {
357   - // Regular format
358   - // Read 4 bytes into bytes (32 bit integer),
359   - // specifying the size of the element
360   - if (stream.readRawData((char*)&bytes, 4) != 4)
361   - qFatal("Unexpected end of file.");
362   - }
363   -
364   - // Set the size of data to bytes
365   - data.resize(bytes);
366   -
367   - // Read bytes amount of data from the file into data
368   - if (int(bytes) != stream.readRawData(data.data(), bytes))
369   - qFatal("Unexpected end of file.");
370   -
371   - // Alignment
372   - int skipBytes = (bytes < 4) ? (4 - bytes) : (8 - bytes%8)%8;
373   - if (skipBytes != 0) stream.skipRawData(skipBytes);
374   - }
375   - };
376   -
377   - Template read() const
378   - {
379   - QByteArray byteArray;
380   - QtUtils::readFile(file, byteArray);
381   - QDataStream f(byteArray);
382   -
383   - { // Check header
384   - QByteArray header(128, 0);
385   - f.readRawData(header.data(), 128);
386   - if (!header.startsWith("MATLAB 5.0 MAT-file"))
387   - qFatal("Invalid MAT header.");
388   - }
389   -
390   - Template t(file);
391   -
392   - while (!f.atEnd()) {
393   - Element element(f);
394   -
395   - // miCOMPRESSED
396   - if (element.type == 15) {
397   - // Prepend the number of bytes to element.data
398   - element.data.prepend((char*)&element.bytes, 4); // Qt zlib wrapper requires this to preallocate the buffer
399   - QDataStream uncompressed(qUncompress(element.data));
400   - element = Element(uncompressed);
401   - }
402   -
403   - // miMATRIX
404   - if (element.type == 14) {
405   - QDataStream matrix(element.data);
406   - qint32 rows = 0, columns = 0;
407   - int matrixType = 0;
408   - QByteArray matrixData;
409   - while (!matrix.atEnd()) {
410   - Element subelement(matrix);
411   - if (subelement.type == 5) { // Dimensions array
412   - if (subelement.bytes == 8) {
413   - rows = ((qint32*)subelement.data.data())[0];
414   - columns = ((qint32*)subelement.data.data())[1];
415   - } else {
416   - qWarning("matFormat::read can only handle 2D arrays.");
417   - }
418   - } else if (subelement.type == 7) { //miSINGLE
419   - matrixType = CV_32FC1;
420   - matrixData = subelement.data;
421   - } else if (subelement.type == 9) { //miDOUBLE
422   - matrixType = CV_64FC1;
423   - matrixData = subelement.data;
424   - }
425   - }
426   -
427   - if ((rows > 0) && (columns > 0) && (matrixType != 0) && !matrixData.isEmpty()) {
428   - Mat transposed;
429   - transpose(Mat(columns, rows, matrixType, matrixData.data()), transposed);
430   - t.append(transposed);
431   - }
432   - }
433   - }
434   -
435   - return t;
436   - }
437   -
438   - void write(const Template &t) const
439   - {
440   - QByteArray data;
441   - QDataStream stream(&data, QFile::WriteOnly);
442   -
443   - { // Header
444   - QByteArray header = "MATLAB 5.0 MAT-file; Made with OpenBR | www.openbiometrics.org\n";
445   - QByteArray buffer(116-header.size(), 0);
446   - stream.writeRawData(header.data(), header.size());
447   - stream.writeRawData(buffer.data(), buffer.size());
448   - quint64 subsystem = 0;
449   - quint16 version = 0x0100;
450   - const char *endianness = "IM";
451   - stream.writeRawData((const char*)&subsystem, 8);
452   - stream.writeRawData((const char*)&version, 2);
453   - stream.writeRawData(endianness, 2);
454   - }
455   -
456   - for (int i=0; i<t.size(); i++) {
457   - const Mat &m = t[i];
458   - if (m.channels() != 1) qFatal("Only supports single channel matrices.");
459   -
460   - QByteArray subdata;
461   - QDataStream substream(&subdata, QFile::WriteOnly);
462   -
463   - { // Array Flags
464   - quint32 type = 6;
465   - quint32 bytes = 8;
466   - quint64 arrayClass = 0;
467   - switch (m.type()) {
468   - case CV_64FC1: arrayClass = 6; break;
469   - case CV_32FC1: arrayClass = 7; break;
470   - case CV_8UC1: arrayClass = 8; break;
471   - case CV_8SC1: arrayClass = 9; break;
472   - case CV_16UC1: arrayClass = 10; break;
473   - case CV_16SC1: arrayClass = 11; break;
474   - case CV_32SC1: arrayClass = 12; break;
475   - default: qFatal("Unsupported matrix class.");
476   - }
477   - substream.writeRawData((const char*)&type, 4);
478   - substream.writeRawData((const char*)&bytes, 4);
479   - substream.writeRawData((const char*)&arrayClass, 8);
480   - }
481   -
482   - { // Dimensions Array
483   - quint32 type = 5;
484   - quint32 bytes = 8;
485   - substream.writeRawData((const char*)&type, 4);
486   - substream.writeRawData((const char*)&bytes, 4);
487   - substream.writeRawData((const char*)&m.rows, 4);
488   - substream.writeRawData((const char*)&m.cols, 4);
489   - }
490   -
491   - { // Array Name
492   - QByteArray name(qPrintable(QString("OpenBR_%1").arg(QString::number(i))));
493   - quint32 type = 1;
494   - quint32 bytes = name.size();
495   - QByteArray buffer((8 - bytes%8)%8, 0);
496   - substream.writeRawData((const char*)&type, 4);
497   - substream.writeRawData((const char*)&bytes, 4);
498   - substream.writeRawData(name.data(), name.size());
499   - substream.writeRawData(buffer.data(), buffer.size());
500   - }
501   -
502   - { // Real part
503   - quint32 type = 0;
504   - switch (m.type()) {
505   - case CV_8SC1: type = 1; break;
506   - case CV_8UC1: type = 2; break;
507   - case CV_16SC1: type = 3; break;
508   - case CV_16UC1: type = 4; break;
509   - case CV_32SC1: type = 5; break;
510   - case CV_32FC1: type = 7; break;
511   - case CV_64FC1: type = 9; break;
512   - default: qFatal("Unsupported matrix type.");
513   - }
514   - quint32 bytes = m.elemSize() * m.rows * m.cols;
515   - QByteArray buffer((8 - bytes%8)%8, 0);
516   - Mat transposed;
517   - transpose(m, transposed);
518   - substream.writeRawData((const char*)&type, 4);
519   - substream.writeRawData((const char*)&bytes, 4);
520   - substream.writeRawData((const char*)transposed.data, bytes);
521   - substream.writeRawData(buffer.data(), buffer.size());
522   - }
523   -
524   - { // Matrix
525   - quint32 type = 14;
526   - quint32 bytes = subdata.size();
527   - stream.writeRawData((const char*)&type, 4);
528   - stream.writeRawData((const char*)&bytes, 4);
529   - stream.writeRawData(subdata.data(), subdata.size());
530   - }
531   - }
532   -
533   - QtUtils::writeFile(file, data);
534   - }
535   -};
536   -
537   -BR_REGISTER(Format, matFormat)
538   -
539   -/*!
540   - * \ingroup formats
541   - * \brief Returns an empty matrix.
542   - * \author Josh Klontz \cite jklontz
543   - */
544   -class nullFormat : public Format
545   -{
546   - Q_OBJECT
547   -
548   - Template read() const
549   - {
550   - return Template(file, Mat());
551   - }
552   -
553   - void write(const Template &t) const
554   - {
555   - (void)t;
556   - }
557   -};
558   -
559   -BR_REGISTER(Format, nullFormat)
560   -
561   -/*!
562   - * \ingroup formats
563   - * \brief RAW format
564   - *
565   - * http://www.nist.gov/srd/nistsd27.cfm
566   - * \author Josh Klontz \cite jklontz
567   - */
568   -class rawFormat : public Format
569   -{
570   - Q_OBJECT
571   - static QHash<QString, QHash<QString,QSize> > imageSizes; // QHash<Path, QHash<File,Size> >
572   -
573   - Template read() const
574   - {
575   - QString path = file.path();
576   - if (!imageSizes.contains(path)) {
577   - static QMutex mutex;
578   - QMutexLocker locker(&mutex);
579   -
580   - if (!imageSizes.contains(path)) {
581   - const QString imageSize = path+"/ImageSize.txt";
582   - QStringList lines;
583   - if (QFileInfo(imageSize).exists()) {
584   - lines = QtUtils::readLines(imageSize);
585   - lines.removeFirst(); // Remove header
586   - }
587   -
588   - QHash<QString,QSize> sizes;
589   - QRegExp whiteSpace("\\s+");
590   - foreach (const QString &line, lines) {
591   - QStringList words = line.split(whiteSpace);
592   - if (words.size() != 3) continue;
593   - sizes.insert(words[0], QSize(words[2].toInt(), words[1].toInt()));
594   - }
595   -
596   - imageSizes.insert(path, sizes);
597   - }
598   - }
599   -
600   - QByteArray data;
601   - QtUtils::readFile(file, data);
602   -
603   - QSize size = imageSizes[path][file.baseName()];
604   - if (!size.isValid()) size = QSize(800,768);
605   - if (data.size() != size.width() * size.height())
606   - qFatal("Expected %d*%d bytes, got %d.", size.height(), size.width(), data.size());
607   - return Template(file, Mat(size.height(), size.width(), CV_8UC1, data.data()).clone());
608   - }
609   -
610   - void write(const Template &t) const
611   - {
612   - QtUtils::writeFile(file, QByteArray().setRawData((const char*)t.m().data, t.m().total() * t.m().elemSize()));
613   - }
614   -};
615   -
616   -QHash<QString, QHash<QString,QSize> > rawFormat::imageSizes;
617   -
618   -BR_REGISTER(Format, rawFormat)
619   -
620   -/*!
621   - * \ingroup formats
622   - * \brief Retrieves an image from a webcam.
623   - * \author Josh Klontz \cite jklontz
624   - */
625   -class webcamFormat : public Format
626   -{
627   - Q_OBJECT
628   -
629   - Template read() const
630   - {
631   - static QScopedPointer<VideoCapture> videoCapture;
632   -
633   - if (videoCapture.isNull())
634   - videoCapture.reset(new VideoCapture(0));
635   -
636   - Mat m;
637   - videoCapture->read(m);
638   - return Template(m);
639   - }
640   -
641   - void write(const Template &t) const
642   - {
643   - (void) t;
644   - qFatal("Not supported.");
645   - }
646   -};
647   -
648   -BR_REGISTER(Format, webcamFormat)
649   -
650   -/*!
651   - * \ingroup formats
652   - * \brief Decodes images from Base64 xml
653   - * \author Scott Klum \cite sklum
654   - * \author Josh Klontz \cite jklontz
655   - */
656   -class xmlFormat : public Format
657   -{
658   - Q_OBJECT
659   -
660   - Template read() const
661   - {
662   - Template t;
663   -
664   -#ifndef BR_EMBEDDED
665   - QString fileName = file.get<QString>("path") + file.name;
666   -
667   - QDomDocument doc(fileName);
668   - QFile f(fileName);
669   -
670   - if (!f.open(QIODevice::ReadOnly)) qFatal("Unable to open %s for reading.", qPrintable(file.flat()));
671   - if (!doc.setContent(&f)) qWarning("Unable to parse %s.", qPrintable(file.flat()));
672   - f.close();
673   -
674   - QDomElement docElem = doc.documentElement();
675   - QDomNode subject = docElem.firstChild();
676   - while (!subject.isNull()) {
677   - QDomNode fileNode = subject.firstChild();
678   -
679   - while (!fileNode.isNull()) {
680   - QDomElement e = fileNode.toElement();
681   -
682   - if (e.tagName() == "FORMAL_IMG") {
683   - QByteArray byteArray = QByteArray::fromBase64(qPrintable(e.text()));
684   - Mat m = imdecode(Mat(3, byteArray.size(), CV_8UC3, byteArray.data()), CV_LOAD_IMAGE_COLOR);
685   - if (!m.data) qWarning("xmlFormat::read failed to decode image data.");
686   - t.append(m);
687   - } else if ((e.tagName() == "RELEASE_IMG") ||
688   - (e.tagName() == "PREBOOK_IMG") ||
689   - (e.tagName() == "LPROFILE") ||
690   - (e.tagName() == "RPROFILE")) {
691   - // Ignore these other image fields for now
692   - } else {
693   - t.file.set(e.tagName(), e.text());
694   - }
695   -
696   - fileNode = fileNode.nextSibling();
697   - }
698   - subject = subject.nextSibling();
699   - }
700   -
701   - // Calculate age
702   - if (t.file.contains("DOB")) {
703   - const QDate dob = QDate::fromString(t.file.get<QString>("DOB").left(10), "yyyy-MM-dd");
704   - const QDate current = QDate::currentDate();
705   - int age = current.year() - dob.year();
706   - if (current.month() < dob.month()) age--;
707   - t.file.set("Age", age);
708   - }
709   -#endif // BR_EMBEDDED
710   -
711   - return t;
712   - }
713   -
714   - void write(const Template &t) const
715   - {
716   - QStringList lines;
717   - lines.append("<?xml version=\"1.0\" standalone=\"yes\"?>");
718   - lines.append("<openbr-xml-format>");
719   - lines.append("\t<xml-data>");
720   - foreach (const QString &key, t.file.localKeys()) {
721   - if ((key == "Index") || (key == "Label")) continue;
722   - lines.append("\t\t<"+key+">"+QtUtils::toString(t.file.value(key))+"</"+key+">");
723   - }
724   - std::vector<uchar> data;
725   - imencode(".jpg",t.m(),data);
726   - QByteArray byteArray = QByteArray::fromRawData((const char*)data.data(), data.size());
727   - lines.append("\t\t<FORMAL_IMG>"+byteArray.toBase64()+"</FORMAL_IMG>");
728   - lines.append("\t</xml-data>");
729   - lines.append("</openbr-xml-format>");
730   - QtUtils::writeFile(file, lines);
731   - }
732   -};
733   -
734   -BR_REGISTER(Format, xmlFormat)
735   -
736   -/*!
737   - * \ingroup formats
738   - * \brief Reads in scores or ground truth from a text table.
739   - * \author Josh Klontz \cite jklontz
740   - *
741   - * Example of the format:
742   - * \code
743   - * 2.2531514 FALSE 99990377 99990164
744   - * 2.2549822 TRUE 99990101 99990101
745   - * \endcode
746   - */
747   -class scoresFormat : public Format
748   -{
749   - Q_OBJECT
750   - Q_PROPERTY(int column READ get_column WRITE set_column RESET reset_column STORED false)
751   - Q_PROPERTY(bool groundTruth READ get_groundTruth WRITE set_groundTruth RESET reset_groundTruth STORED false)
752   - Q_PROPERTY(QString delimiter READ get_delimiter WRITE set_delimiter RESET reset_delimiter STORED false)
753   - BR_PROPERTY(int, column, 0)
754   - BR_PROPERTY(bool, groundTruth, false)
755   - BR_PROPERTY(QString, delimiter, "\t")
756   -
757   - Template read() const
758   - {
759   - QFile f(file.name);
760   - if (!f.open(QFile::ReadOnly | QFile::Text))
761   - qFatal("Failed to open %s for reading.", qPrintable(f.fileName()));
762   - QList<float> values;
763   - while (!f.atEnd()) {
764   - const QStringList words = QString(f.readLine()).split(delimiter);
765   - if (words.size() <= column) qFatal("Expected file to have at least %d columns.", column+1);
766   - const QString &word = words[column];
767   - bool ok;
768   - float value = word.toFloat(&ok);
769   - if (!ok) value = (QtUtils::toBool(word) ? BEE::Match : BEE::NonMatch);
770   - values.append(value);
771   - }
772   - if (values.size() == 1)
773   - qWarning("Only one value read, double check file line endings.");
774   - Mat result = OpenCVUtils::toMat(values);
775   - if (groundTruth) result.convertTo(result, CV_8U);
776   - return result;
777   - }
778   -
779   - void write(const Template &t) const
780   - {
781   - (void) t;
782   - qFatal("Not implemented.");
783   - }
784   -};
785   -
786   -BR_REGISTER(Format, scoresFormat)
787   -
788   -/*!
789   - * \ingroup formats
790   - * \brief Reads FBI EBTS transactions.
791   - * \author Scott Klum \cite sklum
792   - * https://www.fbibiospecs.org/ebts.html
793   - */
794   -class ebtsFormat : public Format
795   -{
796   - Q_OBJECT
797   -
798   - struct Field {
799   - int type;
800   - QList<QByteArray> data;
801   - };
802   -
803   - struct Record {
804   - int type;
805   - quint32 bytes;
806   - int position; // Starting position of record
807   -
808   - QHash<int,QList<QByteArray> > fields;
809   - };
810   -
811   - quint32 recordBytes(const QByteArray &byteArray, const float recordType, int from) const
812   - {
813   - bool ok;
814   - quint32 size;
815   -
816   - if (recordType == 4 || recordType == 7) {
817   - // read first four bytes
818   - ok = true;
819   - size = qFromBigEndian<quint32>((const uchar*)byteArray.mid(from,4).constData());
820   - } else {
821   - int index = byteArray.indexOf(QChar(0x1D), from);
822   - size = byteArray.mid(from, index-from).split(':').last().toInt(&ok);
823   - }
824   -
825   - return ok ? size : -1;
826   - }
827   -
828   - void parseRecord(const QByteArray &byteArray, Record &record) const
829   - {
830   - if (record.type == 4 || record.type == 7) {
831   - // Just a binary blob
832   - // Read everything after the first four bytes
833   - // Not current supported
834   - } else {
835   - // Continue reading fields until we get all the data
836   - unsigned int position = record.position;
837   - while (position < record.position + record.bytes) {
838   - int index = byteArray.indexOf(QChar(0x1D), position);
839   - Field field = parseField(byteArray.mid(position, index-position),QChar(0x1F));
840   - if (field.type == 999 ) {
841   - // Data begin after the field identifier and the colon
842   - int dataBegin = byteArray.indexOf(':', position)+1;
843   - field.data.clear();
844   - field.data.append(byteArray.mid(dataBegin, record.bytes-(dataBegin-record.position)));
845   -
846   - // Data fields are always last in the record
847   - record.fields.insert(field.type,field.data);
848   - break;
849   - }
850   - // Advance the position accounting for the separator
851   - position += index-position+1;
852   - record.fields.insert(field.type,field.data);
853   - }
854   - }
855   - }
856   -
857   - Field parseField(const QByteArray &byteArray, const QChar &sep) const
858   - {
859   - bool ok;
860   - Field f;
861   -
862   - QList<QByteArray> data = byteArray.split(':');
863   -
864   - f.type = data.first().split('.').last().toInt(&ok);
865   - f.data = data.last().split(sep.toLatin1());
866   -
867   - return f;
868   - }
869   -
870   - Template read() const
871   - {
872   - QByteArray byteArray;
873   - QtUtils::readFile(file, byteArray);
874   -
875   - Template t;
876   -
877   - Mat m;
878   -
879   - QList<Record> records;
880   -
881   - // Read the type one record (every EBTS file will have one of these)
882   - Record r1;
883   - r1.type = 1;
884   - r1.position = 0;
885   - r1.bytes = recordBytes(byteArray,r1.type,r1.position);
886   -
887   - // The fields in a type 1 record are strictly defined
888   - QList<QByteArray> data = byteArray.mid(r1.position,r1.bytes).split(QChar(0x1D).toLatin1());
889   - foreach (const QByteArray &datum, data) {
890   - Field f = parseField(datum,QChar(0x1F));
891   - r1.fields.insert(f.type,f.data);
892   - }
893   -
894   - records.append(r1);
895   -
896   - // Read the type two record (every EBTS file will have one of these)
897   - Record r2;
898   - r2.type = 2;
899   - r2.position = r1.bytes;
900   - r2.bytes = recordBytes(byteArray,r2.type,r2.position);
901   -
902   - // The fields in a type 2 record are strictly defined
903   - data = byteArray.mid(r2.position,r2.bytes).split(QChar(0x1D).toLatin1());
904   - foreach (const QByteArray &datum, data) {
905   - Field f = parseField(datum,QChar(0x1F));
906   - r2.fields.insert(f.type,f.data);
907   - }
908   -
909   - // Demographics
910   - if (r2.fields.contains(18)) {
911   - QString name = r2.fields.value(18).first();
912   - QStringList names = name.split(',');
913   - t.file.set("FIRSTNAME", names.at(1));
914   - t.file.set("LASTNAME", names.at(0));
915   - }
916   -
917   - if (r2.fields.contains(22)) t.file.set("DOB", r2.fields.value(22).first().toInt());
918   - if (r2.fields.contains(24)) t.file.set("GENDER", QString(r2.fields.value(24).first()));
919   - if (r2.fields.contains(25)) t.file.set("RACE", QString(r2.fields.value(25).first()));
920   -
921   - if (t.file.contains("DOB")) {
922   - const QDate dob = QDate::fromString(t.file.get<QString>("DOB"), "yyyyMMdd");
923   - const QDate current = QDate::currentDate();
924   - int age = current.year() - dob.year();
925   - if (current.month() < dob.month()) age--;
926   - t.file.set("Age", age);
927   - }
928   -
929   - records.append(r2);
930   -
931   - // The third field of the first record contains informations about all the remaining records in the transaction
932   - // We don't care about the first two and the final items
933   - QList<QByteArray> recordTypes = r1.fields.value(3);
934   - for (int i=2; i<recordTypes.size()-1; i++) {
935   - // The first two bytes indicate the record index (and we don't want the separator), but we only care about the type
936   - QByteArray recordType = recordTypes[i].mid(3);
937   - Record r;
938   - r.type = recordType.toInt();
939   - records.append(r);
940   - }
941   -
942   - QList<int> frontalIdxs;
943   - int position = r1.bytes + r2.bytes;
944   - for (int i=2; i<records.size(); i++) {
945   - records[i].position = position;
946   - records[i].bytes = recordBytes(byteArray,records[i].type,position);
947   -
948   - parseRecord(byteArray, records[i]);
949   - if (records[i].type == 10) frontalIdxs.append(i);
950   - position += records[i].bytes;
951   - }
952   -
953   - if (!frontalIdxs.isEmpty()) {
954   - // We use the first type 10 record to get the frontal
955   - QByteArray frontal = records[frontalIdxs.first()].fields.value(999).first();
956   - m = imdecode(Mat(3, frontal.size(), CV_8UC3, frontal.data()), CV_LOAD_IMAGE_COLOR);
957   - if (!m.data) qWarning("ebtsFormat::read failed to decode image data.");
958   - t.m() = m;
959   - } else qWarning("ebtsFormat::cannot find image data within file.");
960   -
961   - return t;
962   - }
963   -
964   - void write(const Template &t) const
965   - {
966   - (void) t;
967   - qFatal("Writing EBTS files is not supported.");
968   - }
969   -};
970   -
971   -BR_REGISTER(Format, ebtsFormat)
972   -
973   -} // namespace br
974   -
975   -#include "format.moc"
openbr/plugins/format/binary.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/qtutils.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup formats
  11 + * \brief A simple binary matrix format.
  12 + * \author Josh Klontz \cite jklontz
  13 + * First 4 bytes indicate the number of rows.
  14 + * Second 4 bytes indicate the number of columns.
  15 + * The rest of the bytes are 32-bit floating data elements in row-major order.
  16 + */
  17 +class binaryFormat : public Format
  18 +{
  19 + Q_OBJECT
  20 + Q_PROPERTY(bool raw READ get_raw WRITE set_raw RESET reset_raw STORED false)
  21 + BR_PROPERTY(bool, raw, false)
  22 +
  23 + Template read() const
  24 + {
  25 + QByteArray data;
  26 + QtUtils::readFile(file, data);
  27 + if (raw) {
  28 + return Template(file, Mat(1, data.size(), CV_8UC1, data.data()).clone());
  29 + } else {
  30 + return Template(file, Mat(((quint32*)data.data())[0],
  31 + ((quint32*)data.data())[1],
  32 + CV_32FC1,
  33 + data.data()+8).clone());
  34 + }
  35 + }
  36 +
  37 + void write(const Template &t) const
  38 + {
  39 + QFile f(file);
  40 + QtUtils::touchDir(f);
  41 + if (!f.open(QFile::WriteOnly))
  42 + qFatal("Failed to open %s for writing.", qPrintable(file));
  43 +
  44 + Mat m;
  45 + if (!raw) {
  46 + if (t.m().type() != CV_32FC1)
  47 + t.m().convertTo(m, CV_32F);
  48 + else m = t.m();
  49 +
  50 + if (m.channels() != 1) qFatal("Only supports single channel matrices.");
  51 +
  52 + f.write((const char *) &m.rows, 4);
  53 + f.write((const char *) &m.cols, 4);
  54 + }
  55 + else m = t.m();
  56 +
  57 + qint64 rowSize = m.cols * sizeof(float);
  58 + for (int i=0; i < m.rows; i++)
  59 + {
  60 + f.write((const char *) m.row(i).data, rowSize);
  61 + }
  62 + f.close();
  63 + }
  64 +};
  65 +
  66 +BR_REGISTER(Format, binaryFormat)
  67 +
  68 +} // namespace br
  69 +
  70 +#include "binary.moc"
... ...
openbr/plugins/format/csv.cpp 0 → 100644
  1 +#include <QRegularExpression>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +#include <openbr/core/opencvutils.h>
  5 +#include <openbr/core/qtutils.h>
  6 +
  7 +using namespace cv;
  8 +
  9 +namespace br
  10 +{
  11 +
  12 +/*!
  13 + * \ingroup formats
  14 + * \brief Reads a comma separated value file.
  15 + * \author Josh Klontz \cite jklontz
  16 + */
  17 +class csvFormat : public Format
  18 +{
  19 + Q_OBJECT
  20 +
  21 + Template read() const
  22 + {
  23 + QFile f(file.name);
  24 + f.open(QFile::ReadOnly);
  25 + QStringList lines(QString(f.readAll()).split(QRegularExpression("[\n|\r\n|\r]"), QString::SkipEmptyParts));
  26 + f.close();
  27 +
  28 + bool isUChar = true;
  29 + QList< QList<float> > valsList;
  30 + foreach (const QString &line, lines) {
  31 + QList<float> vals;
  32 + foreach (const QString &word, line.split(QRegExp(" *, *"), QString::SkipEmptyParts)) {
  33 + bool ok;
  34 + const float val = word.toFloat(&ok);
  35 + vals.append(val);
  36 + isUChar = isUChar && (val == float(uchar(val)));
  37 + }
  38 + if (!vals.isEmpty())
  39 + valsList.append(vals);
  40 + }
  41 +
  42 + Mat m(valsList.size(), valsList[0].size(), CV_32FC1);
  43 + for (int i=0; i<valsList.size(); i++)
  44 + for (int j=0; j<valsList[i].size(); j++)
  45 + m.at<float>(i,j) = valsList[i][j];
  46 +
  47 + if (isUChar) m.convertTo(m, CV_8U);
  48 + return Template(m);
  49 + }
  50 +
  51 + void write(const Template &t) const
  52 + {
  53 + const Mat &m = t.m();
  54 + if (t.size() != 1) qFatal("Only supports single matrix templates.");
  55 + if (m.channels() != 1) qFatal("Only supports single channel matrices.");
  56 +
  57 + QStringList lines; lines.reserve(m.rows);
  58 + for (int r=0; r<m.rows; r++) {
  59 + QStringList elements; elements.reserve(m.cols);
  60 + for (int c=0; c<m.cols; c++)
  61 + elements.append(OpenCVUtils::elemToString(m, r, c));
  62 + lines.append(elements.join(","));
  63 + }
  64 +
  65 + QtUtils::writeFile(file, lines);
  66 + }
  67 +};
  68 +
  69 +BR_REGISTER(Format, csvFormat)
  70 +
  71 +} // namespace br
  72 +
  73 +#include "csv.moc"
... ...
openbr/plugins/format/ebts.cpp 0 → 100644
  1 +#include <QtEndian>
  2 +#include <opencv2/highgui/highgui.hpp>
  3 +
  4 +#include <openbr/plugins/openbr_internal.h>
  5 +#include <openbr/core/qtutils.h>
  6 +
  7 +using namespace cv;
  8 +
  9 +namespace br
  10 +{
  11 +
  12 +/*!
  13 + * \ingroup formats
  14 + * \brief Reads FBI EBTS transactions.
  15 + * \author Scott Klum \cite sklum
  16 + * https://www.fbibiospecs.org/ebts.html
  17 + */
  18 +class ebtsFormat : public Format
  19 +{
  20 + Q_OBJECT
  21 +
  22 + struct Field {
  23 + int type;
  24 + QList<QByteArray> data;
  25 + };
  26 +
  27 + struct Record {
  28 + int type;
  29 + quint32 bytes;
  30 + int position; // Starting position of record
  31 +
  32 + QHash<int,QList<QByteArray> > fields;
  33 + };
  34 +
  35 + quint32 recordBytes(const QByteArray &byteArray, const float recordType, int from) const
  36 + {
  37 + bool ok;
  38 + quint32 size;
  39 +
  40 + if (recordType == 4 || recordType == 7) {
  41 + // read first four bytes
  42 + ok = true;
  43 + size = qFromBigEndian<quint32>((const uchar*)byteArray.mid(from,4).constData());
  44 + } else {
  45 + int index = byteArray.indexOf(QChar(0x1D), from);
  46 + size = byteArray.mid(from, index-from).split(':').last().toInt(&ok);
  47 + }
  48 +
  49 + return ok ? size : -1;
  50 + }
  51 +
  52 + void parseRecord(const QByteArray &byteArray, Record &record) const
  53 + {
  54 + if (record.type == 4 || record.type == 7) {
  55 + // Just a binary blob
  56 + // Read everything after the first four bytes
  57 + // Not current supported
  58 + } else {
  59 + // Continue reading fields until we get all the data
  60 + unsigned int position = record.position;
  61 + while (position < record.position + record.bytes) {
  62 + int index = byteArray.indexOf(QChar(0x1D), position);
  63 + Field field = parseField(byteArray.mid(position, index-position),QChar(0x1F));
  64 + if (field.type == 999 ) {
  65 + // Data begin after the field identifier and the colon
  66 + int dataBegin = byteArray.indexOf(':', position)+1;
  67 + field.data.clear();
  68 + field.data.append(byteArray.mid(dataBegin, record.bytes-(dataBegin-record.position)));
  69 +
  70 + // Data fields are always last in the record
  71 + record.fields.insert(field.type,field.data);
  72 + break;
  73 + }
  74 + // Advance the position accounting for the separator
  75 + position += index-position+1;
  76 + record.fields.insert(field.type,field.data);
  77 + }
  78 + }
  79 + }
  80 +
  81 + Field parseField(const QByteArray &byteArray, const QChar &sep) const
  82 + {
  83 + bool ok;
  84 + Field f;
  85 +
  86 + QList<QByteArray> data = byteArray.split(':');
  87 +
  88 + f.type = data.first().split('.').last().toInt(&ok);
  89 + f.data = data.last().split(sep.toLatin1());
  90 +
  91 + return f;
  92 + }
  93 +
  94 + Template read() const
  95 + {
  96 + QByteArray byteArray;
  97 + QtUtils::readFile(file, byteArray);
  98 +
  99 + Template t;
  100 +
  101 + Mat m;
  102 +
  103 + QList<Record> records;
  104 +
  105 + // Read the type one record (every EBTS file will have one of these)
  106 + Record r1;
  107 + r1.type = 1;
  108 + r1.position = 0;
  109 + r1.bytes = recordBytes(byteArray,r1.type,r1.position);
  110 +
  111 + // The fields in a type 1 record are strictly defined
  112 + QList<QByteArray> data = byteArray.mid(r1.position,r1.bytes).split(QChar(0x1D).toLatin1());
  113 + foreach (const QByteArray &datum, data) {
  114 + Field f = parseField(datum,QChar(0x1F));
  115 + r1.fields.insert(f.type,f.data);
  116 + }
  117 +
  118 + records.append(r1);
  119 +
  120 + // Read the type two record (every EBTS file will have one of these)
  121 + Record r2;
  122 + r2.type = 2;
  123 + r2.position = r1.bytes;
  124 + r2.bytes = recordBytes(byteArray,r2.type,r2.position);
  125 +
  126 + // The fields in a type 2 record are strictly defined
  127 + data = byteArray.mid(r2.position,r2.bytes).split(QChar(0x1D).toLatin1());
  128 + foreach (const QByteArray &datum, data) {
  129 + Field f = parseField(datum,QChar(0x1F));
  130 + r2.fields.insert(f.type,f.data);
  131 + }
  132 +
  133 + // Demographics
  134 + if (r2.fields.contains(18)) {
  135 + QString name = r2.fields.value(18).first();
  136 + QStringList names = name.split(',');
  137 + t.file.set("FIRSTNAME", names.at(1));
  138 + t.file.set("LASTNAME", names.at(0));
  139 + }
  140 +
  141 + if (r2.fields.contains(22)) t.file.set("DOB", r2.fields.value(22).first().toInt());
  142 + if (r2.fields.contains(24)) t.file.set("GENDER", QString(r2.fields.value(24).first()));
  143 + if (r2.fields.contains(25)) t.file.set("RACE", QString(r2.fields.value(25).first()));
  144 +
  145 + if (t.file.contains("DOB")) {
  146 + const QDate dob = QDate::fromString(t.file.get<QString>("DOB"), "yyyyMMdd");
  147 + const QDate current = QDate::currentDate();
  148 + int age = current.year() - dob.year();
  149 + if (current.month() < dob.month()) age--;
  150 + t.file.set("Age", age);
  151 + }
  152 +
  153 + records.append(r2);
  154 +
  155 + // The third field of the first record contains informations about all the remaining records in the transaction
  156 + // We don't care about the first two and the final items
  157 + QList<QByteArray> recordTypes = r1.fields.value(3);
  158 + for (int i=2; i<recordTypes.size()-1; i++) {
  159 + // The first two bytes indicate the record index (and we don't want the separator), but we only care about the type
  160 + QByteArray recordType = recordTypes[i].mid(3);
  161 + Record r;
  162 + r.type = recordType.toInt();
  163 + records.append(r);
  164 + }
  165 +
  166 + QList<int> frontalIdxs;
  167 + int position = r1.bytes + r2.bytes;
  168 + for (int i=2; i<records.size(); i++) {
  169 + records[i].position = position;
  170 + records[i].bytes = recordBytes(byteArray,records[i].type,position);
  171 +
  172 + parseRecord(byteArray, records[i]);
  173 + if (records[i].type == 10) frontalIdxs.append(i);
  174 + position += records[i].bytes;
  175 + }
  176 +
  177 + if (!frontalIdxs.isEmpty()) {
  178 + // We use the first type 10 record to get the frontal
  179 + QByteArray frontal = records[frontalIdxs.first()].fields.value(999).first();
  180 + m = imdecode(Mat(3, frontal.size(), CV_8UC3, frontal.data()), CV_LOAD_IMAGE_COLOR);
  181 + if (!m.data) qWarning("ebtsFormat::read failed to decode image data.");
  182 + t.m() = m;
  183 + } else qWarning("ebtsFormat::cannot find image data within file.");
  184 +
  185 + return t;
  186 + }
  187 +
  188 + void write(const Template &t) const
  189 + {
  190 + (void) t;
  191 + qFatal("Writing EBTS files is not supported.");
  192 + }
  193 +};
  194 +
  195 +BR_REGISTER(Format, ebtsFormat)
  196 +
  197 +} // namespace br
  198 +
  199 +#include "ebts.moc"
... ...
openbr/plugins/format/lffs.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/qtutils.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup formats
  11 + * \brief Reads a NIST LFFS file.
  12 + * \author Josh Klontz \cite jklontz
  13 + */
  14 +class lffsFormat : public Format
  15 +{
  16 + Q_OBJECT
  17 +
  18 + Template read() const
  19 + {
  20 + QByteArray byteArray;
  21 + QtUtils::readFile(file.name, byteArray);
  22 + return Mat(1, byteArray.size(), CV_8UC1, byteArray.data()).clone();
  23 + }
  24 +
  25 + void write(const Template &t) const
  26 + {
  27 + QByteArray byteArray((const char*)t.m().data, t.m().total()*t.m().elemSize());
  28 + QtUtils::writeFile(file.name, byteArray);
  29 + }
  30 +};
  31 +
  32 +BR_REGISTER(Format, lffsFormat)
  33 +
  34 +} // namespace br
  35 +
  36 +#include "lffs.moc"
... ...
openbr/plugins/format/mat.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/qtutils.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup formats
  11 + * \brief MATLAB <tt>.mat</tt> format.
  12 + * \author Josh Klontz \cite jklontz
  13 + * http://www.mathworks.com/help/pdf_doc/matlab/matfile_format.pdf
  14 + * \note matFormat is known not to work with compressed matrices
  15 + */
  16 +class matFormat : public Format
  17 +{
  18 + Q_OBJECT
  19 +
  20 + struct Element
  21 + {
  22 + // It is always best to cast integers to a Qt integer type, such as qint16 or quint32, when reading and writing.
  23 + // This ensures that you always know exactly what size integers you are reading and writing, no matter what the
  24 + // underlying platform and architecture the application happens to be running on.
  25 + // http://qt-project.org/doc/qt-4.8/datastreamformat.html
  26 + quint32 type, bytes;
  27 + QByteArray data;
  28 + Element() : type(0), bytes(0) {}
  29 + Element(QDataStream &stream)
  30 + : type(0), bytes(0)
  31 + {
  32 + // Read first 4 bytes into type (32 bit integer),
  33 + // specifying the type of data used
  34 + if (stream.readRawData((char*)&type, 4) != 4)
  35 + qFatal("Unexpected end of file.");
  36 +
  37 + if (type >= 1 << 16) {
  38 + // Small data format
  39 + bytes = type;
  40 + type = type & 0x0000FFFF;
  41 + bytes = bytes >> 16;
  42 + } else {
  43 + // Regular format
  44 + // Read 4 bytes into bytes (32 bit integer),
  45 + // specifying the size of the element
  46 + if (stream.readRawData((char*)&bytes, 4) != 4)
  47 + qFatal("Unexpected end of file.");
  48 + }
  49 +
  50 + // Set the size of data to bytes
  51 + data.resize(bytes);
  52 +
  53 + // Read bytes amount of data from the file into data
  54 + if (int(bytes) != stream.readRawData(data.data(), bytes))
  55 + qFatal("Unexpected end of file.");
  56 +
  57 + // Alignment
  58 + int skipBytes = (bytes < 4) ? (4 - bytes) : (8 - bytes%8)%8;
  59 + if (skipBytes != 0) stream.skipRawData(skipBytes);
  60 + }
  61 + };
  62 +
  63 + Template read() const
  64 + {
  65 + QByteArray byteArray;
  66 + QtUtils::readFile(file, byteArray);
  67 + QDataStream f(byteArray);
  68 +
  69 + { // Check header
  70 + QByteArray header(128, 0);
  71 + f.readRawData(header.data(), 128);
  72 + if (!header.startsWith("MATLAB 5.0 MAT-file"))
  73 + qFatal("Invalid MAT header.");
  74 + }
  75 +
  76 + Template t(file);
  77 +
  78 + while (!f.atEnd()) {
  79 + Element element(f);
  80 +
  81 + // miCOMPRESSED
  82 + if (element.type == 15) {
  83 + // Prepend the number of bytes to element.data
  84 + element.data.prepend((char*)&element.bytes, 4); // Qt zlib wrapper requires this to preallocate the buffer
  85 + QDataStream uncompressed(qUncompress(element.data));
  86 + element = Element(uncompressed);
  87 + }
  88 +
  89 + // miMATRIX
  90 + if (element.type == 14) {
  91 + QDataStream matrix(element.data);
  92 + qint32 rows = 0, columns = 0;
  93 + int matrixType = 0;
  94 + QByteArray matrixData;
  95 + while (!matrix.atEnd()) {
  96 + Element subelement(matrix);
  97 + if (subelement.type == 5) { // Dimensions array
  98 + if (subelement.bytes == 8) {
  99 + rows = ((qint32*)subelement.data.data())[0];
  100 + columns = ((qint32*)subelement.data.data())[1];
  101 + } else {
  102 + qWarning("matFormat::read can only handle 2D arrays.");
  103 + }
  104 + } else if (subelement.type == 7) { //miSINGLE
  105 + matrixType = CV_32FC1;
  106 + matrixData = subelement.data;
  107 + } else if (subelement.type == 9) { //miDOUBLE
  108 + matrixType = CV_64FC1;
  109 + matrixData = subelement.data;
  110 + }
  111 + }
  112 +
  113 + if ((rows > 0) && (columns > 0) && (matrixType != 0) && !matrixData.isEmpty()) {
  114 + Mat transposed;
  115 + transpose(Mat(columns, rows, matrixType, matrixData.data()), transposed);
  116 + t.append(transposed);
  117 + }
  118 + }
  119 + }
  120 +
  121 + return t;
  122 + }
  123 +
  124 + void write(const Template &t) const
  125 + {
  126 + QByteArray data;
  127 + QDataStream stream(&data, QFile::WriteOnly);
  128 +
  129 + { // Header
  130 + QByteArray header = "MATLAB 5.0 MAT-file; Made with OpenBR | www.openbiometrics.org\n";
  131 + QByteArray buffer(116-header.size(), 0);
  132 + stream.writeRawData(header.data(), header.size());
  133 + stream.writeRawData(buffer.data(), buffer.size());
  134 + quint64 subsystem = 0;
  135 + quint16 version = 0x0100;
  136 + const char *endianness = "IM";
  137 + stream.writeRawData((const char*)&subsystem, 8);
  138 + stream.writeRawData((const char*)&version, 2);
  139 + stream.writeRawData(endianness, 2);
  140 + }
  141 +
  142 + for (int i=0; i<t.size(); i++) {
  143 + const Mat &m = t[i];
  144 + if (m.channels() != 1) qFatal("Only supports single channel matrices.");
  145 +
  146 + QByteArray subdata;
  147 + QDataStream substream(&subdata, QFile::WriteOnly);
  148 +
  149 + { // Array Flags
  150 + quint32 type = 6;
  151 + quint32 bytes = 8;
  152 + quint64 arrayClass = 0;
  153 + switch (m.type()) {
  154 + case CV_64FC1: arrayClass = 6; break;
  155 + case CV_32FC1: arrayClass = 7; break;
  156 + case CV_8UC1: arrayClass = 8; break;
  157 + case CV_8SC1: arrayClass = 9; break;
  158 + case CV_16UC1: arrayClass = 10; break;
  159 + case CV_16SC1: arrayClass = 11; break;
  160 + case CV_32SC1: arrayClass = 12; break;
  161 + default: qFatal("Unsupported matrix class.");
  162 + }
  163 + substream.writeRawData((const char*)&type, 4);
  164 + substream.writeRawData((const char*)&bytes, 4);
  165 + substream.writeRawData((const char*)&arrayClass, 8);
  166 + }
  167 +
  168 + { // Dimensions Array
  169 + quint32 type = 5;
  170 + quint32 bytes = 8;
  171 + substream.writeRawData((const char*)&type, 4);
  172 + substream.writeRawData((const char*)&bytes, 4);
  173 + substream.writeRawData((const char*)&m.rows, 4);
  174 + substream.writeRawData((const char*)&m.cols, 4);
  175 + }
  176 +
  177 + { // Array Name
  178 + QByteArray name(qPrintable(QString("OpenBR_%1").arg(QString::number(i))));
  179 + quint32 type = 1;
  180 + quint32 bytes = name.size();
  181 + QByteArray buffer((8 - bytes%8)%8, 0);
  182 + substream.writeRawData((const char*)&type, 4);
  183 + substream.writeRawData((const char*)&bytes, 4);
  184 + substream.writeRawData(name.data(), name.size());
  185 + substream.writeRawData(buffer.data(), buffer.size());
  186 + }
  187 +
  188 + { // Real part
  189 + quint32 type = 0;
  190 + switch (m.type()) {
  191 + case CV_8SC1: type = 1; break;
  192 + case CV_8UC1: type = 2; break;
  193 + case CV_16SC1: type = 3; break;
  194 + case CV_16UC1: type = 4; break;
  195 + case CV_32SC1: type = 5; break;
  196 + case CV_32FC1: type = 7; break;
  197 + case CV_64FC1: type = 9; break;
  198 + default: qFatal("Unsupported matrix type.");
  199 + }
  200 + quint32 bytes = m.elemSize() * m.rows * m.cols;
  201 + QByteArray buffer((8 - bytes%8)%8, 0);
  202 + Mat transposed;
  203 + transpose(m, transposed);
  204 + substream.writeRawData((const char*)&type, 4);
  205 + substream.writeRawData((const char*)&bytes, 4);
  206 + substream.writeRawData((const char*)transposed.data, bytes);
  207 + substream.writeRawData(buffer.data(), buffer.size());
  208 + }
  209 +
  210 + { // Matrix
  211 + quint32 type = 14;
  212 + quint32 bytes = subdata.size();
  213 + stream.writeRawData((const char*)&type, 4);
  214 + stream.writeRawData((const char*)&bytes, 4);
  215 + stream.writeRawData(subdata.data(), subdata.size());
  216 + }
  217 + }
  218 +
  219 + QtUtils::writeFile(file, data);
  220 + }
  221 +};
  222 +
  223 +BR_REGISTER(Format, matFormat)
  224 +
  225 +} // namespace br
  226 +
  227 +#include "mat.moc"
... ...
openbr/plugins/format/mtx.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/bee.h>
  3 +
  4 +namespace br
  5 +{
  6 +
  7 +/*!
  8 + * \ingroup formats
  9 + * \brief Reads a NIST BEE similarity matrix.
  10 + * \author Josh Klontz \cite jklontz
  11 + */
  12 +class mtxFormat : public Format
  13 +{
  14 + Q_OBJECT
  15 +
  16 + Template read() const
  17 + {
  18 + QString target, query;
  19 + Template result = BEE::readMatrix(file, &target, &query);
  20 + result.file.set("Target", target);
  21 + result.file.set("Query", query);
  22 + return result;
  23 + }
  24 +
  25 + void write(const Template &t) const
  26 + {
  27 + BEE::writeMatrix(t, file);
  28 + }
  29 +};
  30 +
  31 +BR_REGISTER(Format, mtxFormat)
  32 +
  33 +/*!
  34 + * \ingroup formats
  35 + * \brief Reads a NIST BEE mask matrix.
  36 + * \author Josh Klontz \cite jklontz
  37 + */
  38 +class maskFormat : public mtxFormat
  39 +{
  40 + Q_OBJECT
  41 +};
  42 +
  43 +BR_REGISTER(Format, maskFormat)
  44 +
  45 +} // namespace br
  46 +
  47 +#include "mtx.moc"
... ...
openbr/plugins/format/null.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup formats
  8 + * \brief Returns an empty matrix.
  9 + * \author Josh Klontz \cite jklontz
  10 + */
  11 +class nullFormat : public Format
  12 +{
  13 + Q_OBJECT
  14 +
  15 + Template read() const
  16 + {
  17 + return Template(file, cv::Mat());
  18 + }
  19 +
  20 + void write(const Template &t) const
  21 + {
  22 + (void)t;
  23 + }
  24 +};
  25 +
  26 +BR_REGISTER(Format, nullFormat)
  27 +
  28 +} // namespace br
  29 +
  30 +#include "null.moc"
... ...
openbr/plugins/format/raw.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/qtutils.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup formats
  11 + * \brief RAW format
  12 + *
  13 + * http://www.nist.gov/srd/nistsd27.cfm
  14 + * \author Josh Klontz \cite jklontz
  15 + */
  16 +class rawFormat : public Format
  17 +{
  18 + Q_OBJECT
  19 + static QHash<QString, QHash<QString,QSize> > imageSizes; // QHash<Path, QHash<File,Size> >
  20 +
  21 + Template read() const
  22 + {
  23 + QString path = file.path();
  24 + if (!imageSizes.contains(path)) {
  25 + static QMutex mutex;
  26 + QMutexLocker locker(&mutex);
  27 +
  28 + if (!imageSizes.contains(path)) {
  29 + const QString imageSize = path+"/ImageSize.txt";
  30 + QStringList lines;
  31 + if (QFileInfo(imageSize).exists()) {
  32 + lines = QtUtils::readLines(imageSize);
  33 + lines.removeFirst(); // Remove header
  34 + }
  35 +
  36 + QHash<QString,QSize> sizes;
  37 + QRegExp whiteSpace("\\s+");
  38 + foreach (const QString &line, lines) {
  39 + QStringList words = line.split(whiteSpace);
  40 + if (words.size() != 3) continue;
  41 + sizes.insert(words[0], QSize(words[2].toInt(), words[1].toInt()));
  42 + }
  43 +
  44 + imageSizes.insert(path, sizes);
  45 + }
  46 + }
  47 +
  48 + QByteArray data;
  49 + QtUtils::readFile(file, data);
  50 +
  51 + QSize size = imageSizes[path][file.baseName()];
  52 + if (!size.isValid()) size = QSize(800,768);
  53 + if (data.size() != size.width() * size.height())
  54 + qFatal("Expected %d*%d bytes, got %d.", size.height(), size.width(), data.size());
  55 + return Template(file, Mat(size.height(), size.width(), CV_8UC1, data.data()).clone());
  56 + }
  57 +
  58 + void write(const Template &t) const
  59 + {
  60 + QtUtils::writeFile(file, QByteArray().setRawData((const char*)t.m().data, t.m().total() * t.m().elemSize()));
  61 + }
  62 +};
  63 +
  64 +QHash<QString, QHash<QString,QSize> > rawFormat::imageSizes;
  65 +
  66 +BR_REGISTER(Format, rawFormat)
  67 +
  68 +} // namespace br
  69 +
  70 +#include "raw.moc"
... ...
openbr/plugins/format/scores.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/qtutils.h>
  3 +#include <openbr/core/opencvutils.h>
  4 +#include <openbr/core/bee.h>
  5 +
  6 +using namespace cv;
  7 +
  8 +namespace br
  9 +{
  10 +
  11 +/*!
  12 + * \ingroup formats
  13 + * \brief Reads in scores or ground truth from a text table.
  14 + * \author Josh Klontz \cite jklontz
  15 + *
  16 + * Example of the format:
  17 + * \code
  18 + * 2.2531514 FALSE 99990377 99990164
  19 + * 2.2549822 TRUE 99990101 99990101
  20 + * \endcode
  21 + */
  22 +class scoresFormat : public Format
  23 +{
  24 + Q_OBJECT
  25 + Q_PROPERTY(int column READ get_column WRITE set_column RESET reset_column STORED false)
  26 + Q_PROPERTY(bool groundTruth READ get_groundTruth WRITE set_groundTruth RESET reset_groundTruth STORED false)
  27 + Q_PROPERTY(QString delimiter READ get_delimiter WRITE set_delimiter RESET reset_delimiter STORED false)
  28 + BR_PROPERTY(int, column, 0)
  29 + BR_PROPERTY(bool, groundTruth, false)
  30 + BR_PROPERTY(QString, delimiter, "\t")
  31 +
  32 + Template read() const
  33 + {
  34 + QFile f(file.name);
  35 + if (!f.open(QFile::ReadOnly | QFile::Text))
  36 + qFatal("Failed to open %s for reading.", qPrintable(f.fileName()));
  37 + QList<float> values;
  38 + while (!f.atEnd()) {
  39 + const QStringList words = QString(f.readLine()).split(delimiter);
  40 + if (words.size() <= column) qFatal("Expected file to have at least %d columns.", column+1);
  41 + const QString &word = words[column];
  42 + bool ok;
  43 + float value = word.toFloat(&ok);
  44 + if (!ok) value = (QtUtils::toBool(word) ? BEE::Match : BEE::NonMatch);
  45 + values.append(value);
  46 + }
  47 + if (values.size() == 1)
  48 + qWarning("Only one value read, double check file line endings.");
  49 + Mat result = OpenCVUtils::toMat(values);
  50 + if (groundTruth) result.convertTo(result, CV_8U);
  51 + return result;
  52 + }
  53 +
  54 + void write(const Template &t) const
  55 + {
  56 + (void) t;
  57 + qFatal("Not implemented.");
  58 + }
  59 +};
  60 +
  61 +BR_REGISTER(Format, scoresFormat)
  62 +
  63 +} // namespace br
  64 +
  65 +#include "scores.moc"
... ...
openbr/plugins/format/video.cpp 0 → 100644
  1 +#include <opencv2/highgui/highgui.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +#include <openbr/core/qtutils.h>
  5 +#include <openbr/core/opencvutils.h>
  6 +
  7 +using namespace cv;
  8 +
  9 +namespace br
  10 +{
  11 +
  12 +/*!
  13 + * \ingroup formats
  14 + * \brief Read all frames of a video using OpenCV
  15 + * \author Charles Otto \cite caotto
  16 + */
  17 +class videoFormat : public Format
  18 +{
  19 + Q_OBJECT
  20 +
  21 +public:
  22 + Template read() const
  23 + {
  24 + if (!file.exists() )
  25 + return Template();
  26 +
  27 + VideoCapture videoSource(file.name.toStdString());
  28 + videoSource.open(file.name.toStdString() );
  29 +
  30 +
  31 + Template frames;
  32 + if (!videoSource.isOpened()) {
  33 + qWarning("video file open failed");
  34 + return frames;
  35 + }
  36 +
  37 + bool open = true;
  38 + while (open) {
  39 + cv::Mat frame;
  40 + open = videoSource.read(frame);
  41 + if (!open) break;
  42 +
  43 + frames.append(cv::Mat());
  44 + frames.back() = frame.clone();
  45 + }
  46 +
  47 + return frames;
  48 + }
  49 +
  50 + void write(const Template &t) const
  51 + {
  52 + int fourcc = OpenCVUtils::getFourcc();
  53 + VideoWriter videoSink(file.name.toStdString(), fourcc, 30, t.begin()->size());
  54 +
  55 + // Did we successfully open the output file?
  56 + if (!videoSink.isOpened() ) qFatal("Failed to open output file");
  57 +
  58 + for (Template::const_iterator it = t.begin(); it!= t.end(); ++it) {
  59 + videoSink << *it;
  60 + }
  61 + }
  62 +};
  63 +
  64 +BR_REGISTER(Format, videoFormat)
  65 +
  66 +/*!
  67 + * \ingroup formats
  68 + * \brief Retrieves an image from a webcam.
  69 + * \author Josh Klontz \cite jklontz
  70 + */
  71 +class webcamFormat : public Format
  72 +{
  73 + Q_OBJECT
  74 +
  75 + Template read() const
  76 + {
  77 + static QScopedPointer<VideoCapture> videoCapture;
  78 +
  79 + if (videoCapture.isNull())
  80 + videoCapture.reset(new VideoCapture(0));
  81 +
  82 + Mat m;
  83 + videoCapture->read(m);
  84 + return Template(m);
  85 + }
  86 +
  87 + void write(const Template &t) const
  88 + {
  89 + (void) t;
  90 + qFatal("Not supported.");
  91 + }
  92 +};
  93 +
  94 +BR_REGISTER(Format, webcamFormat)
  95 +
  96 +/*!
  97 + * \ingroup formats
  98 + * \brief Reads image files.
  99 + * \author Josh Klontz \cite jklontz
  100 + */
  101 +class DefaultFormat : public Format
  102 +{
  103 + Q_OBJECT
  104 +
  105 + Template read() const
  106 + {
  107 + Template t;
  108 +
  109 + if (file.name.startsWith("http://") || file.name.startsWith("https://") || file.name.startsWith("www.")) {
  110 + if (Factory<Format>::names().contains("url")) {
  111 + File urlFile = file;
  112 + urlFile.name.append(".url");
  113 + QScopedPointer<Format> url(Factory<Format>::make(urlFile));
  114 + t = url->read();
  115 + }
  116 + } else {
  117 + Mat m = imread(file.resolved().toStdString());
  118 + if (m.data) {
  119 + t.append(m);
  120 + } else {
  121 + videoFormat videoReader;
  122 + videoReader.file = file;
  123 + t = videoReader.read();
  124 + }
  125 + }
  126 +
  127 + return t;
  128 + }
  129 +
  130 + void write(const Template &t) const
  131 + {
  132 + if (t.size() > 1) {
  133 + videoFormat videoWriter;
  134 + videoWriter.file = file;
  135 + videoWriter.write(t);
  136 + } else if (t.size() == 1) {
  137 + QtUtils::touchDir(QDir(file.path()));
  138 + imwrite(file.name.toStdString(), t);
  139 + }
  140 + }
  141 +};
  142 +
  143 +BR_REGISTER(Format, DefaultFormat)
  144 +
  145 +} // namespace br
  146 +
  147 +#include "video.moc"
... ...
openbr/plugins/format/xml.cpp 0 → 100644
  1 +#ifndef BR_EMBEDDED
  2 +#include <QtXml>
  3 +#endif // BR_EMBEDDED
  4 +#include <opencv2/highgui/highgui.hpp>
  5 +
  6 +#include <openbr/plugins/openbr_internal.h>
  7 +#include <openbr/core/qtutils.h>
  8 +
  9 +using namespace cv;
  10 +
  11 +namespace br
  12 +{
  13 +
  14 +/*!
  15 + * \ingroup formats
  16 + * \brief Decodes images from Base64 xml
  17 + * \author Scott Klum \cite sklum
  18 + * \author Josh Klontz \cite jklontz
  19 + */
  20 +class xmlFormat : public Format
  21 +{
  22 + Q_OBJECT
  23 +
  24 + Template read() const
  25 + {
  26 + Template t;
  27 +
  28 +#ifndef BR_EMBEDDED
  29 + QString fileName = file.get<QString>("path") + file.name;
  30 +
  31 + QDomDocument doc(fileName);
  32 + QFile f(fileName);
  33 +
  34 + if (!f.open(QIODevice::ReadOnly)) qFatal("Unable to open %s for reading.", qPrintable(file.flat()));
  35 + if (!doc.setContent(&f)) qWarning("Unable to parse %s.", qPrintable(file.flat()));
  36 + f.close();
  37 +
  38 + QDomElement docElem = doc.documentElement();
  39 + QDomNode subject = docElem.firstChild();
  40 + while (!subject.isNull()) {
  41 + QDomNode fileNode = subject.firstChild();
  42 +
  43 + while (!fileNode.isNull()) {
  44 + QDomElement e = fileNode.toElement();
  45 +
  46 + if (e.tagName() == "FORMAL_IMG") {
  47 + QByteArray byteArray = QByteArray::fromBase64(qPrintable(e.text()));
  48 + Mat m = imdecode(Mat(3, byteArray.size(), CV_8UC3, byteArray.data()), CV_LOAD_IMAGE_COLOR);
  49 + if (!m.data) qWarning("xmlFormat::read failed to decode image data.");
  50 + t.append(m);
  51 + } else if ((e.tagName() == "RELEASE_IMG") ||
  52 + (e.tagName() == "PREBOOK_IMG") ||
  53 + (e.tagName() == "LPROFILE") ||
  54 + (e.tagName() == "RPROFILE")) {
  55 + // Ignore these other image fields for now
  56 + } else {
  57 + t.file.set(e.tagName(), e.text());
  58 + }
  59 +
  60 + fileNode = fileNode.nextSibling();
  61 + }
  62 + subject = subject.nextSibling();
  63 + }
  64 +
  65 + // Calculate age
  66 + if (t.file.contains("DOB")) {
  67 + const QDate dob = QDate::fromString(t.file.get<QString>("DOB").left(10), "yyyy-MM-dd");
  68 + const QDate current = QDate::currentDate();
  69 + int age = current.year() - dob.year();
  70 + if (current.month() < dob.month()) age--;
  71 + t.file.set("Age", age);
  72 + }
  73 +#endif // BR_EMBEDDED
  74 +
  75 + return t;
  76 + }
  77 +
  78 + void write(const Template &t) const
  79 + {
  80 + QStringList lines;
  81 + lines.append("<?xml version=\"1.0\" standalone=\"yes\"?>");
  82 + lines.append("<openbr-xml-format>");
  83 + lines.append("\t<xml-data>");
  84 + foreach (const QString &key, t.file.localKeys()) {
  85 + if ((key == "Index") || (key == "Label")) continue;
  86 + lines.append("\t\t<"+key+">"+QtUtils::toString(t.file.value(key))+"</"+key+">");
  87 + }
  88 + std::vector<uchar> data;
  89 + imencode(".jpg",t.m(),data);
  90 + QByteArray byteArray = QByteArray::fromRawData((const char*)data.data(), data.size());
  91 + lines.append("\t\t<FORMAL_IMG>"+byteArray.toBase64()+"</FORMAL_IMG>");
  92 + lines.append("\t</xml-data>");
  93 + lines.append("</openbr-xml-format>");
  94 + QtUtils::writeFile(file, lines);
  95 + }
  96 +};
  97 +
  98 +BR_REGISTER(Format, xmlFormat)
  99 +
  100 +} // namespace br
  101 +
  102 +#include "xml.moc"
... ...
openbr/plugins/gui.cpp
... ... @@ -928,6 +928,54 @@ public:
928 928  
929 929 BR_REGISTER(Transform, SurveyTransform)
930 930  
  931 +class FilterTransform : public ShowTransform
  932 +{
  933 + Q_OBJECT
  934 +
  935 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  936 + {
  937 + if (Globals->parallelism > 1)
  938 + qFatal("FilterTransform cannot execute in parallel.");
  939 +
  940 + if (src.empty())
  941 + return;
  942 +
  943 + foreach (const Template &t, src) {
  944 + Template u(t.file);
  945 + foreach (const cv::Mat &m, t) {
  946 + qImageBuffer = toQImage(m);
  947 + displayBuffer->convertFromImage(qImageBuffer);
  948 +
  949 + emit updateImage(displayBuffer->copy(displayBuffer->rect()));
  950 +
  951 + // Blocking wait for a key-press
  952 + if (this->waitInput) {
  953 + QString answer = p_window->waitForKeyPress();
  954 + qDebug() << answer;
  955 + if (answer == "y")
  956 + u.append(m);
  957 + }
  958 + }
  959 + if (!u.empty())
  960 + dst.append(u);
  961 + }
  962 + }
  963 + PromptWindow *p_window;
  964 +
  965 +
  966 + void init()
  967 + {
  968 + if (!Globals->useGui)
  969 + return;
  970 +
  971 + initActual<PromptWindow>();
  972 + p_window = (PromptWindow *) window;
  973 +
  974 + emit changeTitle("Keep: y Discard: n");
  975 + }
  976 +};
  977 +
  978 +BR_REGISTER(Transform, FilterTransform)
931 979  
932 980 /*!
933 981 * \ingroup transforms
... ...
openbr/plugins/gui/adjacentoverlay.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Load the image named in the specified property, draw it on the current matrix adjacent to the rect specified in the other property.
  13 + * \author Charles Otto \cite caotto
  14 + */
  15 +class AdjacentOverlayTransform : public Transform
  16 +{
  17 + Q_OBJECT
  18 +
  19 + Q_PROPERTY(QString imgName READ get_imgName WRITE set_imgName RESET reset_imgName STORED false)
  20 + Q_PROPERTY(QString targetName READ get_targetName WRITE set_targetName RESET reset_targetName STORED false)
  21 + BR_PROPERTY(QString, imgName, "")
  22 + BR_PROPERTY(QString, targetName, "")
  23 +
  24 + QSharedPointer<Transform> opener;
  25 + void project(const Template &src, Template &dst) const
  26 + {
  27 + dst = src;
  28 +
  29 + if (imgName.isEmpty() || targetName.isEmpty() || !dst.file.contains(imgName) || !dst.file.contains(targetName))
  30 + return;
  31 +
  32 + QVariant temp = src.file.value(imgName);
  33 + cv::Mat im;
  34 + // is this a filename?
  35 + if (temp.canConvert<QString>()) {
  36 + QString im_name = temp.toString();
  37 + Template temp_im;
  38 + opener->project(File(im_name), temp_im);
  39 + im = temp_im.m();
  40 + }
  41 + // a cv::Mat ?
  42 + else if (temp.canConvert<cv::Mat>())
  43 + im = src.file.get<cv::Mat>(imgName);
  44 + else
  45 + qDebug() << "Unrecognized property type " << imgName << "for" << src.file.name;
  46 +
  47 + // Location of detected face in source image
  48 + QRectF target_location = src.file.get<QRectF>(targetName);
  49 +
  50 + // match width with target region
  51 + qreal target_width = target_location.width();
  52 + qreal current_width = im.cols;
  53 + qreal current_height = im.rows;
  54 +
  55 + qreal aspect_ratio = current_height / current_width;
  56 + qreal target_height = target_width * aspect_ratio;
  57 +
  58 + cv::resize(im, im, cv::Size(target_width, target_height));
  59 +
  60 + // ROI used to maybe crop the matched image
  61 + cv::Rect clip_roi;
  62 + clip_roi.x = 0;
  63 + clip_roi.y = 0;
  64 + clip_roi.width = im.cols;
  65 + clip_roi.height= im.rows <= dst.m().rows ? im.rows : dst.m().rows;
  66 +
  67 + int half_width = src.m().cols / 2;
  68 + int out_x = 0;
  69 +
  70 + // place in the source image we will copy the matched image to.
  71 + cv::Rect target_roi;
  72 + bool left_side = false;
  73 + int width_adjust = 0;
  74 + // Place left
  75 + if (target_location.center().rx() > half_width) {
  76 + out_x = target_location.left() - im.cols;
  77 + if (out_x < 0) {
  78 + width_adjust = abs(out_x);
  79 + out_x = 0;
  80 + }
  81 + left_side = true;
  82 + }
  83 + // place right
  84 + else {
  85 + out_x = target_location.right();
  86 + int high = out_x + im.cols;
  87 + if (high >= src.m().cols) {
  88 + width_adjust = abs(high - src.m().cols + 1);
  89 + }
  90 + }
  91 +
  92 + cv::Mat outIm;
  93 + if (width_adjust)
  94 + {
  95 + outIm.create(dst.m().rows, dst.m().cols + width_adjust, CV_8UC3);
  96 + memset(outIm.data, 127, outIm.rows * outIm.cols * outIm.channels());
  97 +
  98 + Rect temp;
  99 +
  100 + if (left_side)
  101 + temp = Rect(abs(width_adjust), 0, dst.m().cols, dst.m().rows);
  102 +
  103 + else
  104 + temp = Rect(0, 0, dst.m().cols, dst.m().rows);
  105 +
  106 + dst.m().copyTo(outIm(temp));
  107 +
  108 + }
  109 + else
  110 + outIm = dst.m();
  111 +
  112 + if (clip_roi.height + target_location.top() >= outIm.rows)
  113 + {
  114 + clip_roi.height -= abs(outIm.rows - (clip_roi.height + target_location.top() ));
  115 + }
  116 + if (clip_roi.x + clip_roi.width >= im.cols) {
  117 + clip_roi.width -= abs(im.cols - (clip_roi.x + clip_roi.width + 1));
  118 + if (clip_roi.width < 0)
  119 + clip_roi.width = 1;
  120 + }
  121 +
  122 + if (clip_roi.y + clip_roi.height >= im.rows) {
  123 + clip_roi.height -= abs(im.rows - (clip_roi.y + clip_roi.height + 1));
  124 + }
  125 + if (clip_roi.x < 0)
  126 + clip_roi.x = 0;
  127 + if (clip_roi.y < 0)
  128 + clip_roi.y = 0;
  129 +
  130 + if (clip_roi.height < 0)
  131 + clip_roi.height = 0;
  132 +
  133 + if (clip_roi.width < 0)
  134 + clip_roi.width = 0;
  135 +
  136 +
  137 + if (clip_roi.y + clip_roi.height >= im.rows)
  138 + {
  139 + qDebug() << "Bad clip y" << clip_roi.y + clip_roi.height << im.rows;
  140 + }
  141 + if (clip_roi.x + clip_roi.width >= im.cols)
  142 + {
  143 + qDebug() << "Bad clip x" << clip_roi.x + clip_roi.width << im.cols;
  144 + }
  145 +
  146 + if (clip_roi.y < 0 || clip_roi.height < 0)
  147 + {
  148 + qDebug() << "bad clip y, low" << clip_roi.y << clip_roi.height;
  149 + qFatal("die");
  150 + }
  151 + if (clip_roi.x < 0 || clip_roi.width < 0)
  152 + {
  153 + qDebug() << "bad clip x, low" << clip_roi.x << clip_roi.width;
  154 + qFatal("die");
  155 + }
  156 +
  157 + target_roi.x = out_x;
  158 + target_roi.width = clip_roi.width;
  159 + target_roi.y = target_location.top();
  160 + target_roi.height = clip_roi.height;
  161 +
  162 +
  163 + im = im(clip_roi);
  164 +
  165 + if (target_roi.x < 0 || target_roi.x >= outIm.cols)
  166 + {
  167 + qDebug() << "Bad xdim in targetROI!" << target_roi.x << " out im x: " << outIm.cols;
  168 + qFatal("die");
  169 + }
  170 +
  171 + if (target_roi.x + target_roi.width < 0 || (target_roi.x + target_roi.width) >= outIm.cols)
  172 + {
  173 + qDebug() << "Bad xdim in targetROI!" << target_roi.x + target_roi.width;
  174 + qFatal("die");
  175 + }
  176 +
  177 + if (target_roi.y < 0 || target_roi.y >= outIm.rows)
  178 + {
  179 + qDebug() << "Bad ydim in targetROI!" << target_roi.y;
  180 + qFatal("die");
  181 + }
  182 +
  183 + if ((target_roi.y + target_roi.height) < 0 || (target_roi.y + target_roi.height) > outIm.rows)
  184 + {
  185 + qDebug() << "Bad ydim in targetROI!" << target_roi.y + target_roi.height;
  186 + qDebug() << "target_roi.y: " << target_roi.y << " height: " << target_roi.height;
  187 + qFatal("die");
  188 + }
  189 +
  190 +
  191 + std::vector<cv::Mat> channels;
  192 + cv::split(outIm, channels);
  193 +
  194 + std::vector<cv::Mat> patch_channels;
  195 + cv::split(im, patch_channels);
  196 +
  197 + for (size_t i=0; i < channels.size(); i++)
  198 + {
  199 + cv::addWeighted(channels[i](target_roi), 0, patch_channels[i % patch_channels.size()], 1, 0,channels[i](target_roi));
  200 + }
  201 + cv::merge(channels, outIm);
  202 + dst.m() = outIm;
  203 +
  204 + }
  205 +
  206 + void init()
  207 + {
  208 + opener = QSharedPointer<br::Transform>(br::Transform::make("Cache(Open)", NULL));
  209 + }
  210 +
  211 +};
  212 +
  213 +BR_REGISTER(Transform, AdjacentOverlayTransform)
  214 +
  215 +} // namespace br
  216 +
  217 +#include "adjacentoverlay.moc"
... ...
openbr/plugins/gui/draw.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup transforms
  11 + * \brief Renders metadata onto the image.
  12 + *
  13 + * The inPlace argument controls whether or not the image is cloned before the metadata is drawn.
  14 + *
  15 + * \author Josh Klontz \cite jklontz
  16 + */
  17 +class DrawTransform : public UntrainableTransform
  18 +{
  19 + Q_OBJECT
  20 + Q_PROPERTY(bool verbose READ get_verbose WRITE set_verbose RESET reset_verbose STORED false)
  21 + Q_PROPERTY(bool points READ get_points WRITE set_points RESET reset_points STORED false)
  22 + Q_PROPERTY(bool rects READ get_rects WRITE set_rects RESET reset_rects STORED false)
  23 + Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false)
  24 + Q_PROPERTY(int lineThickness READ get_lineThickness WRITE set_lineThickness RESET reset_lineThickness STORED false)
  25 + Q_PROPERTY(bool named READ get_named WRITE set_named RESET reset_named STORED false)
  26 + Q_PROPERTY(bool location READ get_location WRITE set_location RESET reset_location STORED false)
  27 + BR_PROPERTY(bool, verbose, false)
  28 + BR_PROPERTY(bool, points, true)
  29 + BR_PROPERTY(bool, rects, true)
  30 + BR_PROPERTY(bool, inPlace, false)
  31 + BR_PROPERTY(int, lineThickness, 1)
  32 + BR_PROPERTY(bool, named, true)
  33 + BR_PROPERTY(bool, location, true)
  34 +
  35 + void project(const Template &src, Template &dst) const
  36 + {
  37 + const Scalar color(0,255,0);
  38 + const Scalar verboseColor(255, 255, 0);
  39 + dst.m() = inPlace ? src.m() : src.m().clone();
  40 +
  41 + if (points) {
  42 + const QList<Point2f> pointsList = (named) ? OpenCVUtils::toPoints(src.file.points()+src.file.namedPoints()) : OpenCVUtils::toPoints(src.file.points());
  43 + for (int i=0; i<pointsList.size(); i++) {
  44 + const Point2f &point = pointsList[i];
  45 + circle(dst, point, 3, color, -1);
  46 + QString label = (location) ? QString("%1,(%2,%3)").arg(QString::number(i),QString::number(point.x),QString::number(point.y)) : QString("%1").arg(QString::number(i));
  47 + if (verbose) putText(dst, label.toStdString(), point, FONT_HERSHEY_SIMPLEX, 0.5, verboseColor, 1);
  48 + }
  49 + }
  50 + if (rects) {
  51 + foreach (const Rect &rect, OpenCVUtils::toRects(src.file.namedRects() + src.file.rects()))
  52 + rectangle(dst, rect, color, lineThickness);
  53 + }
  54 + }
  55 +};
  56 +
  57 +BR_REGISTER(Transform, DrawTransform)
  58 +
  59 +} // namespace br
  60 +
  61 +#include "draw.moc"
... ...
openbr/plugins/gui/drawgridlines.cpp 0 → 100644
  1 +#include <opencv2/highgui/highgui.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Draws a grid on the image
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class DrawGridLinesTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 + Q_PROPERTY(int rows READ get_rows WRITE set_rows RESET reset_rows STORED false)
  19 + Q_PROPERTY(int columns READ get_columns WRITE set_columns RESET reset_columns STORED false)
  20 + Q_PROPERTY(int r READ get_r WRITE set_r RESET reset_r STORED false)
  21 + Q_PROPERTY(int g READ get_g WRITE set_g RESET reset_g STORED false)
  22 + Q_PROPERTY(int b READ get_b WRITE set_b RESET reset_b STORED false)
  23 + BR_PROPERTY(int, rows, 0)
  24 + BR_PROPERTY(int, columns, 0)
  25 + BR_PROPERTY(int, r, 196)
  26 + BR_PROPERTY(int, g, 196)
  27 + BR_PROPERTY(int, b, 196)
  28 +
  29 + void project(const Template &src, Template &dst) const
  30 + {
  31 + Mat m = src.m().clone();
  32 + float rowStep = 1.f * m.rows / (rows+1);
  33 + float columnStep = 1.f * m.cols / (columns+1);
  34 + int thickness = qMin(m.rows, m.cols) / 256;
  35 + for (float row = rowStep/2; row < m.rows; row += rowStep)
  36 + line(m, Point(0, row), Point(m.cols, row), Scalar(r, g, b), thickness, CV_AA);
  37 + for (float column = columnStep/2; column < m.cols; column += columnStep)
  38 + line(m, Point(column, 0), Point(column, m.rows), Scalar(r, g, b), thickness, CV_AA);
  39 + dst = m;
  40 + }
  41 +};
  42 +
  43 +BR_REGISTER(Transform, DrawGridLinesTransform)
  44 +
  45 +} // namespace br
  46 +
  47 +#include "drawgridlines.moc"
... ...
openbr/plugins/gui/drawopticalflow.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup transforms
  11 + * \brief Draw a line representing the direction and magnitude of optical flow at the specified points.
  12 + * \author Austin Blanton \cite imaus10
  13 + */
  14 +class DrawOpticalFlow : public UntrainableTransform
  15 +{
  16 + Q_OBJECT
  17 + Q_PROPERTY(QString original READ get_original WRITE set_original RESET reset_original STORED false)
  18 + BR_PROPERTY(QString, original, "original")
  19 +
  20 + void project(const Template &src, Template &dst) const
  21 + {
  22 + const Scalar color(0,255,0);
  23 + Mat flow = src.m();
  24 + dst = src;
  25 + if (!dst.file.contains(original)) qFatal("The original img must be saved in the metadata with SaveMat.");
  26 + dst.m() = dst.file.get<Mat>(original);
  27 + dst.file.remove(original);
  28 + foreach (const Point2f &pt, OpenCVUtils::toPoints(dst.file.points())) {
  29 + Point2f dxy = flow.at<Point2f>(pt.y, pt.x);
  30 + Point2f newPt(pt.x+dxy.x, pt.y+dxy.y);
  31 + line(dst, pt, newPt, color);
  32 + }
  33 + }
  34 +};
  35 +
  36 +BR_REGISTER(Transform, DrawOpticalFlow)
  37 +
  38 +} // namespace br
  39 +
  40 +#include "drawopticalflow.moc"
... ...
openbr/plugins/gui/drawpropertiespoint.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup transforms
  11 + * \brief Draw the values of a list of properties at the specified point on the image
  12 + *
  13 + * The inPlace argument controls whether or not the image is cloned before it is drawn on.
  14 + *
  15 + * \author Charles Otto \cite caotto
  16 + */
  17 +class DrawPropertiesPointTransform : public UntrainableTransform
  18 +{
  19 + Q_OBJECT
  20 + Q_PROPERTY(QStringList propNames READ get_propNames WRITE set_propNames RESET reset_propNames STORED false)
  21 + Q_PROPERTY(QString pointName READ get_pointName WRITE set_pointName RESET reset_pointName STORED false)
  22 + Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false)
  23 + BR_PROPERTY(QStringList, propNames, QStringList())
  24 + BR_PROPERTY(QString, pointName, "")
  25 + BR_PROPERTY(bool, inPlace, false)
  26 +
  27 + void project(const Template &src, Template &dst) const
  28 + {
  29 + dst = src;
  30 + if (propNames.isEmpty() || pointName.isEmpty())
  31 + return;
  32 +
  33 + dst.m() = inPlace ? src.m() : src.m().clone();
  34 +
  35 + QVariant point = dst.file.value(pointName);
  36 +
  37 + if (!point.canConvert(QVariant::PointF))
  38 + return;
  39 +
  40 + QPointF targetPoint = point.toPointF();
  41 +
  42 + Point2f cvPoint = OpenCVUtils::toPoint(targetPoint);
  43 +
  44 +
  45 + const Scalar textColor(255, 255, 0);
  46 +
  47 + std::string outString = "";
  48 + foreach (const QString &propName, propNames)
  49 + {
  50 + QVariant prop = dst.file.value(propName);
  51 +
  52 + if (!prop.canConvert(QVariant::String))
  53 + continue;
  54 + QString propString = prop.toString();
  55 + outString += propName.toStdString() + ": " + propString.toStdString() + " ";
  56 +
  57 + }
  58 + if (outString.empty())
  59 + return;
  60 +
  61 + putText(dst, outString, cvPoint, FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1);
  62 + }
  63 +
  64 +};
  65 +
  66 +BR_REGISTER(Transform, DrawPropertiesPointTransform)
  67 +
  68 +} // namespace br
  69 +
  70 +#include "drawpropertiespoint.moc"
... ...
openbr/plugins/gui/drawpropertypoint.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup transforms
  11 + * \brief Draw the value of the specified property at the specified point on the image
  12 + *
  13 + * The inPlace argument controls whether or not the image is cloned before it is drawn on.
  14 + *
  15 + * \author Charles Otto \cite caotto
  16 + */
  17 +class DrawPropertyPointTransform : public UntrainableTransform
  18 +{
  19 + Q_OBJECT
  20 + Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false)
  21 + Q_PROPERTY(QString pointName READ get_pointName WRITE set_pointName RESET reset_pointName STORED false)
  22 + Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false)
  23 + BR_PROPERTY(QString, propName, "")
  24 + BR_PROPERTY(QString, pointName, "")
  25 + BR_PROPERTY(bool, inPlace, false)
  26 +
  27 +
  28 + void project(const Template &src, Template &dst) const
  29 + {
  30 + dst = src;
  31 + if (propName.isEmpty() || pointName.isEmpty())
  32 + return;
  33 +
  34 + dst.m() = inPlace ? src.m() : src.m().clone();
  35 +
  36 + const Scalar textColor(255, 255, 0);
  37 +
  38 + QVariant prop = dst.file.value(propName);
  39 +
  40 +
  41 + if (!prop.canConvert(QVariant::String))
  42 + return;
  43 + QString propString = prop.toString();
  44 +
  45 + QVariant point = dst.file.value(pointName);
  46 +
  47 + if (!point.canConvert(QVariant::PointF))
  48 + return;
  49 +
  50 + QPointF targetPoint = point.toPointF();
  51 +
  52 + Point2f cvPoint = OpenCVUtils::toPoint(targetPoint);
  53 +
  54 + std::string text = propName.toStdString() + ": " + propString.toStdString();
  55 + putText(dst, text, cvPoint, FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1);
  56 + }
  57 +
  58 +};
  59 +BR_REGISTER(Transform, DrawPropertyPointTransform)
  60 +
  61 +} // namespace br
  62 +
  63 +#include "drawpropertypoint.moc"
... ...
openbr/plugins/gui/drawsegmentation.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace std;
  6 +using namespace cv;
  7 +
  8 +namespace br
  9 +{
  10 +
  11 +/*!
  12 + * \ingroup transforms
  13 + * \brief Fill in the segmentations or draw a line between intersecting segments.
  14 + * \author Austin Blanton \cite imaus10
  15 + */
  16 +class DrawSegmentation : public UntrainableTransform
  17 +{
  18 + Q_OBJECT
  19 + Q_PROPERTY(bool fillSegment READ get_fillSegment WRITE set_fillSegment RESET reset_fillSegment STORED false)
  20 + BR_PROPERTY(bool, fillSegment, true)
  21 +
  22 + void project(const Template &src, Template &dst) const
  23 + {
  24 + if (!src.file.contains("SegmentsMask") || !src.file.contains("NumSegments")) qFatal("Must supply a Contours object in the metadata to drawContours.");
  25 + Mat segments = src.file.get<Mat>("SegmentsMask");
  26 + int numSegments = src.file.get<int>("NumSegments");
  27 +
  28 + dst.file = src.file;
  29 + Mat drawn = fillSegment ? Mat(segments.size(), CV_8UC3, Scalar::all(0)) : src.m();
  30 +
  31 + for (int i=1; i<numSegments+1; i++) {
  32 + Mat mask = segments == i;
  33 + if (fillSegment) { // color the whole segment
  34 + // set to a random color - get ready for a craaaazy acid trip
  35 + int b = theRNG().uniform(0, 255);
  36 + int g = theRNG().uniform(0, 255);
  37 + int r = theRNG().uniform(0, 255);
  38 + drawn.setTo(Scalar(r,g,b), mask);
  39 + } else { // draw lines where there's a color change
  40 + vector<vector<Point> > contours;
  41 + Scalar color(0,255,0);
  42 + findContours(mask, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
  43 + drawContours(drawn, contours, -1, color);
  44 + }
  45 + }
  46 +
  47 + dst.m() = drawn;
  48 + }
  49 +};
  50 +
  51 +BR_REGISTER(Transform, DrawSegmentation)
  52 +
  53 +} // namespace br
  54 +
  55 +#include "drawsegmentation.moc"
... ...
openbr/plugins/imgproc/abs.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Computes the absolute value of each element.
  9 + * \author Josh Klontz \cite jklontz
  10 + */
  11 +class AbsTransform : public UntrainableTransform
  12 +{
  13 + Q_OBJECT
  14 +
  15 + void project(const Template &src, Template &dst) const
  16 + {
  17 + dst = cv::abs(src);
  18 + }
  19 +};
  20 +
  21 +BR_REGISTER(Transform, AbsTransform)
  22 +
  23 +} // namespace br
  24 +
  25 +#include "abs.moc"
... ...
openbr/plugins/imgproc/blend.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Alpha-blend two matrices
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class BlendTransform : public UntrainableMetaTransform
  14 +{
  15 + Q_OBJECT
  16 + Q_PROPERTY(float alpha READ get_alpha WRITE set_alpha RESET reset_alpha STORED false)
  17 + BR_PROPERTY(float, alpha, 0.5)
  18 +
  19 + void project(const Template &src, Template &dst) const
  20 + {
  21 + if (src.size() != 2) qFatal("Expected two source matrices.");
  22 + addWeighted(src[0], alpha, src[1], 1-alpha, 0, dst);
  23 + }
  24 +};
  25 +
  26 +BR_REGISTER(Transform, BlendTransform)
  27 +
  28 +} // namespace br
  29 +
  30 +#include "blend.moc"
... ...
openbr/plugins/imgproc/blur.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Gaussian blur
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class BlurTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 + Q_PROPERTY(float sigma READ get_sigma WRITE set_sigma RESET reset_sigma STORED false)
  19 + Q_PROPERTY(bool ROI READ get_ROI WRITE set_ROI RESET reset_ROI STORED false)
  20 + BR_PROPERTY(float, sigma, 1)
  21 + BR_PROPERTY(bool, ROI, false)
  22 +
  23 + void project(const Template &src, Template &dst) const
  24 + {
  25 + if (!ROI) GaussianBlur(src, dst, Size(0,0), sigma);
  26 + else {
  27 + dst.m() = src.m();
  28 + foreach (const QRectF &rect, src.file.rects()) {
  29 + Rect region(rect.x(), rect.y(), rect.width(), rect.height());
  30 + Mat input = dst.m();
  31 + Mat output = input.clone();
  32 + GaussianBlur(input(region), output(region), Size(0,0), sigma);
  33 + dst.m() = output;
  34 + }
  35 + }
  36 + }
  37 +};
  38 +
  39 +BR_REGISTER(Transform, BlurTransform)
  40 +
  41 +} // namespace br
  42 +
  43 +#include "blur.moc"
... ...
openbr/plugins/imgproc/contrasteq.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/tanh_sse.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup transforms
  11 + * \brief Xiaoyang Tan; Triggs, B.;
  12 + * "Enhanced Local Texture Feature Sets for Face Recognition Under Difficult Lighting Conditions,"
  13 + * Image Processing, IEEE Transactions on , vol.19, no.6, pp.1635-1650, June 2010
  14 + * \author Josh Klontz \cite jklontz
  15 + */
  16 +class ContrastEqTransform : public UntrainableTransform
  17 +{
  18 + Q_OBJECT
  19 + Q_PROPERTY(float a READ get_a WRITE set_a RESET reset_a STORED false)
  20 + Q_PROPERTY(float t READ get_t WRITE set_t RESET reset_t STORED false)
  21 + BR_PROPERTY(float, a, 1)
  22 + BR_PROPERTY(float, t, 0.1)
  23 +
  24 + void project(const Template &src, Template &dst) const
  25 + {
  26 + if (src.m().channels() != 1) qFatal("Expected single channel source matrix.");
  27 +
  28 + // Stage 1
  29 + Mat stage1;
  30 + {
  31 + Mat abs_dst;
  32 + absdiff(src, Scalar(0), abs_dst);
  33 + Mat pow_dst;
  34 + pow(abs_dst, a, pow_dst);
  35 + float denominator = pow((float)mean(pow_dst)[0], 1.f/a);
  36 + src.m().convertTo(stage1, CV_32F, 1/denominator);
  37 + }
  38 +
  39 + // Stage 2
  40 + Mat stage2;
  41 + {
  42 + Mat abs_dst;
  43 + absdiff(stage1, Scalar(0), abs_dst);
  44 + Mat min_dst;
  45 + min(abs_dst, t, min_dst);
  46 + Mat pow_dst;
  47 + pow(min_dst, a, pow_dst);
  48 + float denominator = pow((float)mean(pow_dst)[0], 1.f/a);
  49 + stage1.convertTo(stage2, CV_32F, 1/denominator);
  50 + }
  51 +
  52 + // Hyperbolic tangent
  53 + const int nRows = src.m().rows;
  54 + const int nCols = src.m().cols;
  55 + const float* p = (const float*)stage2.ptr();
  56 + Mat m(nRows, nCols, CV_32FC1);
  57 + for (int i=0; i<nRows; i++)
  58 + for (int j=0; j<nCols; j++)
  59 + m.at<float>(i, j) = fast_tanh(p[i*nCols+j]);
  60 + // TODO: m.at<float>(i, j) = t * fast_tanh(p[i*nCols+j] / t);
  61 +
  62 + dst = m;
  63 + }
  64 +};
  65 +
  66 +BR_REGISTER(Transform, ContrastEqTransform)
  67 +
  68 +} // namespace br
  69 +
  70 +#include "contrasteq.moc"
... ...
openbr/plugins/imgproc/crop.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Crops about the specified region of interest.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class CropTransform : public UntrainableTransform
  14 +{
  15 + Q_OBJECT
  16 + Q_PROPERTY(int x READ get_x WRITE set_x RESET reset_x STORED false)
  17 + Q_PROPERTY(int y READ get_y WRITE set_y RESET reset_y STORED false)
  18 + Q_PROPERTY(int width READ get_width WRITE set_width RESET reset_width STORED false)
  19 + Q_PROPERTY(int height READ get_height WRITE set_height RESET reset_height STORED false)
  20 + BR_PROPERTY(int, x, 0)
  21 + BR_PROPERTY(int, y, 0)
  22 + BR_PROPERTY(int, width, -1)
  23 + BR_PROPERTY(int, height, -1)
  24 +
  25 + void project(const Template &src, Template &dst) const
  26 + {
  27 + dst = Mat(src, Rect(x, y, width < 1 ? src.m().cols-x-abs(width) : width, height < 1 ? src.m().rows-y-abs(height) : height));
  28 + }
  29 +};
  30 +
  31 +BR_REGISTER(Transform, CropTransform)
  32 +
  33 +} // namespace br
  34 +
  35 +#include "crop.moc"
... ...
openbr/plugins/imgproc/cropblack.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup transforms
  11 + * \brief Crop out black borders
  12 + * \author Josh Klontz \cite jklontz
  13 + */
  14 +class CropBlackTransform : public UntrainableTransform
  15 +{
  16 + Q_OBJECT
  17 +
  18 + void project(const Template &src, Template &dst) const
  19 + {
  20 + Mat gray;
  21 + OpenCVUtils::cvtGray(src, gray);
  22 +
  23 + int xStart = 0;
  24 + while (xStart < gray.cols) {
  25 + if (mean(gray.col(xStart))[0] >= 1) break;
  26 + xStart++;
  27 + }
  28 +
  29 + int xEnd = gray.cols - 1;
  30 + while (xEnd >= 0) {
  31 + if (mean(gray.col(xEnd))[0] >= 1) break;
  32 + xEnd--;
  33 + }
  34 +
  35 + int yStart = 0;
  36 + while (yStart < gray.rows) {
  37 + if (mean(gray.col(yStart))[0] >= 1) break;
  38 + yStart++;
  39 + }
  40 +
  41 + int yEnd = gray.rows - 1;
  42 + while (yEnd >= 0) {
  43 + if (mean(gray.col(yEnd))[0] >= 1) break;
  44 + yEnd--;
  45 + }
  46 +
  47 + dst = src.m()(Rect(xStart, yStart, xEnd-xStart, yEnd-yStart));
  48 + }
  49 +};
  50 +
  51 +BR_REGISTER(Transform, CropBlackTransform)
  52 +
  53 +} // namespace br
  54 +
  55 +#include "cropblack.moc"
... ...
openbr/plugins/imgproc/cropsquare.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Trim the image so the width and the height are the same size.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class CropSquareTransform : public UntrainableTransform
  14 +{
  15 + Q_OBJECT
  16 +
  17 + void project(const Template &src, Template &dst) const
  18 + {
  19 + const Mat &m = src;
  20 + const int newSize = min(m.rows, m.cols);
  21 + dst = Mat(m, Rect((m.cols-newSize)/2, (m.rows-newSize)/2, newSize, newSize));
  22 + }
  23 +};
  24 +
  25 +BR_REGISTER(Transform, CropSquareTransform)
  26 +
  27 +} // namespace br
  28 +
  29 +#include "cropsquare.moc"
... ...
openbr/plugins/imgproc/csdn.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace std;
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup transforms
  11 + * \brief Meyers, E.; Wolf, L.
  12 + * “Using biologically inspired features for face processing,”
  13 + * Int. Journal of Computer Vision, vol. 76, no. 1, pp 93–104, 2008.
  14 + * \author Scott Klum \cite sklum
  15 + */
  16 +
  17 +class CSDNTransform : public UntrainableTransform
  18 +{
  19 + Q_OBJECT
  20 +
  21 + Q_PROPERTY(float s READ get_s WRITE set_s RESET reset_s STORED false)
  22 + BR_PROPERTY(int, s, 16)
  23 +
  24 + void project(const Template &src, Template &dst) const
  25 + {
  26 + if (src.m().channels() != 1) qFatal("Expected single channel source matrix.");
  27 +
  28 + const int nRows = src.m().rows;
  29 + const int nCols = src.m().cols;
  30 +
  31 + Mat m;
  32 + src.m().convertTo(m, CV_32FC1);
  33 +
  34 + const int surround = s/2;
  35 +
  36 + for ( int i = 0; i < nRows; i++ ) {
  37 + for ( int j = 0; j < nCols; j++ ) {
  38 + int width = min( j+surround, nCols ) - max( 0, j-surround );
  39 + int height = min( i+surround, nRows ) - max( 0, i-surround );
  40 +
  41 + Rect_<int> ROI(max(0, j-surround), max(0, i-surround), width, height);
  42 +
  43 + Scalar_<float> avg = mean(m(ROI));
  44 +
  45 + m.at<float>(i,j) = m.at<float>(i,j) - avg[0];
  46 + }
  47 + }
  48 +
  49 + dst = m;
  50 +
  51 + }
  52 +};
  53 +
  54 +BR_REGISTER(Transform, CSDNTransform)
  55 +
  56 +} // namespace br
  57 +
  58 +#include "csdn.moc"
... ...
openbr/plugins/imgproc/cvtcolor.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Colorspace conversion.
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class CvtColorTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 + Q_ENUMS(ColorSpace)
  19 + Q_PROPERTY(ColorSpace colorSpace READ get_colorSpace WRITE set_colorSpace RESET reset_colorSpace STORED false)
  20 + Q_PROPERTY(int channel READ get_channel WRITE set_channel RESET reset_channel STORED false)
  21 +
  22 +public:
  23 + enum ColorSpace { Gray = CV_BGR2GRAY,
  24 + RGBGray = CV_RGB2GRAY,
  25 + HLS = CV_BGR2HLS,
  26 + HSV = CV_BGR2HSV,
  27 + Lab = CV_BGR2Lab,
  28 + Luv = CV_BGR2Luv,
  29 + RGB = CV_BGR2RGB,
  30 + XYZ = CV_BGR2XYZ,
  31 + YCrCb = CV_BGR2YCrCb,
  32 + Color = CV_GRAY2BGR };
  33 +
  34 +private:
  35 + BR_PROPERTY(ColorSpace, colorSpace, Gray)
  36 + BR_PROPERTY(int, channel, -1)
  37 +
  38 + void project(const Template &src, Template &dst) const
  39 + {
  40 + if (src.m().channels() > 1 || colorSpace == CV_GRAY2BGR) cvtColor(src, dst, colorSpace);
  41 + else dst = src;
  42 +
  43 + if (channel != -1) {
  44 + std::vector<Mat> mv;
  45 + split(dst, mv);
  46 + dst = mv[channel % (int)mv.size()];
  47 + }
  48 + }
  49 +};
  50 +
  51 +BR_REGISTER(Transform, CvtColorTransform)
  52 +
  53 +} // namespace br
  54 +
  55 +#include "cvtcolor.moc"
... ...
openbr/plugins/imgproc/cvtfloat.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Convert to floating point format.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class CvtFloatTransform : public UntrainableTransform
  14 +{
  15 + Q_OBJECT
  16 +
  17 + void project(const Template &src, Template &dst) const
  18 + {
  19 + src.m().convertTo(dst, CV_32F);
  20 + }
  21 +};
  22 +
  23 +BR_REGISTER(Transform, CvtFloatTransform)
  24 +
  25 +} // namespace br
  26 +
  27 +#include "cvtfloat.moc"
... ...
openbr/plugins/imgproc/cvtuchar.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
  3 +
  4 +namespace br
  5 +{
  6 +
  7 +/*!
  8 + * \ingroup transforms
  9 + * \brief Convert to uchar format
  10 + * \author Josh Klontz \cite jklontz
  11 + */
  12 +class CvtUCharTransform : public UntrainableTransform
  13 +{
  14 + Q_OBJECT
  15 +
  16 + void project(const Template &src, Template &dst) const
  17 + {
  18 + OpenCVUtils::cvtUChar(src, dst);
  19 + }
  20 +};
  21 +
  22 +BR_REGISTER(Transform, CvtUCharTransform)
  23 +
  24 +} // namespace br
  25 +
  26 +#include "cvtuchar.moc"
... ...
openbr/plugins/denoising.cpp renamed to openbr/plugins/imgproc/denoising.cpp
... ... @@ -15,7 +15,8 @@
15 15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 16  
17 17 #include <opencv2/photo/photo.hpp>
18   -#include "openbr_internal.h"
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
19 20  
20 21 using namespace cv;
21 22  
... ...
openbr/plugins/imgproc/discardalpha.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Drop the alpha channel (if exists).
  13 + * \author Austin Blanton \cite imaus10
  14 + */
  15 +class DiscardAlphaTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 +
  19 + void project(const Template &src, Template &dst) const
  20 + {
  21 + if (src.m().channels() > 4 || src.m().channels() == 2) {
  22 + dst.file.fte = true;
  23 + return;
  24 + }
  25 +
  26 + dst = src;
  27 + if (src.m().channels() == 4) {
  28 + std::vector<Mat> mv;
  29 + split(src, mv);
  30 + mv.pop_back();
  31 + merge(mv, dst);
  32 + }
  33 + }
  34 +};
  35 +
  36 +BR_REGISTER(Transform, DiscardAlphaTransform)
  37 +
  38 +} // namespace br
  39 +
  40 +#include "discardalpha.moc"
... ...
openbr/plugins/imgproc/div.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Enforce a multiple of \em n columns.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class DivTransform : public UntrainableTransform
  14 +{
  15 + Q_OBJECT
  16 + Q_PROPERTY(int n READ get_n WRITE set_n RESET reset_n STORED false)
  17 + BR_PROPERTY(int, n, 1)
  18 +
  19 + void project(const Template &src, Template &dst) const
  20 + {
  21 + dst = Mat(src, Rect(0,0,n*(src.m().cols/n),src.m().rows));
  22 + }
  23 +};
  24 +
  25 +BR_REGISTER(Transform, DivTransform)
  26 +
  27 +} // namespace br
  28 +
  29 +#include "div.moc"
... ...
openbr/plugins/imgproc/dog.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Difference of gaussians
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class DoGTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 + Q_PROPERTY(float sigma0 READ get_sigma0 WRITE set_sigma0 RESET reset_sigma0 STORED false)
  19 + Q_PROPERTY(float sigma1 READ get_sigma1 WRITE set_sigma1 RESET reset_sigma1 STORED false)
  20 + BR_PROPERTY(float, sigma0, 1)
  21 + BR_PROPERTY(float, sigma1, 2)
  22 +
  23 + Size ksize0, ksize1;
  24 +
  25 + static Size getKernelSize(double sigma)
  26 + {
  27 + // Inverts OpenCV's conversion from kernel size to sigma:
  28 + // sigma = ((ksize-1)*0.5 - 1)*0.3 + 0.8
  29 + // See documentation for cv::getGaussianKernel()
  30 + int ksize = ((sigma - 0.8) / 0.3 + 1) * 2 + 1;
  31 + if (ksize % 2 == 0) ksize++;
  32 + return Size(ksize, ksize);
  33 + }
  34 +
  35 + void init()
  36 + {
  37 + ksize0 = getKernelSize(sigma0);
  38 + ksize1 = getKernelSize(sigma1);
  39 + }
  40 +
  41 + void project(const Template &src, Template &dst) const
  42 + {
  43 + Mat g0, g1;
  44 + GaussianBlur(src, g0, ksize0, 0);
  45 + GaussianBlur(src, g1, ksize1, 0);
  46 + subtract(g0, g1, dst);
  47 + }
  48 +};
  49 +
  50 +BR_REGISTER(Transform, DoGTransform)
  51 +
  52 +} // namespace br
  53 +
  54 +#include "dog.moc"
... ...
openbr/plugins/imgproc/ensurechannels.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Enforce the matrix has a certain number of channels by adding or removing channels.
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class EnsureChannelsTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 + Q_PROPERTY(int n READ get_n WRITE set_n RESET reset_n STORED false)
  19 + BR_PROPERTY(int, n, 1)
  20 +
  21 + void project(const Template &src, Template &dst) const
  22 + {
  23 + if (src.m().channels() == n) {
  24 + dst = src;
  25 + } else {
  26 + std::vector<Mat> mv;
  27 + split(src, mv);
  28 +
  29 + // Add extra channels
  30 + while ((int)mv.size() < n) {
  31 + for (int i=0; i<src.m().channels(); i++) {
  32 + mv.push_back(mv[i]);
  33 + if ((int)mv.size() == n)
  34 + break;
  35 + }
  36 + }
  37 +
  38 + // Remove extra channels
  39 + while ((int)mv.size() > n)
  40 + mv.pop_back();
  41 +
  42 + merge(mv, dst);
  43 + }
  44 + }
  45 +};
  46 +
  47 +BR_REGISTER(Transform, EnsureChannelsTransform)
  48 +
  49 +} // namespace br
  50 +
  51 +#include "ensurechannels.moc"
... ...
openbr/plugins/imgproc/flood.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Fill black pixels with the specified color.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class FloodTransform : public UntrainableTransform
  14 +{
  15 + Q_OBJECT
  16 + Q_PROPERTY(int r READ get_r WRITE set_r RESET reset_r STORED false)
  17 + Q_PROPERTY(int g READ get_g WRITE set_g RESET reset_g STORED false)
  18 + Q_PROPERTY(int b READ get_b WRITE set_b RESET reset_b STORED false)
  19 + Q_PROPERTY(bool all READ get_all WRITE set_all RESET reset_all STORED false)
  20 + BR_PROPERTY(int, r, 0)
  21 + BR_PROPERTY(int, g, 0)
  22 + BR_PROPERTY(int, b, 0)
  23 + BR_PROPERTY(bool, all, false)
  24 +
  25 + void project(const Template &src, Template &dst) const
  26 + {
  27 + dst = src.m().clone();
  28 + dst.m().setTo(Scalar(r, g, b), all ? Mat() : dst.m()==0);
  29 + }
  30 +};
  31 +
  32 +BR_REGISTER(Transform, FloodTransform)
  33 +
  34 +} // namespace br
  35 +
  36 +#include "flood.moc"
... ...
openbr/plugins/imgproc/gamma.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Gamma correction
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class GammaTransform : public UntrainableTransform
  14 +{
  15 + Q_OBJECT
  16 + Q_PROPERTY(float gamma READ get_gamma WRITE set_gamma RESET reset_gamma STORED false)
  17 + BR_PROPERTY(float, gamma, 0.2)
  18 +
  19 + Mat lut;
  20 +
  21 + void init()
  22 + {
  23 + lut.create(256, 1, CV_32FC1);
  24 + if (gamma == 0) for (int i=0; i<256; i++) lut.at<float>(i,0) = log((float)i);
  25 + else for (int i=0; i<256; i++) lut.at<float>(i,0) = pow(i, gamma);
  26 + }
  27 +
  28 + void project(const Template &src, Template &dst) const
  29 + {
  30 + if (src.m().depth() == CV_8U) LUT(src, lut, dst);
  31 + else pow(src, gamma, dst);
  32 + }
  33 +};
  34 +
  35 +BR_REGISTER(Transform, GammaTransform)
  36 +
  37 +} // namespace br
  38 +
  39 +#include "gamma.moc"
... ...
openbr/plugins/imgproc/gradient.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Computes magnitude and/or angle of image.
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class GradientTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 + Q_ENUMS(Channel)
  19 + Q_PROPERTY(Channel channel READ get_channel WRITE set_channel RESET reset_channel STORED false)
  20 +
  21 +public:
  22 + enum Channel { Magnitude, Angle, MagnitudeAndAngle };
  23 +
  24 +private:
  25 + BR_PROPERTY(Channel, channel, Angle)
  26 +
  27 + void project(const Template &src, Template &dst) const
  28 + {
  29 + Mat dx, dy, magnitude, angle;
  30 + Sobel(src, dx, CV_32F, 1, 0, CV_SCHARR);
  31 + Sobel(src, dy, CV_32F, 0, 1, CV_SCHARR);
  32 + cartToPolar(dx, dy, magnitude, angle, true);
  33 + std::vector<Mat> mv;
  34 + if ((channel == Magnitude) || (channel == MagnitudeAndAngle)) {
  35 + const float theoreticalMaxMagnitude = sqrt(2*pow(float(2*(3+10+3)*255), 2.f));
  36 + mv.push_back(magnitude / theoreticalMaxMagnitude);
  37 + }
  38 + if ((channel == Angle) || (channel == MagnitudeAndAngle))
  39 + mv.push_back(angle);
  40 + Mat result;
  41 + merge(mv, result);
  42 + dst.append(result);
  43 + }
  44 +};
  45 +
  46 +BR_REGISTER(Transform, GradientTransform)
  47 +
  48 +} // namespace br
  49 +
  50 +#include "gradient.moc"
... ...
openbr/plugins/imgproc/hist.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Histograms the matrix
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class HistTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 + Q_PROPERTY(float max READ get_max WRITE set_max RESET reset_max STORED false)
  19 + Q_PROPERTY(float min READ get_min WRITE set_min RESET reset_min STORED false)
  20 + Q_PROPERTY(int dims READ get_dims WRITE set_dims RESET reset_dims STORED false)
  21 + BR_PROPERTY(float, max, 256)
  22 + BR_PROPERTY(float, min, 0)
  23 + BR_PROPERTY(int, dims, -1)
  24 +
  25 + void project(const Template &src, Template &dst) const
  26 + {
  27 + const int dims = this->dims == -1 ? max - min : this->dims;
  28 +
  29 + std::vector<Mat> mv;
  30 + split(src, mv);
  31 + Mat m(mv.size(), dims, CV_32FC1);
  32 +
  33 + for (size_t i=0; i<mv.size(); i++) {
  34 + int channels[] = {0};
  35 + int histSize[] = {dims};
  36 + float range[] = {min, max};
  37 + const float* ranges[] = {range};
  38 + Mat hist, chan = mv[i];
  39 + // calcHist requires F or U, might as well convert just in case
  40 + if (mv[i].depth() != CV_8U && mv[i].depth() != CV_32F)
  41 + mv[i].convertTo(chan, CV_32F);
  42 + calcHist(&chan, 1, channels, Mat(), hist, 1, histSize, ranges);
  43 + memcpy(m.ptr(i), hist.ptr(), dims * sizeof(float));
  44 + }
  45 +
  46 + dst += m;
  47 + }
  48 +};
  49 +
  50 +BR_REGISTER(Transform, HistTransform)
  51 +
  52 +} // namespace br
  53 +
  54 +#include "hist.moc"
... ...
openbr/plugins/hist.cpp renamed to openbr/plugins/imgproc/histbin.cpp
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 "openbr_internal.h"
19   -#include "openbr/core/common.h"
20   -#include "openbr/core/opencvutils.h"
  1 +#include <openbr/plugins/openbr_internal.h>
21 2  
22 3 using namespace cv;
23 4  
... ... @@ -26,52 +7,10 @@ namespace br
26 7  
27 8 /*!
28 9 * \ingroup transforms
29   - * \brief Histograms the matrix
30   - * \author Josh Klontz \cite jklontz
31   - */
32   -class HistTransform : public UntrainableTransform
33   -{
34   - Q_OBJECT
35   - Q_PROPERTY(float max READ get_max WRITE set_max RESET reset_max STORED false)
36   - Q_PROPERTY(float min READ get_min WRITE set_min RESET reset_min STORED false)
37   - Q_PROPERTY(int dims READ get_dims WRITE set_dims RESET reset_dims STORED false)
38   - BR_PROPERTY(float, max, 256)
39   - BR_PROPERTY(float, min, 0)
40   - BR_PROPERTY(int, dims, -1)
41   -
42   - void project(const Template &src, Template &dst) const
43   - {
44   - const int dims = this->dims == -1 ? max - min : this->dims;
45   -
46   - std::vector<Mat> mv;
47   - split(src, mv);
48   - Mat m(mv.size(), dims, CV_32FC1);
49   -
50   - for (size_t i=0; i<mv.size(); i++) {
51   - int channels[] = {0};
52   - int histSize[] = {dims};
53   - float range[] = {min, max};
54   - const float* ranges[] = {range};
55   - Mat hist, chan = mv[i];
56   - // calcHist requires F or U, might as well convert just in case
57   - if (mv[i].depth() != CV_8U && mv[i].depth() != CV_32F)
58   - mv[i].convertTo(chan, CV_32F);
59   - calcHist(&chan, 1, channels, Mat(), hist, 1, histSize, ranges);
60   - memcpy(m.ptr(i), hist.ptr(), dims * sizeof(float));
61   - }
62   -
63   - dst += m;
64   - }
65   -};
66   -
67   -BR_REGISTER(Transform, HistTransform)
68   -
69   -/*!
70   - * \ingroup transforms
71 10 * \brief Quantizes the values into bins.
72 11 * \author Josh Klontz \cite jklontz
73 12 */
74   -class BinTransform : public UntrainableTransform
  13 +class HistBinTransform : public UntrainableTransform
75 14 {
76 15 Q_OBJECT
77 16 Q_PROPERTY(float min READ get_min WRITE set_min RESET reset_min STORED false)
... ... @@ -120,76 +59,8 @@ class BinTransform : public UntrainableTransform
120 59 }
121 60 };
122 61  
123   -BR_REGISTER(Transform, BinTransform)
124   -
125   -/*!
126   - * \ingroup transforms
127   - * \brief Converts each element to its rank-ordered value.
128   - * \author Josh Klontz \cite jklontz
129   - */
130   -class RankTransform : public UntrainableTransform
131   -{
132   - Q_OBJECT
133   -
134   - void project(const Template &src, Template &dst) const
135   - {
136   - const Mat &m = src;
137   - assert(m.channels() == 1);
138   - dst = Mat(m.rows, m.cols, CV_32FC1);
139   - typedef QPair<float,int> Tuple;
140   - QList<Tuple> tuples = Common::Sort(OpenCVUtils::matrixToVector<float>(m));
141   -
142   - float prevValue = 0;
143   - int prevRank = 0;
144   - for (int i=0; i<tuples.size(); i++) {
145   - int rank;
146   - if (tuples[i].first == prevValue) rank = prevRank;
147   - else rank = i;
148   - dst.m().at<float>(tuples[i].second / m.cols, tuples[i].second % m.cols) = rank;
149   - prevValue = tuples[i].first;
150   - prevRank = rank;
151   - }
152   - }
153   -};
154   -
155   -BR_REGISTER(Transform, RankTransform)
156   -
157   -/*!
158   - * \ingroup transforms
159   - * \brief An integral histogram
160   - * \author Josh Klontz \cite jklontz
161   - */
162   -class IntegralHistTransform : public UntrainableTransform
163   -{
164   - Q_OBJECT
165   - Q_PROPERTY(int bins READ get_bins WRITE set_bins RESET reset_bins STORED false)
166   - Q_PROPERTY(int radius READ get_radius WRITE set_radius RESET reset_radius STORED false)
167   - BR_PROPERTY(int, bins, 256)
168   - BR_PROPERTY(int, radius, 16)
169   -
170   - void project(const Template &src, Template &dst) const
171   - {
172   - const Mat &m = src.m();
173   - if (m.type() != CV_8UC1) qFatal("IntegralHist requires 8UC1 matrices.");
174   -
175   - Mat integral(m.rows/radius+1, (m.cols/radius+1)*bins, CV_32SC1);
176   - integral.setTo(0);
177   - for (int i=1; i<integral.rows; i++) {
178   - for (int j=1; j<integral.cols; j+=bins) {
179   - for (int k=0; k<bins; k++) integral.at<qint32>(i, j+k) += integral.at<qint32>(i-1, j +k);
180   - for (int k=0; k<bins; k++) integral.at<qint32>(i, j+k) += integral.at<qint32>(i , j-bins+k);
181   - for (int k=0; k<bins; k++) integral.at<qint32>(i, j+k) -= integral.at<qint32>(i-1, j-bins+k);
182   - for (int k=0; k<radius; k++)
183   - for (int l=0; l<radius; l++)
184   - integral.at<qint32>(i, j+m.at<quint8>((i-1)*radius+k,(j/bins-1)*radius+l))++;
185   - }
186   - }
187   - dst = integral;
188   - }
189   -};
190   -
191   -BR_REGISTER(Transform, IntegralHistTransform)
  62 +BR_REGISTER(Transform, HistBinTransform)
192 63  
193 64 } // namespace br
194 65  
195   -#include "hist.moc"
  66 +#include "histbin.moc"
... ...
openbr/plugins/imgproc/inpaint.cpp 0 → 100644
  1 +#include <opencv2/photo/photo.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Wraps OpenCV inpainting
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class InpaintTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 + Q_ENUMS(Method)
  19 + Q_PROPERTY(int radius READ get_radius WRITE set_radius RESET reset_radius STORED false)
  20 + Q_PROPERTY(Method method READ get_method WRITE set_method RESET reset_method STORED false)
  21 +
  22 +public:
  23 + /*!< */
  24 + enum Method { NavierStokes = INPAINT_NS,
  25 + Telea = INPAINT_TELEA };
  26 +
  27 +private:
  28 + BR_PROPERTY(int, radius, 1)
  29 + BR_PROPERTY(Method, method, NavierStokes)
  30 + Transform *cvtGray;
  31 +
  32 + void init()
  33 + {
  34 + cvtGray = make("Cvt(Gray)");
  35 + }
  36 +
  37 + void project(const Template &src, Template &dst) const
  38 + {
  39 + inpaint(src, (*cvtGray)(src)<5, dst, radius, method);
  40 + }
  41 +};
  42 +
  43 +} // namespace br
  44 +
  45 +#include "inpaint.moc"
... ...
openbr/plugins/imgproc/integral.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Computes integral image.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class IntegralTransform : public UntrainableTransform
  14 +{
  15 + Q_OBJECT
  16 +
  17 + void project(const Template &src, Template &dst) const
  18 + {
  19 + cv::integral(src, dst);
  20 + }
  21 +};
  22 +
  23 +BR_REGISTER(Transform, IntegralTransform)
  24 +
  25 +} // namespace br
  26 +
  27 +#include "integral.moc"
... ...
openbr/plugins/imgproc/integralhist.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief An integral histogram
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class IntegralHistTransform : public UntrainableTransform
  14 +{
  15 + Q_OBJECT
  16 + Q_PROPERTY(int bins READ get_bins WRITE set_bins RESET reset_bins STORED false)
  17 + Q_PROPERTY(int radius READ get_radius WRITE set_radius RESET reset_radius STORED false)
  18 + BR_PROPERTY(int, bins, 256)
  19 + BR_PROPERTY(int, radius, 16)
  20 +
  21 + void project(const Template &src, Template &dst) const
  22 + {
  23 + const Mat &m = src.m();
  24 + if (m.type() != CV_8UC1) qFatal("IntegralHist requires 8UC1 matrices.");
  25 +
  26 + Mat integral(m.rows/radius+1, (m.cols/radius+1)*bins, CV_32SC1);
  27 + integral.setTo(0);
  28 + for (int i=1; i<integral.rows; i++) {
  29 + for (int j=1; j<integral.cols; j+=bins) {
  30 + for (int k=0; k<bins; k++) integral.at<qint32>(i, j+k) += integral.at<qint32>(i-1, j +k);
  31 + for (int k=0; k<bins; k++) integral.at<qint32>(i, j+k) += integral.at<qint32>(i , j-bins+k);
  32 + for (int k=0; k<bins; k++) integral.at<qint32>(i, j+k) -= integral.at<qint32>(i-1, j-bins+k);
  33 + for (int k=0; k<radius; k++)
  34 + for (int l=0; l<radius; l++)
  35 + integral.at<qint32>(i, j+m.at<quint8>((i-1)*radius+k,(j/bins-1)*radius+l))++;
  36 + }
  37 + }
  38 + dst = integral;
  39 + }
  40 +};
  41 +
  42 +BR_REGISTER(Transform, IntegralHistTransform)
  43 +
  44 +} // namespace br
  45 +
  46 +#include "integralhist.moc"
... ...
openbr/plugins/integral.cpp renamed to openbr/plugins/imgproc/integralsampler.cpp
1   -#include <opencv2/imgproc/imgproc.hpp>
2   -#include <opencv2/imgproc/imgproc_c.h>
3   -#include <Eigen/Core>
4   -#include "openbr_internal.h"
  1 +#include <Eigen/Dense>
5 2  
6   -#include "openbr/core/opencvutils.h"
  3 +#include <openbr/plugins/openbr_internal.h>
7 4  
8 5 using namespace cv;
9 6  
... ... @@ -12,23 +9,6 @@ namespace br
12 9  
13 10 /*!
14 11 * \ingroup transforms
15   - * \brief Computes integral image.
16   - * \author Josh Klontz \cite jklontz
17   - */
18   -class IntegralTransform : public UntrainableTransform
19   -{
20   - Q_OBJECT
21   -
22   - void project(const Template &src, Template &dst) const
23   - {
24   - integral(src, dst);
25   - }
26   -};
27   -
28   -BR_REGISTER(Transform, IntegralTransform)
29   -
30   -/*!
31   - * \ingroup transforms
32 12 * \brief Sliding window feature extraction from a multi-channel integral image.
33 13 * \author Josh Klontz \cite jklontz
34 14 */
... ... @@ -121,254 +101,6 @@ class IntegralSamplerTransform : public UntrainableTransform
121 101  
122 102 BR_REGISTER(Transform, IntegralSamplerTransform)
123 103  
124   -/*!
125   - * \ingroup transforms
126   - * \brief Construct template in a recursive decent manner.
127   - * \author Josh Klontz \cite jklontz
128   - */
129   -class RecursiveIntegralSamplerTransform : public Transform
130   -{
131   - Q_OBJECT
132   - Q_PROPERTY(int scales READ get_scales WRITE set_scales RESET reset_scales STORED false)
133   - Q_PROPERTY(float scaleFactor READ get_scaleFactor WRITE set_scaleFactor RESET reset_scaleFactor STORED false)
134   - Q_PROPERTY(int minSize READ get_minSize WRITE set_minSize RESET reset_minSize STORED false)
135   - Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform)
136   - BR_PROPERTY(int, scales, 6)
137   - BR_PROPERTY(float, scaleFactor, 2)
138   - BR_PROPERTY(int, minSize, 8)
139   - BR_PROPERTY(br::Transform*, transform, NULL)
140   -
141   - Transform *subTransform;
142   -
143   - typedef Eigen::Map< const Eigen::Matrix<qint32,Eigen::Dynamic,1> > InputDescriptor;
144   - typedef Eigen::Map< Eigen::Matrix<float,Eigen::Dynamic,1> > OutputDescriptor;
145   - typedef Eigen::Map< const Eigen::Matrix<float,Eigen::Dynamic,1> > SecondOrderInputDescriptor;
146   -
147   - void init()
148   - {
149   - if (scales >= 2) {
150   - File subFile = file;
151   - subFile.set("scales", scales-1);
152   - subTransform = make(subFile.flat());
153   - } else {
154   - subTransform = NULL;
155   - }
156   - }
157   -
158   - static void integralHistogram(const Mat &src, const int x, const int y, const int width, const int height, Mat &dst, int index)
159   - {
160   - const int channels = src.channels();
161   - OutputDescriptor(dst.ptr<float>(index), channels, 1) =
162   - ( InputDescriptor(src.ptr<qint32>(y+height, x+width), channels, 1)
163   - - InputDescriptor(src.ptr<qint32>(y, x+width), channels, 1)
164   - - InputDescriptor(src.ptr<qint32>(y+height, x), channels, 1)
165   - + InputDescriptor(src.ptr<qint32>(y, x), channels, 1)).cast<float>()/(height*width);
166   - }
167   -
168   - void computeDescriptor(const Mat &src, Mat &dst) const
169   - {
170   - const int channels = src.channels();
171   - const int rows = src.rows-1; // Integral images have an extra row and column
172   - const int columns = src.cols-1;
173   -
174   - Mat tmp(5, channels, CV_32FC1);
175   - integralHistogram(src, 0, 0, columns/2, rows/2, tmp, 0);
176   - integralHistogram(src, columns/2, 0, columns/2, rows/2, tmp, 1);
177   - integralHistogram(src, 0, rows/2, columns/2, rows/2, tmp, 2);
178   - integralHistogram(src, columns/2, rows/2, columns/2, rows/2, tmp, 3);
179   - integralHistogram(src, columns/4, rows/4, columns/2, rows/2, tmp, 4);
180   - const SecondOrderInputDescriptor a(tmp.ptr<float>(0), channels, 1);
181   - const SecondOrderInputDescriptor b(tmp.ptr<float>(1), channels, 1);
182   - const SecondOrderInputDescriptor c(tmp.ptr<float>(2), channels, 1);
183   - const SecondOrderInputDescriptor d(tmp.ptr<float>(3), channels, 1);
184   - const SecondOrderInputDescriptor e(tmp.ptr<float>(4), channels, 1);
185   -
186   - dst = Mat(5, channels, CV_32FC1);
187   - OutputDescriptor(dst.ptr<float>(0), channels, 1) = (a+b+c+d)/4.f;
188   - OutputDescriptor(dst.ptr<float>(1), channels, 1) = ((a+b+c+d)/4.f-e);
189   - OutputDescriptor(dst.ptr<float>(2), channels, 1) = ((a+b)-(c+d))/2.f;
190   - OutputDescriptor(dst.ptr<float>(3), channels, 1) = ((a+c)-(b+d))/2.f;
191   - OutputDescriptor(dst.ptr<float>(4), channels, 1) = ((a+d)-(b+c))/2.f;
192   - dst = dst.reshape(1, 1);
193   - }
194   -
195   - Template subdivide(const Template &src) const
196   - {
197   - // Integral images have an extra row and column
198   - int subWidth = (src.m().cols-1) / scaleFactor + 1;
199   - int subHeight = (src.m().rows-1) / scaleFactor + 1;
200   - return Template(src.file, QList<Mat>() << Mat(src, Rect(0, 0, subWidth, subHeight))
201   - << Mat(src, Rect(src.m().cols-subWidth, 0, subWidth, subHeight))
202   - << Mat(src, Rect(0, src.m().rows-subHeight, subWidth, subHeight))
203   - << Mat(src, Rect(src.m().cols-subWidth, src.m().rows-subHeight, subWidth, subHeight)));
204   - }
205   -
206   - bool canSubdivide(const Template &t) const
207   - {
208   - // Integral images have an extra row and column
209   - const int subWidth = (t.m().cols-1) / scaleFactor;
210   - const int subHeight = (t.m().rows-1) / scaleFactor;
211   - return ((subWidth >= minSize) && (subHeight >= minSize));
212   - }
213   -
214   - void train(const TemplateList &src)
215   - {
216   - if (src.first().m().depth() != CV_32S)
217   - qFatal("Expected CV_32S depth!");
218   -
219   - if (subTransform != NULL) {
220   - TemplateList subSrc; subSrc.reserve(src.size());
221   - foreach (const Template &t, src)
222   - if (canSubdivide(t))
223   - subSrc.append(subdivide(t));
224   -
225   - if (subSrc.isEmpty()) {
226   - delete subTransform;
227   - subTransform = NULL;
228   - } else {
229   - subTransform->train(subSrc);
230   - }
231   - }
232   -
233   - TemplateList dst; dst.reserve(src.size());
234   - foreach (const Template &t, src) {
235   - Template u(t.file);
236   - computeDescriptor(t, u);
237   - dst.append(u);
238   - }
239   - transform->train(dst);
240   - }
241   -
242   - void project(const Template &src, Template &dst) const
243   - {
244   - computeDescriptor(src, dst);
245   - transform->project(dst, dst);
246   -
247   - if ((subTransform != NULL) && canSubdivide(src)) {
248   - Template subDst;
249   - subTransform->project(subdivide(src), subDst);
250   - dst.append(subDst);
251   - }
252   - }
253   -
254   - void store(QDataStream &stream) const
255   - {
256   - transform->store(stream);
257   - stream << (subTransform != NULL);
258   - if (subTransform != NULL)
259   - subTransform->store(stream);
260   - }
261   -
262   - void load(QDataStream &stream)
263   - {
264   - transform->load(stream);
265   - bool hasSubTransform;
266   - stream >> hasSubTransform;
267   - if (hasSubTransform) subTransform->load(stream);
268   - else { delete subTransform; subTransform = NULL; }
269   - }
270   -};
271   -
272   -BR_REGISTER(Transform, RecursiveIntegralSamplerTransform)
273   -
274   -/*!
275   - * \ingroup transforms
276   - * \brief Computes magnitude and/or angle of image.
277   - * \author Josh Klontz \cite jklontz
278   - */
279   -class GradientTransform : public UntrainableTransform
280   -{
281   - Q_OBJECT
282   - Q_ENUMS(Channel)
283   - Q_PROPERTY(Channel channel READ get_channel WRITE set_channel RESET reset_channel STORED false)
284   -
285   -public:
286   - enum Channel { Magnitude, Angle, MagnitudeAndAngle };
287   -
288   -private:
289   - BR_PROPERTY(Channel, channel, Angle)
290   -
291   - void project(const Template &src, Template &dst) const
292   - {
293   - Mat dx, dy, magnitude, angle;
294   - Sobel(src, dx, CV_32F, 1, 0, CV_SCHARR);
295   - Sobel(src, dy, CV_32F, 0, 1, CV_SCHARR);
296   - cartToPolar(dx, dy, magnitude, angle, true);
297   - std::vector<Mat> mv;
298   - if ((channel == Magnitude) || (channel == MagnitudeAndAngle)) {
299   - const float theoreticalMaxMagnitude = sqrt(2*pow(float(2*(3+10+3)*255), 2.f));
300   - mv.push_back(magnitude / theoreticalMaxMagnitude);
301   - }
302   - if ((channel == Angle) || (channel == MagnitudeAndAngle))
303   - mv.push_back(angle);
304   - Mat result;
305   - merge(mv, result);
306   - dst.append(result);
307   - }
308   -};
309   -
310   -BR_REGISTER(Transform, GradientTransform)
311   -
312   -/*!
313   - * \ingroup transforms
314   - * \brief Projects each row based on a computed word.
315   - * \author Josh Klontz \cite jklontz
316   - */
317   -class WordWiseTransform : public Transform
318   -{
319   - Q_OBJECT
320   - Q_PROPERTY(br::Transform* getWords READ get_getWords WRITE set_getWords RESET reset_getWords)
321   - Q_PROPERTY(br::Transform* byWord READ get_byWord WRITE set_byWord RESET reset_byWord)
322   - Q_PROPERTY(int numWords READ get_numWords WRITE set_numWords RESET reset_numWords)
323   - BR_PROPERTY(br::Transform*, getWords, NULL)
324   - BR_PROPERTY(br::Transform*, byWord, NULL)
325   - BR_PROPERTY(int, numWords, 0)
326   -
327   - void train(const TemplateList &data)
328   - {
329   - getWords->train(data);
330   - TemplateList bins;
331   - getWords->project(data, bins);
332   -
333   - numWords = 0;
334   - foreach (const Template &t, bins) {
335   - double minVal, maxVal;
336   - minMaxLoc(t, &minVal, &maxVal);
337   - numWords = max(numWords, int(maxVal)+1);
338   - }
339   -
340   - TemplateList reworded; reworded.reserve(data.size());
341   - foreach (const Template &t, data)
342   - reworded.append(reword(t));
343   - byWord->train(reworded);
344   - }
345   -
346   - void project(const Template &src, Template &dst) const
347   - {
348   - byWord->project(reword(src), dst);
349   - }
350   -
351   - Template reword(const Template &src) const
352   - {
353   - Template words;
354   - getWords->project(src, words);
355   - QVector<int> wordCounts(numWords, 0);
356   - for (int i=0; i<words.m().rows; i++)
357   - wordCounts[words.m().at<uchar>(i,0)]++;
358   - Template reworded(src.file); reworded.reserve(numWords);
359   - for (int i=0; i<numWords; i++)
360   - reworded.append(Mat(wordCounts[i], src.m().cols, src.m().type()));
361   - QVector<int> indicies(numWords, 0);
362   - for (int i=0; i<src.m().rows; i++) {
363   - const int word = words.m().at<uchar>(i,0);
364   - src.m().row(i).copyTo(reworded[word].row(indicies[word]++));
365   - }
366   - return reworded;
367   - }
368   -};
369   -
370   -BR_REGISTER(Transform, WordWiseTransform)
371   -
372 104 } // namespace br
373 105  
374   -#include "integral.moc"
  106 +#include "integralsampler.moc"
... ...
openbr/plugins/imgproc/limitsize.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Limit the size of the template
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class LimitSizeTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 + Q_PROPERTY(int max READ get_max WRITE set_max RESET reset_max STORED false)
  19 + BR_PROPERTY(int, max, -1)
  20 +
  21 + void project(const Template &src, Template &dst) const
  22 + {
  23 + const Mat &m = src;
  24 + if (m.rows > m.cols)
  25 + if (m.rows > max) resize(m, dst, Size(std::max(1, m.cols * max / m.rows), max));
  26 + else dst = m;
  27 + else
  28 + if (m.cols > max) resize(m, dst, Size(max, std::max(1, m.rows * max / m.cols)));
  29 + else dst = m;
  30 + }
  31 +};
  32 +
  33 +BR_REGISTER(Transform, LimitSizeTransform)
  34 +
  35 +} // namespace br
  36 +
  37 +#include "limitsize.moc"
... ...
openbr/plugins/imgproc/madd.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief dst = a*src+b
  9 + * \author Josh Klontz \cite jklontz
  10 + */
  11 +class MAddTransform : public UntrainableTransform
  12 +{
  13 + Q_OBJECT
  14 + Q_PROPERTY(double a READ get_a WRITE set_a RESET reset_a STORED false)
  15 + Q_PROPERTY(double b READ get_b WRITE set_b RESET reset_b STORED false)
  16 + BR_PROPERTY(double, a, 1)
  17 + BR_PROPERTY(double, b, 0)
  18 +
  19 + void project(const Template &src, Template &dst) const
  20 + {
  21 + src.m().convertTo(dst.m(), src.m().depth(), a, b);
  22 + }
  23 +};
  24 +
  25 +BR_REGISTER(Transform, MAddTransform)
  26 +
  27 +} // namespace br
  28 +
  29 +#include "madd.moc"
... ...
openbr/plugins/imgproc/mean.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Computes the mean of a set of templates.
  11 + * \note Suitable for visualization only as it sets every projected template to the mean template.
  12 + * \author Scott Klum \cite sklum
  13 + */
  14 +class MeanTransform : public Transform
  15 +{
  16 + Q_OBJECT
  17 +
  18 + Mat mean;
  19 +
  20 + void train(const TemplateList &data)
  21 + {
  22 + mean = Mat::zeros(data[0].m().rows,data[0].m().cols,CV_32F);
  23 +
  24 + for (int i = 0; i < data.size(); i++) {
  25 + Mat converted;
  26 + data[i].m().convertTo(converted, CV_32F);
  27 + mean += converted;
  28 + }
  29 +
  30 + mean /= data.size();
  31 + }
  32 +
  33 + void project(const Template &src, Template &dst) const
  34 + {
  35 + dst = src;
  36 + dst.m() = mean;
  37 + }
  38 +
  39 +};
  40 +
  41 +BR_REGISTER(Transform, MeanTransform)
  42 +
  43 +} // namespace br
  44 +
  45 +#include "mean.moc"
... ...
openbr/plugins/imgproc/meanfill.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Fill 0 pixels with the mean of non-0 pixels.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class MeanFillTransform : public UntrainableTransform
  14 +{
  15 + Q_OBJECT
  16 +
  17 + void project(const Template &src, Template &dst) const
  18 + {
  19 + dst = src.m().clone();
  20 + dst.m().setTo(mean(dst, dst.m()!=0), dst.m()==0);
  21 + }
  22 +};
  23 +
  24 +BR_REGISTER(Transform, MeanFillTransform)
  25 +
  26 +} // namespace br
  27 +
  28 +#include "meanfill.moc"
... ...
openbr/plugins/imgproc/pow.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Raise each element to the specified power.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class PowTransform : public UntrainableTransform
  14 +{
  15 + Q_OBJECT
  16 + Q_PROPERTY(float power READ get_power WRITE set_power RESET reset_power STORED false)
  17 + Q_PROPERTY(bool preserveSign READ get_preserveSign WRITE set_preserveSign RESET reset_preserveSign STORED false)
  18 + BR_PROPERTY(float, power, 2)
  19 + BR_PROPERTY(bool, preserveSign, false)
  20 +
  21 + void project(const Template &src, Template &dst) const
  22 + {
  23 + pow(preserveSign ? abs(src) : src.m(), power, dst);
  24 + if (preserveSign) subtract(Scalar::all(0), dst, dst, src.m() < 0);
  25 + }
  26 +};
  27 +
  28 +BR_REGISTER(Transform, PowTransform)
  29 +
  30 +} // namespace br
  31 +
  32 +#include "pow.moc"
... ...
openbr/plugins/imgproc/rank.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/common.h>
  3 +#include <openbr/core/opencvutils.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Converts each element to its rank-ordered value.
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class RankTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 +
  19 + void project(const Template &src, Template &dst) const
  20 + {
  21 + const Mat &m = src;
  22 + assert(m.channels() == 1);
  23 + dst = Mat(m.rows, m.cols, CV_32FC1);
  24 + typedef QPair<float,int> Tuple;
  25 + QList<Tuple> tuples = Common::Sort(OpenCVUtils::matrixToVector<float>(m));
  26 +
  27 + float prevValue = 0;
  28 + int prevRank = 0;
  29 + for (int i=0; i<tuples.size(); i++) {
  30 + int rank;
  31 + if (tuples[i].first == prevValue) rank = prevRank;
  32 + else rank = i;
  33 + dst.m().at<float>(tuples[i].second / m.cols, tuples[i].second % m.cols) = rank;
  34 + prevValue = tuples[i].first;
  35 + prevRank = rank;
  36 + }
  37 + }
  38 +};
  39 +
  40 +BR_REGISTER(Transform, RankTransform)
  41 +
  42 +} // namespace br
  43 +
  44 +#include "rank.moc"
... ...
openbr/plugins/imgproc/recursiveintegralsampler.cpp 0 → 100644
  1 +#include <Eigen/Dense>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Construct template in a recursive decent manner.
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class RecursiveIntegralSamplerTransform : public Transform
  16 +{
  17 + Q_OBJECT
  18 + Q_PROPERTY(int scales READ get_scales WRITE set_scales RESET reset_scales STORED false)
  19 + Q_PROPERTY(float scaleFactor READ get_scaleFactor WRITE set_scaleFactor RESET reset_scaleFactor STORED false)
  20 + Q_PROPERTY(int minSize READ get_minSize WRITE set_minSize RESET reset_minSize STORED false)
  21 + Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform)
  22 + BR_PROPERTY(int, scales, 6)
  23 + BR_PROPERTY(float, scaleFactor, 2)
  24 + BR_PROPERTY(int, minSize, 8)
  25 + BR_PROPERTY(br::Transform*, transform, NULL)
  26 +
  27 + Transform *subTransform;
  28 +
  29 + typedef Eigen::Map< const Eigen::Matrix<qint32,Eigen::Dynamic,1> > InputDescriptor;
  30 + typedef Eigen::Map< Eigen::Matrix<float,Eigen::Dynamic,1> > OutputDescriptor;
  31 + typedef Eigen::Map< const Eigen::Matrix<float,Eigen::Dynamic,1> > SecondOrderInputDescriptor;
  32 +
  33 + void init()
  34 + {
  35 + if (scales >= 2) {
  36 + File subFile = file;
  37 + subFile.set("scales", scales-1);
  38 + subTransform = make(subFile.flat());
  39 + } else {
  40 + subTransform = NULL;
  41 + }
  42 + }
  43 +
  44 + static void integralHistogram(const Mat &src, const int x, const int y, const int width, const int height, Mat &dst, int index)
  45 + {
  46 + const int channels = src.channels();
  47 + OutputDescriptor(dst.ptr<float>(index), channels, 1) =
  48 + ( InputDescriptor(src.ptr<qint32>(y+height, x+width), channels, 1)
  49 + - InputDescriptor(src.ptr<qint32>(y, x+width), channels, 1)
  50 + - InputDescriptor(src.ptr<qint32>(y+height, x), channels, 1)
  51 + + InputDescriptor(src.ptr<qint32>(y, x), channels, 1)).cast<float>()/(height*width);
  52 + }
  53 +
  54 + void computeDescriptor(const Mat &src, Mat &dst) const
  55 + {
  56 + const int channels = src.channels();
  57 + const int rows = src.rows-1; // Integral images have an extra row and column
  58 + const int columns = src.cols-1;
  59 +
  60 + Mat tmp(5, channels, CV_32FC1);
  61 + integralHistogram(src, 0, 0, columns/2, rows/2, tmp, 0);
  62 + integralHistogram(src, columns/2, 0, columns/2, rows/2, tmp, 1);
  63 + integralHistogram(src, 0, rows/2, columns/2, rows/2, tmp, 2);
  64 + integralHistogram(src, columns/2, rows/2, columns/2, rows/2, tmp, 3);
  65 + integralHistogram(src, columns/4, rows/4, columns/2, rows/2, tmp, 4);
  66 + const SecondOrderInputDescriptor a(tmp.ptr<float>(0), channels, 1);
  67 + const SecondOrderInputDescriptor b(tmp.ptr<float>(1), channels, 1);
  68 + const SecondOrderInputDescriptor c(tmp.ptr<float>(2), channels, 1);
  69 + const SecondOrderInputDescriptor d(tmp.ptr<float>(3), channels, 1);
  70 + const SecondOrderInputDescriptor e(tmp.ptr<float>(4), channels, 1);
  71 +
  72 + dst = Mat(5, channels, CV_32FC1);
  73 + OutputDescriptor(dst.ptr<float>(0), channels, 1) = (a+b+c+d)/4.f;
  74 + OutputDescriptor(dst.ptr<float>(1), channels, 1) = ((a+b+c+d)/4.f-e);
  75 + OutputDescriptor(dst.ptr<float>(2), channels, 1) = ((a+b)-(c+d))/2.f;
  76 + OutputDescriptor(dst.ptr<float>(3), channels, 1) = ((a+c)-(b+d))/2.f;
  77 + OutputDescriptor(dst.ptr<float>(4), channels, 1) = ((a+d)-(b+c))/2.f;
  78 + dst = dst.reshape(1, 1);
  79 + }
  80 +
  81 + Template subdivide(const Template &src) const
  82 + {
  83 + // Integral images have an extra row and column
  84 + int subWidth = (src.m().cols-1) / scaleFactor + 1;
  85 + int subHeight = (src.m().rows-1) / scaleFactor + 1;
  86 + return Template(src.file, QList<Mat>() << Mat(src, Rect(0, 0, subWidth, subHeight))
  87 + << Mat(src, Rect(src.m().cols-subWidth, 0, subWidth, subHeight))
  88 + << Mat(src, Rect(0, src.m().rows-subHeight, subWidth, subHeight))
  89 + << Mat(src, Rect(src.m().cols-subWidth, src.m().rows-subHeight, subWidth, subHeight)));
  90 + }
  91 +
  92 + bool canSubdivide(const Template &t) const
  93 + {
  94 + // Integral images have an extra row and column
  95 + const int subWidth = (t.m().cols-1) / scaleFactor;
  96 + const int subHeight = (t.m().rows-1) / scaleFactor;
  97 + return ((subWidth >= minSize) && (subHeight >= minSize));
  98 + }
  99 +
  100 + void train(const TemplateList &src)
  101 + {
  102 + if (src.first().m().depth() != CV_32S)
  103 + qFatal("Expected CV_32S depth!");
  104 +
  105 + if (subTransform != NULL) {
  106 + TemplateList subSrc; subSrc.reserve(src.size());
  107 + foreach (const Template &t, src)
  108 + if (canSubdivide(t))
  109 + subSrc.append(subdivide(t));
  110 +
  111 + if (subSrc.isEmpty()) {
  112 + delete subTransform;
  113 + subTransform = NULL;
  114 + } else {
  115 + subTransform->train(subSrc);
  116 + }
  117 + }
  118 +
  119 + TemplateList dst; dst.reserve(src.size());
  120 + foreach (const Template &t, src) {
  121 + Template u(t.file);
  122 + computeDescriptor(t, u);
  123 + dst.append(u);
  124 + }
  125 + transform->train(dst);
  126 + }
  127 +
  128 + void project(const Template &src, Template &dst) const
  129 + {
  130 + computeDescriptor(src, dst);
  131 + transform->project(dst, dst);
  132 +
  133 + if ((subTransform != NULL) && canSubdivide(src)) {
  134 + Template subDst;
  135 + subTransform->project(subdivide(src), subDst);
  136 + dst.append(subDst);
  137 + }
  138 + }
  139 +
  140 + void store(QDataStream &stream) const
  141 + {
  142 + transform->store(stream);
  143 + stream << (subTransform != NULL);
  144 + if (subTransform != NULL)
  145 + subTransform->store(stream);
  146 + }
  147 +
  148 + void load(QDataStream &stream)
  149 + {
  150 + transform->load(stream);
  151 + bool hasSubTransform;
  152 + stream >> hasSubTransform;
  153 + if (hasSubTransform) subTransform->load(stream);
  154 + else { delete subTransform; subTransform = NULL; }
  155 + }
  156 +};
  157 +
  158 +BR_REGISTER(Transform, RecursiveIntegralSamplerTransform)
  159 +
  160 +} // namespace br
  161 +
  162 +#include "recursiveintegralsampler.moc"
... ...
openbr/plugins/imgproc/resize.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Resize the template
  13 + * \author Josh Klontz \cite jklontz
  14 + * \note Method: Area should be used for shrinking an image, Cubic for slow but accurate enlargment, Bilin for fast enlargement.
  15 + * \param preserveAspect If true, the image will be sized per specification, but
  16 + * a border will be applied to preserve aspect ratio.
  17 + */
  18 +class ResizeTransform : public UntrainableTransform
  19 +{
  20 + Q_OBJECT
  21 + Q_ENUMS(Method)
  22 +
  23 +public:
  24 + /*!< */
  25 + enum Method { Near = INTER_NEAREST,
  26 + Area = INTER_AREA,
  27 + Bilin = INTER_LINEAR,
  28 + Cubic = INTER_CUBIC,
  29 + Lanczo = INTER_LANCZOS4};
  30 +
  31 +private:
  32 + Q_PROPERTY(int rows READ get_rows WRITE set_rows RESET reset_rows STORED false)
  33 + Q_PROPERTY(int columns READ get_columns WRITE set_columns RESET reset_columns STORED false)
  34 + Q_PROPERTY(Method method READ get_method WRITE set_method RESET reset_method STORED false)
  35 + Q_PROPERTY(bool preserveAspect READ get_preserveAspect WRITE set_preserveAspect RESET reset_preserveAspect STORED false)
  36 + BR_PROPERTY(int, rows, -1)
  37 + BR_PROPERTY(int, columns, -1)
  38 + BR_PROPERTY(Method, method, Bilin)
  39 + BR_PROPERTY(bool, preserveAspect, false)
  40 +
  41 + void project(const Template &src, Template &dst) const
  42 + {
  43 + if (!preserveAspect)
  44 + resize(src, dst, Size((columns == -1) ? src.m().cols*rows/src.m().rows : columns, rows), 0, 0, method);
  45 + else {
  46 + float inRatio = (float) src.m().rows / src.m().cols;
  47 + float outRatio = (float) rows / columns;
  48 + dst = Mat::zeros(rows, columns, src.m().type());
  49 + if (outRatio > inRatio) {
  50 + float heightAR = src.m().rows * inRatio / outRatio;
  51 + Mat buffer;
  52 + resize(src, buffer, Size(columns, heightAR), 0, 0, method);
  53 + buffer.copyTo(dst.m()(Rect(0, (rows - heightAR) / 2, columns, heightAR)));
  54 + } else {
  55 + float widthAR = src.m().cols / inRatio * outRatio;
  56 + Mat buffer;
  57 + resize(src, buffer, Size(widthAR, rows), 0, 0, method);
  58 + buffer.copyTo(dst.m()(Rect((columns - widthAR) / 2, 0, widthAR, rows)));
  59 + }
  60 + }
  61 + }
  62 +};
  63 +
  64 +BR_REGISTER(Transform, ResizeTransform)
  65 +
  66 +} // namespace br
  67 +
  68 +#include "resize.moc"
... ...
openbr/plugins/imgproc/rg.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Normalized RG color space.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class RGTransform : public UntrainableTransform
  14 +{
  15 + Q_OBJECT
  16 +
  17 + void project(const Template &src, Template &dst) const
  18 + {
  19 + if (src.m().type() != CV_8UC3)
  20 + qFatal("Expected CV_8UC3 images.");
  21 +
  22 + const Mat &m = src.m();
  23 + Mat R(m.size(), CV_8UC1); // R / (R+G+B)
  24 + Mat G(m.size(), CV_8UC1); // G / (R+G+B)
  25 +
  26 + for (int i=0; i<m.rows; i++)
  27 + for (int j=0; j<m.cols; j++) {
  28 + Vec3b v = m.at<Vec3b>(i,j);
  29 + const int b = v[0];
  30 + const int g = v[1];
  31 + const int r = v[2];
  32 + const int sum = b + g + r;
  33 + if (sum > 0) {
  34 + R.at<uchar>(i, j) = saturate_cast<uchar>(255.0*r/(r+g+b));
  35 + G.at<uchar>(i, j) = saturate_cast<uchar>(255.0*g/(r+g+b));
  36 + } else {
  37 + R.at<uchar>(i, j) = 0;
  38 + G.at<uchar>(i, j) = 0;
  39 + }
  40 + }
  41 +
  42 + dst.append(R);
  43 + dst.append(G);
  44 + }
  45 +};
  46 +
  47 +BR_REGISTER(Transform, RGTransform)
  48 +
  49 +} // namespace br
  50 +
  51 +#include "rg.moc"
... ...
openbr/plugins/imgproc/roi.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup transforms
  11 + * \brief Crops the rectangular regions of interest.
  12 + * \author Josh Klontz \cite jklontz
  13 + */
  14 +class ROITransform : public UntrainableTransform
  15 +{
  16 + Q_OBJECT
  17 + Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false)
  18 + BR_PROPERTY(QString, propName, "")
  19 +
  20 + void project(const Template &src, Template &dst) const
  21 + {
  22 + if (!propName.isEmpty()) {
  23 + QRectF rect = src.file.get<QRectF>(propName);
  24 + dst += src.m()(OpenCVUtils::toRect(rect));
  25 + } else if (!src.file.rects().empty()) {
  26 + foreach (const QRectF &rect, src.file.rects())
  27 + dst += src.m()(OpenCVUtils::toRect(rect));
  28 + } else if (src.file.contains(QStringList() << "X" << "Y" << "Width" << "Height")) {
  29 + dst += src.m()(Rect(src.file.get<int>("X"),
  30 + src.file.get<int>("Y"),
  31 + src.file.get<int>("Width"),
  32 + src.file.get<int>("Height")));
  33 + } else {
  34 + dst = src;
  35 + if (Globals->verbose)
  36 + qWarning("No rects present in file.");
  37 + }
  38 + dst.file.clearRects();
  39 + }
  40 +};
  41 +
  42 +BR_REGISTER(Transform, ROITransform)
  43 +
  44 +} // namespace br
  45 +
  46 +#include "roi.moc"
... ...
openbr/plugins/imgproc/roifrompoints.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Crops the rectangular regions of interest from given points and sizes.
  11 + * \author Austin Blanton \cite imaus10
  12 + */
  13 +class ROIFromPtsTransform : public UntrainableTransform
  14 +{
  15 + Q_OBJECT
  16 + Q_PROPERTY(int width READ get_width WRITE set_width RESET reset_width STORED false)
  17 + Q_PROPERTY(int height READ get_height WRITE set_height RESET reset_height STORED false)
  18 + BR_PROPERTY(int, width, 1)
  19 + BR_PROPERTY(int, height, 1)
  20 +
  21 + void project(const Template &src, Template &dst) const
  22 + {
  23 + foreach (const QPointF &pt, src.file.points()) {
  24 + int x = pt.x() - (width/2);
  25 + int y = pt.y() - (height/2);
  26 + dst += src.m()(Rect(x, y, width, height));
  27 + }
  28 + }
  29 +};
  30 +
  31 +BR_REGISTER(Transform, ROIFromPtsTransform)
  32 +
  33 +} // namespace br
  34 +
  35 +#include "roifrompoints.moc"
... ...
openbr/plugins/imgproc/scale.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Scales using the given factor
  13 + * \author Scott Klum \cite sklum
  14 + */
  15 +class ScaleTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 +
  19 + Q_PROPERTY(float scaleFactor READ get_scaleFactor WRITE set_scaleFactor RESET reset_scaleFactor STORED false)
  20 + BR_PROPERTY(float, scaleFactor, 1.)
  21 +
  22 + void project(const Template &src, Template &dst) const
  23 + {
  24 + resize(src, dst, Size(src.m().cols*scaleFactor,src.m().rows*scaleFactor));
  25 + }
  26 +};
  27 +
  28 +BR_REGISTER(Transform, ScaleTransform)
  29 +
  30 +} // namespace br
  31 +
  32 +#include "scale.moc"
... ...
openbr/plugins/imgproc/splitchannels.cpp 0 → 100644
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Split a multi-channel matrix into several single-channel matrices.
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class SplitChannelsTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 +
  19 + void project(const Template &src, Template &dst) const
  20 + {
  21 + std::vector<Mat> mv;
  22 + split(src, mv);
  23 + foreach (const Mat &m, mv)
  24 + dst += m;
  25 + }
  26 +};
  27 +
  28 +BR_REGISTER(Transform, SplitChannelsTransform)
  29 +
  30 +} // namespace br
  31 +
  32 +#include "splitchannels.moc"
... ...
openbr/plugins/imgproc/subdivide.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Divide the matrix into 4 smaller matricies of equal size.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class SubdivideTransform : public UntrainableTransform
  14 +{
  15 + Q_OBJECT
  16 +
  17 + void project(const Template &src, Template &dst) const
  18 + {
  19 + const Mat &m = src;
  20 + const int subrows = m.rows/2;
  21 + const int subcolumns = m.cols/2;
  22 + dst.append(Mat(m,Rect(0, 0, subcolumns, subrows)).clone());
  23 + dst.append(Mat(m,Rect(subcolumns, 0, subcolumns, subrows)).clone());
  24 + dst.append(Mat(m,Rect(0, subrows, subcolumns, subrows)).clone());
  25 + dst.append(Mat(m,Rect(subcolumns, subrows, subcolumns, subrows)).clone());
  26 + }
  27 +};
  28 +
  29 +BR_REGISTER(Transform, SubdivideTransform)
  30 +
  31 +} // namespace br
  32 +
  33 +#include "subdivide.moc"
... ...
openbr/plugins/io/write.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup transforms
  11 + * \brief Write all mats to disk as images.
  12 + * \author Brendan Klare \cite bklare
  13 + */
  14 +class WriteTransform : public TimeVaryingTransform
  15 +{
  16 + Q_OBJECT
  17 + Q_PROPERTY(QString outputDirectory READ get_outputDirectory WRITE set_outputDirectory RESET reset_outputDirectory STORED false)
  18 + Q_PROPERTY(QString imageName READ get_imageName WRITE set_imageName RESET reset_imageName STORED false)
  19 + Q_PROPERTY(QString imgExtension READ get_imgExtension WRITE set_imgExtension RESET reset_imgExtension STORED false)
  20 + BR_PROPERTY(QString, outputDirectory, "Temp")
  21 + BR_PROPERTY(QString, imageName, "image")
  22 + BR_PROPERTY(QString, imgExtension, "jpg")
  23 +
  24 + int cnt;
  25 +
  26 + void init() {
  27 + cnt = 0;
  28 + if (! QDir(outputDirectory).exists())
  29 + QDir().mkdir(outputDirectory);
  30 + }
  31 +
  32 + void projectUpdate(const Template &src, Template &dst)
  33 + {
  34 + dst = src;
  35 + OpenCVUtils::saveImage(dst.m(), QString("%1/%2_%3.%4").arg(outputDirectory).arg(imageName).arg(cnt++, 5, 10, QChar('0')).arg(imgExtension));
  36 + }
  37 +
  38 +};
  39 +
  40 +BR_REGISTER(Transform, WriteTransform)
  41 +
  42 +} // namespace br
  43 +
  44 +#include "write.moc"
... ...
openbr/plugins/keypoint.cpp deleted
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/features2d/features2d.hpp>
18   -#include <opencv2/objdetect/objdetect.hpp>
19   -#include <opencv2/nonfree/nonfree.hpp>
20   -#include "openbr_internal.h"
21   -#include "openbr/core/opencvutils.h"
22   -
23   -using namespace cv;
24   -
25   -namespace br
26   -{
27   -
28   -/*!
29   - * \ingroup transforms
30   - * \brief Wraps OpenCV Key Point Detector
31   - * \author Josh Klontz \cite jklontz
32   - */
33   -class KeyPointDetectorTransform : public UntrainableTransform
34   -{
35   - Q_OBJECT
36   - Q_PROPERTY(QString detector READ get_detector WRITE set_detector RESET reset_detector STORED false)
37   - BR_PROPERTY(QString, detector, "SIFT")
38   -
39   - Ptr<FeatureDetector> featureDetector;
40   -
41   - void init()
42   - {
43   - featureDetector = FeatureDetector::create(detector.toStdString());
44   - if (featureDetector.empty())
45   - qFatal("Failed to create KeyPointDetector: %s", qPrintable(detector));
46   - }
47   -
48   - void project(const Template &src, Template &dst) const
49   - {
50   - dst = src;
51   -
52   - std::vector<KeyPoint> keyPoints;
53   - try {
54   - featureDetector->detect(src, keyPoints);
55   - } catch (...) {
56   - qWarning("Key point detection failed for file %s", qPrintable(src.file.name));
57   - dst.file.fte = true;
58   - }
59   -
60   - QList<Rect> rects;
61   - foreach (const KeyPoint &keyPoint, keyPoints)
62   - rects.append(Rect(keyPoint.pt.x-keyPoint.size/2, keyPoint.pt.y-keyPoint.size/2, keyPoint.size, keyPoint.size));
63   - dst.file.setRects(OpenCVUtils::fromRects(rects));
64   - }
65   -};
66   -
67   -BR_REGISTER(Transform, KeyPointDetectorTransform)
68   -
69   -/*!
70   - * \ingroup transforms
71   - * \brief Wraps OpenCV Key Point Descriptor
72   - * \author Josh Klontz \cite jklontz
73   - */
74   -class KeyPointDescriptorTransform : public UntrainableTransform
75   -{
76   - Q_OBJECT
77   - Q_PROPERTY(QString descriptor READ get_descriptor WRITE set_descriptor RESET reset_descriptor STORED false)
78   - Q_PROPERTY(int size READ get_size WRITE set_size RESET reset_size STORED false)
79   - BR_PROPERTY(QString, descriptor, "SIFT")
80   - BR_PROPERTY(int, size, -1)
81   -
82   - Ptr<DescriptorExtractor> descriptorExtractor;
83   -
84   - void init()
85   - {
86   - descriptorExtractor = DescriptorExtractor::create(descriptor.toStdString());
87   - if (descriptorExtractor.empty())
88   - qFatal("Failed to create DescriptorExtractor: %s", qPrintable(descriptor));
89   - }
90   -
91   - void project(const Template &src, Template &dst) const
92   - {
93   - std::vector<KeyPoint> keyPoints;
94   - if (size == -1)
95   - foreach (const QRectF &ROI, src.file.rects())
96   - keyPoints.push_back(KeyPoint(ROI.x()+ROI.width()/2, ROI.y()+ROI.height()/2, (ROI.width() + ROI.height())/2));
97   - else
98   - foreach (const QPointF &landmark, src.file.points())
99   - keyPoints.push_back(KeyPoint(landmark.x(), landmark.y(), size));
100   - if (keyPoints.empty()) return;
101   - descriptorExtractor->compute(src, keyPoints, dst);
102   - }
103   -};
104   -
105   -BR_REGISTER(Transform, KeyPointDescriptorTransform)
106   -
107   -/*!
108   - * \ingroup transforms
109   - * \brief Wraps OpenCV Key Point Matcher
110   - * \author Josh Klontz \cite jklontz
111   - */
112   -class KeyPointMatcherDistance : public UntrainableDistance
113   -{
114   - Q_OBJECT
115   - Q_PROPERTY(QString matcher READ get_matcher WRITE set_matcher RESET reset_matcher STORED false)
116   - Q_PROPERTY(float maxRatio READ get_maxRatio WRITE set_maxRatio RESET reset_maxRatio STORED false)
117   - BR_PROPERTY(QString, matcher, "BruteForce")
118   - BR_PROPERTY(float, maxRatio, 0.8)
119   -
120   - Ptr<DescriptorMatcher> descriptorMatcher;
121   -
122   - void init()
123   - {
124   - descriptorMatcher = DescriptorMatcher::create(matcher.toStdString());
125   - if (descriptorMatcher.empty())
126   - qFatal("Failed to create DescriptorMatcher: %s", qPrintable(matcher));
127   - }
128   -
129   - float compare(const Mat &a, const Mat &b) const
130   - {
131   - if ((a.rows < 2) || (b.rows < 2)) return 0;
132   -
133   - std::vector< std::vector<DMatch> > matches;
134   - if (a.rows < b.rows) descriptorMatcher->knnMatch(a, b, matches, 2);
135   - else descriptorMatcher->knnMatch(b, a, matches, 2);
136   -
137   - QList<float> distances;
138   - foreach (const std::vector<DMatch> &match, matches) {
139   - if (match[0].distance / match[1].distance > maxRatio) continue;
140   - distances.append(match[0].distance);
141   - }
142   - qSort(distances);
143   -
144   - float similarity = 0;
145   - for (int i=0; i<distances.size(); i++)
146   - similarity += 1.f/(1+distances[i])/(i+1);
147   - return similarity;
148   - }
149   -};
150   -
151   -BR_REGISTER(Distance, KeyPointMatcherDistance)
152   -
153   -/*!
154   - * \ingroup transforms
155   - * \brief Specialize wrapper OpenCV SIFT wrapper
156   - * \author Josh Klontz \cite jklontz
157   - */
158   -class SIFTDescriptorTransform : public UntrainableTransform
159   -{
160   - Q_OBJECT
161   - Q_PROPERTY(int size READ get_size WRITE set_size RESET reset_size STORED false)
162   - Q_PROPERTY(QList<int> sizes READ get_sizes WRITE set_sizes RESET reset_sizes STORED false)
163   - Q_PROPERTY(int nFeatures READ get_nFeatures WRITE set_nFeatures RESET reset_nFeatures STORED false)
164   - Q_PROPERTY(int nOctaveLayers READ get_nOctaveLayers WRITE set_nOctaveLayers RESET reset_nOctaveLayers STORED false)
165   - Q_PROPERTY(double contrastThreshold READ get_contrastThreshold WRITE set_contrastThreshold RESET reset_contrastThreshold STORED false)
166   - Q_PROPERTY(double edgeThreshold READ get_edgeThreshold WRITE set_edgeThreshold RESET reset_edgeThreshold STORED false)
167   - Q_PROPERTY(double sigma READ get_sigma WRITE set_sigma RESET reset_sigma STORED false)
168   - BR_PROPERTY(int, size, 1)
169   - BR_PROPERTY(QList<int>, sizes, QList<int>())
170   - BR_PROPERTY(int, nFeatures, 0)
171   - BR_PROPERTY(int, nOctaveLayers, 3)
172   - BR_PROPERTY(double, contrastThreshold, 0.04)
173   - BR_PROPERTY(double, edgeThreshold, 10)
174   - BR_PROPERTY(double, sigma, 1.6)
175   -
176   - SIFT sift;
177   -
178   - void init()
179   - {
180   - if (sizes.empty())
181   - sizes.append(size);
182   - sift = SIFT(nFeatures, nOctaveLayers, contrastThreshold, edgeThreshold, sigma);
183   - }
184   -
185   - void project(const Template &src, Template &dst) const
186   - {
187   - std::vector<KeyPoint> keyPoints;
188   - foreach (const QPointF &val, src.file.points())
189   - foreach (const int r, sizes)
190   - keyPoints.push_back(KeyPoint(val.x(), val.y(), r));
191   -
192   - Mat m;
193   - sift(src, Mat(), keyPoints, m, true);
194   - m.setTo(0, m<0); // SIFT returns large negative values when it goes off the edge of the image.
195   - dst += m;
196   - }
197   -};
198   -
199   -BR_REGISTER(Transform, SIFTDescriptorTransform)
200   -
201   -/*!
202   - * \ingroup transforms
203   - * \brief OpenCV HOGDescriptor wrapper
204   - * \author Austin Blanton \cite imaus10
205   - */
206   -class HoGDescriptorTransform : public UntrainableTransform
207   -{
208   - Q_OBJECT
209   -
210   - HOGDescriptor hog;
211   -
212   - void project(const Template &src, Template &dst) const
213   - {
214   - std::vector<float> descriptorVals;
215   - std::vector<Point> locations;
216   - Size winStride = Size(0,0);
217   - Size padding = Size(0,0);
218   - foreach (const Mat &rect, src) {
219   - hog.compute(rect, descriptorVals, winStride, padding, locations);
220   - Mat HoGFeats(descriptorVals, true);
221   - dst += HoGFeats;
222   - }
223   - }
224   -};
225   -
226   -BR_REGISTER(Transform, HoGDescriptorTransform)
227   -
228   -/*!
229   - * \ingroup transforms
230   - * \brief Add landmarks to the template in a grid layout
231   - * \author Josh Klontz \cite jklontz
232   - */
233   -class GridTransform : public UntrainableTransform
234   -{
235   - Q_OBJECT
236   - Q_PROPERTY(int rows READ get_rows WRITE set_rows RESET reset_rows STORED false)
237   - Q_PROPERTY(int columns READ get_columns WRITE set_columns RESET reset_columns STORED false)
238   - BR_PROPERTY(int, rows, 1)
239   - BR_PROPERTY(int, columns, 1)
240   -
241   - void project(const Template &src, Template &dst) const
242   - {
243   - QList<QPointF> landmarks;
244   - const float row_step = 1.f * src.m().rows / rows;
245   - const float column_step = 1.f * src.m().cols / columns;
246   - for (float y=row_step/2; y<src.m().rows; y+=row_step)
247   - for (float x=column_step/2; x<src.m().cols; x+=column_step)
248   - landmarks.append(QPointF(x,y));
249   - dst = src;
250   - dst.file.setPoints(landmarks);
251   - }
252   -};
253   -
254   -BR_REGISTER(Transform, GridTransform)
255   -
256   -} // namespace br
257   -
258   -#include "keypoint.moc"
openbr/plugins/landmarks.cpp
... ... @@ -498,6 +498,30 @@ class NormalizePointsTransform : public UntrainableTransform
498 498  
499 499 BR_REGISTER(Transform, NormalizePointsTransform)
500 500  
  501 +class SetPointsInRectTransform : public UntrainableMetadataTransform
  502 +{
  503 + Q_OBJECT
  504 +
  505 + void projectMetadata(const File &src, File &dst) const
  506 + {
  507 + dst = src;
  508 +
  509 + QList<QRectF> rects = src.rects();
  510 + if (rects.size() != 1)
  511 + qFatal("Must have one and only one rect per template");
  512 + QRectF rect = rects.first();
  513 +
  514 + QList<QPointF> srcPoints = src.points();
  515 + QList<QPointF> dstPoints;
  516 + foreach (const QPointF &point, srcPoints)
  517 + dstPoints.append(QPointF(point.x() - rect.x(), point.y() - rect.y()));
  518 +
  519 + dst.setPoints(dstPoints);
  520 + }
  521 +};
  522 +
  523 +BR_REGISTER(Transform, SetPointsInRectTransform)
  524 +
501 525 /*!
502 526 * \ingroup transforms
503 527 * \brief Normalize points to be relative to a single point
... ...
openbr/plugins/lbp.cpp
... ... @@ -46,8 +46,6 @@ class LBPTransform : public UntrainableTransform
46 46 uchar lut[256];
47 47 uchar null;
48 48  
49   - friend class ColoredU2Transform;
50   -
51 49 /* Returns the number of 0->1 or 1->0 transitions in i */
52 50 static int numTransitions(int i)
53 51 {
... ... @@ -125,74 +123,6 @@ class LBPTransform : public UntrainableTransform
125 123  
126 124 BR_REGISTER(Transform, LBPTransform)
127 125  
128   -/*!
129   - * \ingroup transforms
130   - * \brief For visualization of LBP patterns.
131   - * \author Josh Klontz \cite jklontz
132   - */
133   -class ColoredU2Transform : public UntrainableTransform
134   -{
135   - Q_OBJECT
136   -
137   - /* Returns the number of 1 bits in i */
138   - static int bitCount(int i)
139   - {
140   - int count = 0;
141   - for (int j=0; j<8; j++)
142   - count += (i>>j)%2;
143   - return count;
144   - }
145   -
146   - void project(const Template &src, Template &dst) const
147   - {
148   - static Mat hueLUT, saturationLUT, valueLUT;
149   -
150   - if (!hueLUT.data) {
151   - const int NUM_COLORS = 10;
152   - hueLUT.create(1, 256, CV_8UC1);
153   - hueLUT.setTo(0);
154   -
155   - uchar uid = 0;
156   - for (int i=0; i<256; i++) {
157   - const int transitions = LBPTransform::numTransitions(i);
158   - int u2;
159   - if (transitions <= 2) u2 = uid++;
160   - else u2 = 58;
161   -
162   - // Assign hue based on bit count
163   - int color = bitCount(i);
164   - if (transitions > 2) color = NUM_COLORS-1;
165   - hueLUT.at<uchar>(0, u2) = 255*color/NUM_COLORS;
166   - }
167   -
168   - saturationLUT.create(1, 256, CV_8UC1);
169   - saturationLUT.setTo(255);
170   -
171   - valueLUT.create(1, 256, CV_8UC1);
172   - valueLUT.setTo(255*3/4);
173   - }
174   -
175   - if (src.m().type() != CV_8UC1)
176   - qFatal("Expected 8UC1 source type.");
177   -
178   - Mat hue, saturation, value;
179   - LUT(src, hueLUT, hue);
180   - LUT(src, saturationLUT, saturation);
181   - LUT(src, valueLUT, value);
182   -
183   - std::vector<Mat> mv;
184   - mv.push_back(hue);
185   - mv.push_back(saturation);
186   - mv.push_back(value);
187   -
188   - Mat coloredU2;
189   - merge(mv, coloredU2);
190   - cvtColor(coloredU2, dst, CV_HSV2BGR);
191   - }
192   -};
193   -
194   -BR_REGISTER(Transform, ColoredU2Transform)
195   -
196 126 } // namespace br
197 127  
198 128 #include "lbp.moc"
... ...
openbr/plugins/metadata/grid.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Add landmarks to the template in a grid layout
  9 + * \author Josh Klontz \cite jklontz
  10 + */
  11 +class GridTransform : public UntrainableTransform
  12 +{
  13 + Q_OBJECT
  14 + Q_PROPERTY(int rows READ get_rows WRITE set_rows RESET reset_rows STORED false)
  15 + Q_PROPERTY(int columns READ get_columns WRITE set_columns RESET reset_columns STORED false)
  16 + BR_PROPERTY(int, rows, 1)
  17 + BR_PROPERTY(int, columns, 1)
  18 +
  19 + void project(const Template &src, Template &dst) const
  20 + {
  21 + QList<QPointF> landmarks;
  22 + const float row_step = 1.f * src.m().rows / rows;
  23 + const float column_step = 1.f * src.m().cols / columns;
  24 + for (float y=row_step/2; y<src.m().rows; y+=row_step)
  25 + for (float x=column_step/2; x<src.m().cols; x+=column_step)
  26 + landmarks.append(QPointF(x,y));
  27 + dst = src;
  28 + dst.file.setPoints(landmarks);
  29 + }
  30 +};
  31 +
  32 +BR_REGISTER(Transform, GridTransform)
  33 +
  34 +} // namespace br
  35 +
  36 +#include "grid.moc"
... ...
openbr/plugins/metadata/keytorect.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Convert values of key_X, key_Y, key_Width, key_Height to a rect.
  9 + * \author Jordan Cheney \cite JordanCheney
  10 + */
  11 +class KeyToRectTransform : public UntrainableMetadataTransform
  12 +{
  13 + Q_OBJECT
  14 + Q_PROPERTY(QString key READ get_key WRITE set_key RESET reset_key STORED false)
  15 + BR_PROPERTY(QString, key, "")
  16 +
  17 + void projectMetadata(const File &src, File &dst) const
  18 + {
  19 + dst = src;
  20 +
  21 + if (src.contains(QStringList() << key + "_X" << key + "_Y" << key + "_Width" << key + "_Height"))
  22 + dst.appendRect(QRectF(src.get<int>(key + "_X"),
  23 + src.get<int>(key + "_Y"),
  24 + src.get<int>(key + "_Width"),
  25 + src.get<int>(key + "_Height")));
  26 +
  27 + }
  28 +
  29 +};
  30 +
  31 +BR_REGISTER(Transform, KeyToRectTransform)
  32 +
  33 +} // namespace br
  34 +
  35 +#include "keytorect.moc"
... ...