Commit b34029cc89b22994e6464b16479488ee7a775525

Authored by Jordan Cheney
1 parent f645840e

Incremental progress for plugins reorg

Showing 113 changed files with 5111 additions and 4674 deletions
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"
... ...
openbr/plugins/metadata/procrustes.cpp 0 โ†’ 100644
  1 +#include <Eigen/Dense>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup transforms
  10 + * \brief Procrustes alignment of points
  11 + * \author Scott Klum \cite sklum
  12 + */
  13 +class ProcrustesTransform : public MetadataTransform
  14 +{
  15 + Q_OBJECT
  16 +
  17 + Q_PROPERTY(bool warp READ get_warp WRITE set_warp RESET reset_warp STORED false)
  18 + BR_PROPERTY(bool, warp, true)
  19 +
  20 + Eigen::MatrixXf meanShape;
  21 +
  22 + void train(const TemplateList &data)
  23 + {
  24 + QList< QList<QPointF> > normalizedPoints;
  25 +
  26 + // Normalize all sets of points
  27 + foreach (br::Template datum, data) {
  28 + QList<QPointF> points = datum.file.points();
  29 + QList<QRectF> rects = datum.file.rects();
  30 +
  31 + if (points.empty() || rects.empty()) continue;
  32 +
  33 + // Assume rect appended last was bounding box
  34 + points.append(rects.last().topLeft());
  35 + points.append(rects.last().topRight());
  36 + points.append(rects.last().bottomLeft());
  37 + points.append(rects.last().bottomRight());
  38 +
  39 + // Center shape at origin
  40 + Scalar mean = cv::mean(OpenCVUtils::toPoints(points).toVector().toStdVector());
  41 + for (int i = 0; i < points.size(); i++) points[i] -= QPointF(mean[0],mean[1]);
  42 +
  43 + // Remove scale component
  44 + float norm = cv::norm(OpenCVUtils::toPoints(points).toVector().toStdVector());
  45 + for (int i = 0; i < points.size(); i++) points[i] /= norm;
  46 +
  47 + normalizedPoints.append(points);
  48 + }
  49 +
  50 + if (normalizedPoints.empty()) qFatal("Unable to calculate normalized points");
  51 +
  52 + // Determine mean shape, assuming all shapes contain the same number of points
  53 + meanShape = Eigen::MatrixXf(normalizedPoints[0].size(), 2);
  54 +
  55 + for (int i = 0; i < normalizedPoints[0].size(); i++) {
  56 + double x = 0;
  57 + double y = 0;
  58 +
  59 + for (int j = 0; j < normalizedPoints.size(); j++) {
  60 + x += normalizedPoints[j][i].x();
  61 + y += normalizedPoints[j][i].y();
  62 + }
  63 +
  64 + x /= (double)normalizedPoints.size();
  65 + y /= (double)normalizedPoints.size();
  66 +
  67 + meanShape(i,0) = x;
  68 + meanShape(i,1) = y;
  69 + }
  70 + }
  71 +
  72 + void project(const Template &src, Template &dst) const
  73 + {
  74 + QList<QPointF> points = src.file.points();
  75 + QList<QRectF> rects = src.file.rects();
  76 +
  77 + if (points.empty() || rects.empty()) {
  78 + dst = src;
  79 + if (Globals->verbose) qWarning("Procrustes alignment failed because points or rects are empty.");
  80 + return;
  81 + }
  82 +
  83 + // Assume rect appended last was bounding box
  84 + points.append(rects.last().topLeft());
  85 + points.append(rects.last().topRight());
  86 + points.append(rects.last().bottomLeft());
  87 + points.append(rects.last().bottomRight());
  88 +
  89 + Scalar mean = cv::mean(OpenCVUtils::toPoints(points).toVector().toStdVector());
  90 + for (int i = 0; i < points.size(); i++) points[i] -= QPointF(mean[0],mean[1]);
  91 +
  92 + Eigen::MatrixXf srcMat(points.size(), 2);
  93 + float norm = cv::norm(OpenCVUtils::toPoints(points).toVector().toStdVector());
  94 + for (int i = 0; i < points.size(); i++) {
  95 + points[i] /= norm;
  96 + srcMat(i,0) = points[i].x();
  97 + srcMat(i,1) = points[i].y();
  98 + }
  99 +
  100 + Eigen::JacobiSVD<Eigen::MatrixXf> svd(srcMat.transpose()*meanShape, Eigen::ComputeThinU | Eigen::ComputeThinV);
  101 + Eigen::MatrixXf R = svd.matrixU()*svd.matrixV().transpose();
  102 +
  103 + dst = src;
  104 +
  105 + // Store procrustes stats in the order:
  106 + // R(0,0), R(1,0), R(1,1), R(0,1), mean_x, mean_y, norm
  107 + QList<float> procrustesStats;
  108 + procrustesStats << R(0,0) << R(1,0) << R(1,1) << R(0,1) << mean[0] << mean[1] << norm;
  109 + dst.file.setList<float>("ProcrustesStats",procrustesStats);
  110 +
  111 + if (warp) {
  112 + Eigen::MatrixXf dstMat = srcMat*R;
  113 + for (int i = 0; i < dstMat.rows(); i++) {
  114 + dst.file.appendPoint(QPointF(dstMat(i,0),dstMat(i,1)));
  115 + }
  116 + }
  117 + }
  118 +
  119 + void store(QDataStream &stream) const
  120 + {
  121 + stream << meanShape;
  122 + }
  123 +
  124 + void load(QDataStream &stream)
  125 + {
  126 + stream >> meanShape;
  127 + }
  128 +
  129 +};
  130 +
  131 +BR_REGISTER(Transform, ProcrustesTransform)
  132 +
  133 +} // namespace br
  134 +
  135 +#include "procrustes.moc"
... ...
openbr/plugins/motion.cpp
... ... @@ -59,48 +59,6 @@ class OpticalFlowTransform : public UntrainableMetaTransform
59 59  
60 60 BR_REGISTER(Transform, OpticalFlowTransform)
61 61  
62   -/*!
63   - * \ingroup transforms
64   - * \brief Wraps OpenCV's BackgroundSubtractorMOG2 and puts the foreground mask in the Template metadata.
65   - * \author Austin Blanton \cite imaus10
66   - */
67   -class SubtractBackgroundTransform : public TimeVaryingTransform
68   -{
69   - Q_OBJECT
70   -
71   - // TODO: This is broken.
72   - // BackgroundSubtractorMOG2 mog;
73   -
74   -public:
75   - SubtractBackgroundTransform() : TimeVaryingTransform(false, false) {}
76   -
77   -private:
78   - void projectUpdate(const Template &src, Template &dst)
79   - {
80   - dst = src;
81   - Mat mask;
82   - // TODO: broken
83   - // mog(src, mask);
84   - erode(mask, mask, Mat());
85   - dilate(mask, mask, Mat());
86   - dst.file.set("Mask", QVariant::fromValue(mask));
87   - }
88   -
89   - void project(const Template &src, Template &dst) const
90   - {
91   - (void) src; (void) dst; qFatal("no way");
92   - }
93   -
94   - void finalize(TemplateList &output)
95   - {
96   - (void) output;
97   - // TODO: Broken
98   - // mog = BackgroundSubtractorMOG2();
99   - }
100   -};
101   -
102   -BR_REGISTER(Transform, SubtractBackgroundTransform)
103   -
104 62 } // namespace br
105 63  
106 64 #include "motion.moc"
... ...
openbr/plugins/plugins.cmake
... ... @@ -12,8 +12,28 @@ foreach(DIR ${BR_THIRDPARTY_PLUGINS_DIR})
12 12 set(BR_THIRDPARTY_PLUGINS ${BR_THIRDPARTY_PLUGINS} ${PLUGINS})
13 13 endforeach()
14 14  
  15 +set(BR_PLUGINS_DIR ${BR_PLUGINS_DIR} core)
  16 +set(BR_PLUGINS_DIR ${BR_PLUGINS_DIR} io)
  17 +set(BR_PLUGINS_DIR ${BR_PLUGINS_DIR} gui)
  18 +set(BR_PLUGINS_DIR ${BR_PLUGINS_DIR} imgproc)
  19 +set(BR_PLUGINS_DIR ${BR_PLUGINS_DIR} video)
  20 +set(BR_PLUGINS_DIR ${BR_PLUGINS_DIR} cluster)
  21 +set(BR_PLUGINS_DIR ${BR_PLUGINS_DIR} distance)
  22 +set(BR_PLUGINS_DIR ${BR_PLUGINS_DIR} format)
  23 +set(BR_PLUGINS_DIR ${BR_PLUGINS_DIR} representation)
  24 +set(BR_PLUGINS_DIR ${BR_PLUGINS_DIR} detection)
  25 +set(BR_PLUGINS_DIR ${BR_PLUGINS_DIR} classification)
  26 +set(BR_PLUGINS_DIR ${BR_PLUGINS_DIR} metadata)
  27 +
  28 +
  29 +foreach(DIR ${BR_PLUGINS_DIR})
  30 + file(GLOB PLUGINS plugins/${DIR}/*.cpp plugins/${DIR}/*.h)
  31 + set(BR_PLUGINS ${BR_PLUGINS} ${PLUGINS})
  32 +endforeach()
  33 +
15 34 file(GLOB PLUGINS plugins/*.cpp plugins/*.h)
16   -foreach(PLUGIN ${PLUGINS} ${BR_THIRDPARTY_PLUGINS})
  35 +set(BR_PLUGINS ${BR_PLUGINS} ${PLUGINS})
  36 +foreach(PLUGIN ${BR_PLUGINS} ${BR_THIRDPARTY_PLUGINS})
17 37 get_filename_component(PLUGIN_BASENAME ${PLUGIN} NAME_WE)
18 38 get_filename_component(PLUGIN_PATH ${PLUGIN} PATH)
19 39 set(PLUGIN_CMAKE "${PLUGIN_PATH}/${PLUGIN_BASENAME}.cmake")
... ...
openbr/plugins/quantize.cpp
... ... @@ -287,56 +287,6 @@ class ProductQuantizationDistance : public UntrainableDistance
287 287 BR_REGISTER(Distance, ProductQuantizationDistance)
288 288  
289 289 /*!
290   - * \ingroup distances
291   - * \brief Recurively computed distance in a product quantized space
292   - * \author Josh Klontz \cite jklontz
293   - */
294   -class RecursiveProductQuantizationDistance : public UntrainableDistance
295   -{
296   - Q_OBJECT
297   - Q_PROPERTY(float t READ get_t WRITE set_t RESET reset_t STORED false)
298   - BR_PROPERTY(float, t, -std::numeric_limits<float>::max())
299   -
300   - float compare(const Template &a, const Template &b) const
301   - {
302   - return compareRecursive(a, b, 0, a.size(), 0);
303   - }
304   -
305   - float compareRecursive(const QList<cv::Mat> &a, const QList<cv::Mat> &b, int i, int size, float evidence) const
306   - {
307   - float similarity = 0;
308   -
309   - const int elements = a[i].total()-sizeof(quint16);
310   - uchar *aData = a[i].data;
311   - uchar *bData = b[i].data;
312   - quint16 index = *reinterpret_cast<quint16*>(aData);
313   - aData += sizeof(quint16);
314   - bData += sizeof(quint16);
315   -
316   - const float *lut = (const float*)ProductQuantizationLUTs[index].data;
317   - for (int j=0; j<elements; j++) {
318   - const int aj = aData[j];
319   - const int bj = bData[j];
320   - // http://stackoverflow.com/questions/4803180/mapping-elements-in-2d-upper-triangle-and-lower-triangle-to-linear-structure
321   - const int y = max(aj, bj);
322   - const int x = min(aj, bj);
323   - similarity += lut[j*256*(256+1)/2 + x + (y+1)*y/2];
324   - }
325   -
326   - evidence += similarity;
327   - const int subSize = (size-1)/4;
328   - if ((evidence < t) || (subSize == 0)) return similarity;
329   - return similarity
330   - + compareRecursive(a, b, i+1+0*subSize, subSize, evidence)
331   - + compareRecursive(a, b, i+1+1*subSize, subSize, evidence)
332   - + compareRecursive(a, b, i+1+2*subSize, subSize, evidence)
333   - + compareRecursive(a, b, i+1+3*subSize, subSize, evidence);
334   - }
335   -};
336   -
337   -BR_REGISTER(Distance, RecursiveProductQuantizationDistance)
338   -
339   -/*!
340 290 * \ingroup transforms
341 291 * \brief Product quantization \cite jegou11
342 292 * \author Josh Klontz \cite jklontz
... ...
openbr/plugins/random.cpp
... ... @@ -96,38 +96,61 @@ BR_REGISTER(Transform, RndSubspaceTransform)
96 96  
97 97 /*!
98 98 * \ingroup transforms
99   - * \brief Selects a random region.
100   - * \author Josh Klontz \cite jklontz
  99 + * \brief Selects a number of random regions from a negative image.
  100 + * \author Jordan Cheney \cite JordanCheney
101 101 */
102   -class RndRegionTransform : public Transform
  102 +class RndNegSampleTransform : public UntrainableMetaTransform
103 103 {
104 104 Q_OBJECT
105   - Q_PROPERTY(float x READ get_x WRITE set_x RESET reset_x)
106   - Q_PROPERTY(float y READ get_y WRITE set_y RESET reset_y)
107   - Q_PROPERTY(float width READ get_width WRITE set_width RESET reset_width)
108   - Q_PROPERTY(float height READ get_height WRITE set_height RESET reset_height)
109   - BR_PROPERTY(float, x, -1)
110   - BR_PROPERTY(float, y, -1)
111   - BR_PROPERTY(float, width, -1)
112   - BR_PROPERTY(float, height, -1)
  105 + Q_PROPERTY(int numSamples READ get_numSamples WRITE set_numSamples RESET reset_numSamples STORED false)
  106 + Q_PROPERTY(int width READ get_width WRITE set_width RESET reset_width STORED false)
  107 + Q_PROPERTY(int height READ get_height WRITE set_height RESET reset_height STORED false)
  108 + Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false)
  109 + Q_PROPERTY(float negVal READ get_negVal WRITE set_negVal RESET reset_negVal STORED false)
  110 + BR_PROPERTY(int, numSamples, 1)
  111 + BR_PROPERTY(int, width, 24)
  112 + BR_PROPERTY(int, height, 24)
  113 + BR_PROPERTY(QString, propName, "Label")
  114 + BR_PROPERTY(float, negVal, 0)
113 115  
114   - void train(const TemplateList &data)
  116 + void project(const Template &src, Template &dst) const
115 117 {
116   - (void) data;
  118 + dst = src;
  119 +
  120 + if (src.file.get<float>(propName, negVal+1) == negVal)
  121 + return;
117 122  
118 123 RNG &rng = theRNG();
119   - width = rng.uniform(0.f, 1.f);
120   - height = rng.uniform(0.f, 1.f);
121   - x = rng.uniform(0.f, 1.f-width);
122   - y = rng.uniform(0.f, 1.f-height);
  124 + for (int n = 0; n < numSamples; n++) {
  125 + int x = rng.uniform(0, src.m().cols - width - 1);
  126 + int y = rng.uniform(0, src.m().rows - height - 1);
  127 + dst.file.appendRect(Rect(x, y, width, height));
  128 + }
123 129 }
  130 +};
  131 +
  132 +BR_REGISTER(Transform, RndNegSampleTransform)
  133 +
  134 +/*!
  135 + * \ingroup transforms
  136 + * \brief Selects a random region.
  137 + * \author Josh Klontz \cite jklontz
  138 + */
  139 +class RndRegionTransform : public UntrainableTransform
  140 +{
  141 + Q_OBJECT
124 142  
125 143 void project(const Template &src, Template &dst) const
126 144 {
  145 + RNG &rng = theRNG();
  146 + float size = rng.uniform(0.2f, 1.f);
  147 + float x = rng.uniform(0.f, 1.f-size);
  148 + float y = rng.uniform(0.f, 1.f-size);
  149 +
127 150 dst = src.m()(Rect(src.m().cols * x,
128 151 src.m().rows * y,
129   - src.m().cols * width,
130   - src.m().rows * height));
  152 + src.m().cols * size,
  153 + src.m().rows * size));
131 154 }
132 155 };
133 156  
... ...
openbr/plugins/regions.cpp
... ... @@ -374,8 +374,12 @@ class RectFromPointsTransform : public UntrainableTransform
374 374  
375 375 QList<QPointF> points;
376 376  
377   - foreach (int index, indices) {
  377 + int numPoints = (indices.empty() ? src.file.points().size() : indices.size());
  378 + for (int idx = 0; idx < numPoints; idx++) {
  379 + int index = indices.empty() ? idx : indices[idx];
378 380 if (src.file.points().size() > index) {
  381 + if (src.file.points()[index].x() <= 0 ||
  382 + src.file.points()[index].y() <= 0) continue;
379 383 if (src.file.points()[index].x() < minX) minX = src.file.points()[index].x();
380 384 if (src.file.points()[index].x() > maxX) maxX = src.file.points()[index].x();
381 385 if (src.file.points()[index].y() < minY) minY = src.file.points()[index].y();
... ... @@ -390,8 +394,9 @@ class RectFromPointsTransform : public UntrainableTransform
390 394 width += deltaWidth;
391 395  
392 396 double height = maxY-minY;
393   - double deltaHeight = width/aspectRatio - height;
394   - height += deltaHeight;
  397 + //double deltaHeight = width/aspectRatio - height;
  398 + double deltaHeight = height*padding;
  399 + height += deltaHeight;
395 400  
396 401 const int x = std::max(0.0, minX - deltaWidth/2.0);
397 402 const int y = std::max(0.0, minY - deltaHeight/2.0);
... ...
openbr/plugins/representation/hogdescriptor.cpp 0 โ†’ 100644
  1 +#include <opencv2/objdetect/objdetect.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 OpenCV HOGDescriptor wrapper
  13 + * \author Austin Blanton \cite imaus10
  14 + */
  15 +class HoGDescriptorTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 +
  19 + HOGDescriptor hog;
  20 +
  21 + void project(const Template &src, Template &dst) const
  22 + {
  23 + std::vector<float> descriptorVals;
  24 + std::vector<Point> locations;
  25 + Size winStride = Size(0,0);
  26 + Size padding = Size(0,0);
  27 + foreach (const Mat &rect, src) {
  28 + hog.compute(rect, descriptorVals, winStride, padding, locations);
  29 + Mat HoGFeats(descriptorVals, true);
  30 + dst += HoGFeats;
  31 + }
  32 + }
  33 +};
  34 +
  35 +BR_REGISTER(Transform, HoGDescriptorTransform)
  36 +
  37 +} // namespace br
  38 +
  39 +#include "hogdescriptor.moc"
... ...
openbr/plugins/representation/keypointdescriptor.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 Descriptor
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class KeyPointDescriptorTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 + Q_PROPERTY(QString descriptor READ get_descriptor WRITE set_descriptor RESET reset_descriptor STORED false)
  19 + Q_PROPERTY(int size READ get_size WRITE set_size RESET reset_size STORED false)
  20 + BR_PROPERTY(QString, descriptor, "SIFT")
  21 + BR_PROPERTY(int, size, -1)
  22 +
  23 + Ptr<DescriptorExtractor> descriptorExtractor;
  24 +
  25 + void init()
  26 + {
  27 + descriptorExtractor = DescriptorExtractor::create(descriptor.toStdString());
  28 + if (descriptorExtractor.empty())
  29 + qFatal("Failed to create DescriptorExtractor: %s", qPrintable(descriptor));
  30 + }
  31 +
  32 + void project(const Template &src, Template &dst) const
  33 + {
  34 + std::vector<KeyPoint> keyPoints;
  35 + if (size == -1)
  36 + foreach (const QRectF &ROI, src.file.rects())
  37 + keyPoints.push_back(KeyPoint(ROI.x()+ROI.width()/2, ROI.y()+ROI.height()/2, (ROI.width() + ROI.height())/2));
  38 + else
  39 + foreach (const QPointF &landmark, src.file.points())
  40 + keyPoints.push_back(KeyPoint(landmark.x(), landmark.y(), size));
  41 + if (keyPoints.empty()) return;
  42 + descriptorExtractor->compute(src, keyPoints, dst);
  43 + }
  44 +};
  45 +
  46 +BR_REGISTER(Transform, KeyPointDescriptorTransform)
  47 +
  48 +} // namespace br
  49 +
  50 +#include "keypointdescriptor.moc"
... ...
openbr/plugins/representation/siftdescriptor.cpp 0 โ†’ 100644
  1 +#include <opencv2/nonfree/nonfree.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 Specialize wrapper OpenCV SIFT wrapper
  13 + * \author Josh Klontz \cite jklontz
  14 + */
  15 +class SIFTDescriptorTransform : public UntrainableTransform
  16 +{
  17 + Q_OBJECT
  18 + Q_PROPERTY(int size READ get_size WRITE set_size RESET reset_size STORED false)
  19 + Q_PROPERTY(QList<int> sizes READ get_sizes WRITE set_sizes RESET reset_sizes STORED false)
  20 + Q_PROPERTY(int nFeatures READ get_nFeatures WRITE set_nFeatures RESET reset_nFeatures STORED false)
  21 + Q_PROPERTY(int nOctaveLayers READ get_nOctaveLayers WRITE set_nOctaveLayers RESET reset_nOctaveLayers STORED false)
  22 + Q_PROPERTY(double contrastThreshold READ get_contrastThreshold WRITE set_contrastThreshold RESET reset_contrastThreshold STORED false)
  23 + Q_PROPERTY(double edgeThreshold READ get_edgeThreshold WRITE set_edgeThreshold RESET reset_edgeThreshold STORED false)
  24 + Q_PROPERTY(double sigma READ get_sigma WRITE set_sigma RESET reset_sigma STORED false)
  25 + BR_PROPERTY(int, size, 1)
  26 + BR_PROPERTY(QList<int>, sizes, QList<int>())
  27 + BR_PROPERTY(int, nFeatures, 0)
  28 + BR_PROPERTY(int, nOctaveLayers, 3)
  29 + BR_PROPERTY(double, contrastThreshold, 0.04)
  30 + BR_PROPERTY(double, edgeThreshold, 10)
  31 + BR_PROPERTY(double, sigma, 1.6)
  32 +
  33 + SIFT sift;
  34 +
  35 + void init()
  36 + {
  37 + if (sizes.empty())
  38 + sizes.append(size);
  39 + sift = SIFT(nFeatures, nOctaveLayers, contrastThreshold, edgeThreshold, sigma);
  40 + }
  41 +
  42 + void project(const Template &src, Template &dst) const
  43 + {
  44 + std::vector<KeyPoint> keyPoints;
  45 + foreach (const QPointF &val, src.file.points())
  46 + foreach (const int r, sizes)
  47 + keyPoints.push_back(KeyPoint(val.x(), val.y(), r));
  48 +
  49 + Mat m;
  50 + sift(src, Mat(), keyPoints, m, true);
  51 + m.setTo(0, m<0); // SIFT returns large negative values when it goes off the edge of the image.
  52 + dst += m;
  53 + }
  54 +};
  55 +
  56 +BR_REGISTER(Transform, SIFTDescriptorTransform)
  57 +
  58 +} // namespace br
  59 +
  60 +#include "siftdescriptor.moc"
... ...
openbr/plugins/sentence.cpp deleted
1   -#include <stdint.h>
2   -#include "openbr_internal.h"
3   -
4   -using namespace cv;
5   -
6   -namespace br
7   -{
8   -
9   -/*!
10   - * \ingroup transforms
11   - * \brief Ordered words
12   - * \author Josh Klontz \cite jklontz
13   - */
14   -class SentenceTransform : public UntrainableMetaTransform
15   -{
16   - Q_OBJECT
17   -
18   - void project(const Template &src, Template &dst) const
19   - {
20   - QByteArray sentence;
21   - QDataStream stream(&sentence, QIODevice::WriteOnly);
22   - for (int i=0; i<src.size(); i++) {
23   - const Mat &m = src[i];
24   - if (!m.data) continue;
25   - stream.writeRawData((const char*)&i, 4);
26   - stream.writeRawData((const char*)&m.rows, 4);
27   - stream.writeRawData((const char*)&m.cols, 4);
28   - stream.writeRawData((const char*)m.data, 4*m.rows*m.cols);
29   - }
30   - dst.file = src.file;
31   - dst.m() = Mat(1, sentence.size(), CV_8UC1, sentence.data()).clone();
32   - }
33   -};
34   -
35   -BR_REGISTER(Transform, SentenceTransform)
36   -
37   -/*!
38   - * \ingroup distances
39   - * \brief Distance between sentences
40   - * \author Josh Klontz \cite jklontz
41   - */
42   -class SentenceSimilarityDistance : public UntrainableDistance
43   -{
44   - Q_OBJECT
45   -
46   - float compare(const Mat &a, const Mat &b) const
47   - {
48   - uchar *aBuffer = a.data;
49   - uchar *bBuffer = b.data;
50   - const uchar *aEnd = aBuffer + a.cols;
51   - const uchar *bEnd = bBuffer + b.cols;
52   -
53   - int32_t aWord, bWord, aRows, bRows, aColumns, bColumns;
54   - float *aData, *bData;
55   - aWord = aRows = aColumns = -2;
56   - bWord = bRows = bColumns = -1;
57   - aData = bData = NULL;
58   -
59   - float distance = 0;
60   - int comparisons = 0;
61   - while (true) {
62   - if (aWord < bWord) {
63   - if (aBuffer == aEnd) return distance == 0 ? -std::numeric_limits<float>::max() : comparisons / distance;
64   - aWord = *reinterpret_cast<int32_t*>(aBuffer);
65   - aRows = *reinterpret_cast<int32_t*>(aBuffer+4);
66   - aColumns = *reinterpret_cast<int32_t*>(aBuffer+8);
67   - aData = reinterpret_cast<float*>(aBuffer+12);
68   - aBuffer += 12 + 4*aRows*aColumns;
69   - } else if (bWord < aWord) {
70   - if (bBuffer == bEnd) return comparisons == 0 ? -std::numeric_limits<float>::max() : comparisons / distance;
71   - bWord = *reinterpret_cast<int32_t*>(bBuffer);
72   - bRows = *reinterpret_cast<int32_t*>(bBuffer+4);
73   - bColumns = *reinterpret_cast<int32_t*>(bBuffer+8);
74   - bData = reinterpret_cast<float*>(bBuffer+12);
75   - bBuffer += 12 + 4*bRows*bColumns;
76   - } else {
77   - for (int i=0; i<aRows; i++)
78   - for (int j=0; j<bRows; j++)
79   - for (int k=0; k<aColumns; k++)
80   - distance += pow(aData[i*aColumns+k] - bData[j*bColumns+k], 2.f);
81   - comparisons += aRows * bRows * aColumns;
82   - aWord = -2;
83   - bWord = -1;
84   - }
85   - }
86   - }
87   -};
88   -
89   -BR_REGISTER(Distance, SentenceSimilarityDistance)
90   -
91   -} // namespace br
92   -
93   -#include "sentence.moc"
openbr/plugins/stasm4.cmake
1   -set(BR_WITH_STASM4 ON CACHE BOOL "Build with Stasm")
  1 +set(BR_WITH_STASM4 OFF CACHE BOOL "Build with Stasm")
2 2  
3 3 if(${BR_WITH_STASM4})
4 4 find_package(Stasm4 REQUIRED)
... ...
openbr/plugins/frames.cpp renamed to openbr/plugins/video/aggregate.cpp
1   -#include "openbr_internal.h"
  1 +#include <openbr/plugins/openbr_internal.h>
2 2  
3 3 namespace br
4 4 {
... ... @@ -56,33 +56,6 @@ private:
56 56  
57 57 BR_REGISTER(Transform, AggregateFrames)
58 58  
59   -/*!
60   - * \ingroup transforms
61   - * \brief Only use one frame every n frames.
62   - * \author Austin Blanton \cite imaus10
63   - *
64   - * For a video with m frames, DropFrames will pass on m/n frames.
65   - */
66   -class DropFrames : public UntrainableMetaTransform
67   -{
68   - Q_OBJECT
69   - Q_PROPERTY(int n READ get_n WRITE set_n RESET reset_n STORED false)
70   - BR_PROPERTY(int, n, 1)
71   -
72   - void project(const TemplateList &src, TemplateList &dst) const
73   - {
74   - if (src.first().file.get<int>("FrameNumber") % n != 0) return;
75   - dst = src;
76   - }
77   -
78   - void project(const Template &src, Template &dst) const
79   - {
80   - (void) src; (void) dst; qFatal("shouldn't be here");
81   - }
82   -};
83   -
84   -BR_REGISTER(Transform, DropFrames)
85   -
86 59 } // namespace br
87 60  
88   -#include "frames.moc"
  61 +#include "aggregate.moc"
... ...
openbr/plugins/video/drop.cpp 0 โ†’ 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Only use one frame every n frames.
  9 + * \author Austin Blanton \cite imaus10
  10 + *
  11 + * For a video with m frames, DropFrames will pass on m/n frames.
  12 + */
  13 +class DropFrames : public UntrainableMetaTransform
  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 TemplateList &src, TemplateList &dst) const
  20 + {
  21 + if (src.first().file.get<int>("FrameNumber") % n != 0) return;
  22 + dst = src;
  23 + }
  24 +
  25 + void project(const Template &src, Template &dst) const
  26 + {
  27 + (void) src; (void) dst; qFatal("shouldn't be here");
  28 + }
  29 +};
  30 +
  31 +BR_REGISTER(Transform, DropFrames)
  32 +
  33 +} // namespace br
  34 +
  35 +#include "drop.moc"
... ...