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 #include <opencv2/imgproc/imgproc.hpp> 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 using namespace cv; 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 using namespace cv; 4 using namespace cv;
25 5
@@ -28,58 +8,6 @@ namespace br @@ -28,58 +8,6 @@ namespace br
28 8
29 /*! 9 /*!
30 * \ingroup transforms 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 * \brief K nearest neighbors classifier. 11 * \brief K nearest neighbors classifier.
84 * \author Josh Klontz \cite jklontz 12 * \author Josh Klontz \cite jklontz
85 */ 13 */
@@ -151,148 +79,6 @@ class KNNTransform : public Transform @@ -151,148 +79,6 @@ class KNNTransform : public Transform
151 79
152 BR_REGISTER(Transform, KNNTransform) 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 } // namespace br 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,7 +14,7 @@
14 * limitations under the License. * 14 * limitations under the License. *
15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 16
17 -#include "openbr_internal.h" 17 +#include <openbr/plugins/openbr_internal.h>
18 18
19 namespace br 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 namespace br 3 namespace br
10 { 4 {
@@ -103,10 +97,10 @@ class DownsampleTrainingTransform : public Transform @@ -103,10 +97,10 @@ class DownsampleTrainingTransform : public Transform
103 97
104 void project(const Template &src, Template &dst) const 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 void train(const TemplateList &data) 104 void train(const TemplateList &data)
111 { 105 {
112 if (!transform || !transform->trainable) 106 if (!transform || !transform->trainable)
@@ -117,274 +111,9 @@ class DownsampleTrainingTransform : public Transform @@ -117,274 +111,9 @@ class DownsampleTrainingTransform : public Transform
117 transform->train(downsampled); 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 } // namespace br 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,7 +15,7 @@
15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 16
17 #include <opencv2/objdetect/objdetect.hpp> 17 #include <opencv2/objdetect/objdetect.hpp>
18 -#include "openbr_internal.h" 18 +#include <openbr/plugins/openbr_internal.h>
19 #include "openbr/core/opencvutils.h" 19 #include "openbr/core/opencvutils.h"
20 #include "openbr/core/resource.h" 20 #include "openbr/core/resource.h"
21 #include "openbr/core/qtutils.h" 21 #include "openbr/core/qtutils.h"
openbr/plugins/eyes.cpp renamed to openbr/plugins/detection/eyes.cpp
@@ -35,8 +35,9 @@ @@ -35,8 +35,9 @@
35 35
36 #include <opencv2/imgproc/imgproc.hpp> 36 #include <opencv2/imgproc/imgproc.hpp>
37 #include <opencv2/imgproc/imgproc_c.h> 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 using namespace cv; 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,46 +652,6 @@ class SparseLDATransform : public Transform
652 652
653 BR_REGISTER(Transform, SparseLDATransform) 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 } // namespace br 655 } // namespace br
696 656
697 #include "eigen3.moc" 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,6 +928,54 @@ public:
928 928
929 BR_REGISTER(Transform, SurveyTransform) 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 * \ingroup transforms 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,7 +15,8 @@
15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 16
17 #include <opencv2/photo/photo.hpp> 17 #include <opencv2/photo/photo.hpp>
18 -#include "openbr_internal.h" 18 +
  19 +#include <openbr/plugins/openbr_internal.h>
19 20
20 using namespace cv; 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 using namespace cv; 3 using namespace cv;
23 4
@@ -26,52 +7,10 @@ namespace br @@ -26,52 +7,10 @@ namespace br
26 7
27 /*! 8 /*!
28 * \ingroup transforms 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 * \brief Quantizes the values into bins. 10 * \brief Quantizes the values into bins.
72 * \author Josh Klontz \cite jklontz 11 * \author Josh Klontz \cite jklontz
73 */ 12 */
74 -class BinTransform : public UntrainableTransform 13 +class HistBinTransform : public UntrainableTransform
75 { 14 {
76 Q_OBJECT 15 Q_OBJECT
77 Q_PROPERTY(float min READ get_min WRITE set_min RESET reset_min STORED false) 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,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 } // namespace br 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 using namespace cv; 5 using namespace cv;
9 6
@@ -12,23 +9,6 @@ namespace br @@ -12,23 +9,6 @@ namespace br
12 9
13 /*! 10 /*!
14 * \ingroup transforms 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 * \brief Sliding window feature extraction from a multi-channel integral image. 12 * \brief Sliding window feature extraction from a multi-channel integral image.
33 * \author Josh Klontz \cite jklontz 13 * \author Josh Klontz \cite jklontz
34 */ 14 */
@@ -121,254 +101,6 @@ class IntegralSamplerTransform : public UntrainableTransform @@ -121,254 +101,6 @@ class IntegralSamplerTransform : public UntrainableTransform
121 101
122 BR_REGISTER(Transform, IntegralSamplerTransform) 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 } // namespace br 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,6 +498,30 @@ class NormalizePointsTransform : public UntrainableTransform
498 498
499 BR_REGISTER(Transform, NormalizePointsTransform) 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 * \ingroup transforms 526 * \ingroup transforms
503 * \brief Normalize points to be relative to a single point 527 * \brief Normalize points to be relative to a single point
openbr/plugins/lbp.cpp
@@ -46,8 +46,6 @@ class LBPTransform : public UntrainableTransform @@ -46,8 +46,6 @@ class LBPTransform : public UntrainableTransform
46 uchar lut[256]; 46 uchar lut[256];
47 uchar null; 47 uchar null;
48 48
49 - friend class ColoredU2Transform;  
50 -  
51 /* Returns the number of 0->1 or 1->0 transitions in i */ 49 /* Returns the number of 0->1 or 1->0 transitions in i */
52 static int numTransitions(int i) 50 static int numTransitions(int i)
53 { 51 {
@@ -125,74 +123,6 @@ class LBPTransform : public UntrainableTransform @@ -125,74 +123,6 @@ class LBPTransform : public UntrainableTransform
125 123
126 BR_REGISTER(Transform, LBPTransform) 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 } // namespace br 126 } // namespace br
197 127
198 #include "lbp.moc" 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,48 +59,6 @@ class OpticalFlowTransform : public UntrainableMetaTransform
59 59
60 BR_REGISTER(Transform, OpticalFlowTransform) 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 } // namespace br 62 } // namespace br
105 63
106 #include "motion.moc" 64 #include "motion.moc"
openbr/plugins/plugins.cmake
@@ -12,8 +12,28 @@ foreach(DIR ${BR_THIRDPARTY_PLUGINS_DIR}) @@ -12,8 +12,28 @@ foreach(DIR ${BR_THIRDPARTY_PLUGINS_DIR})
12 set(BR_THIRDPARTY_PLUGINS ${BR_THIRDPARTY_PLUGINS} ${PLUGINS}) 12 set(BR_THIRDPARTY_PLUGINS ${BR_THIRDPARTY_PLUGINS} ${PLUGINS})
13 endforeach() 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 file(GLOB PLUGINS plugins/*.cpp plugins/*.h) 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 get_filename_component(PLUGIN_BASENAME ${PLUGIN} NAME_WE) 37 get_filename_component(PLUGIN_BASENAME ${PLUGIN} NAME_WE)
18 get_filename_component(PLUGIN_PATH ${PLUGIN} PATH) 38 get_filename_component(PLUGIN_PATH ${PLUGIN} PATH)
19 set(PLUGIN_CMAKE "${PLUGIN_PATH}/${PLUGIN_BASENAME}.cmake") 39 set(PLUGIN_CMAKE "${PLUGIN_PATH}/${PLUGIN_BASENAME}.cmake")
openbr/plugins/quantize.cpp
@@ -287,56 +287,6 @@ class ProductQuantizationDistance : public UntrainableDistance @@ -287,56 +287,6 @@ class ProductQuantizationDistance : public UntrainableDistance
287 BR_REGISTER(Distance, ProductQuantizationDistance) 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 * \ingroup transforms 290 * \ingroup transforms
341 * \brief Product quantization \cite jegou11 291 * \brief Product quantization \cite jegou11
342 * \author Josh Klontz \cite jklontz 292 * \author Josh Klontz \cite jklontz
openbr/plugins/random.cpp
@@ -96,38 +96,61 @@ BR_REGISTER(Transform, RndSubspaceTransform) @@ -96,38 +96,61 @@ BR_REGISTER(Transform, RndSubspaceTransform)
96 96
97 /*! 97 /*!
98 * \ingroup transforms 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 Q_OBJECT 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 RNG &rng = theRNG(); 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 void project(const Template &src, Template &dst) const 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 dst = src.m()(Rect(src.m().cols * x, 150 dst = src.m()(Rect(src.m().cols * x,
128 src.m().rows * y, 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,8 +374,12 @@ class RectFromPointsTransform : public UntrainableTransform
374 374
375 QList<QPointF> points; 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 if (src.file.points().size() > index) { 380 if (src.file.points().size() > index) {
  381 + if (src.file.points()[index].x() <= 0 ||
  382 + src.file.points()[index].y() <= 0) continue;
379 if (src.file.points()[index].x() < minX) minX = src.file.points()[index].x(); 383 if (src.file.points()[index].x() < minX) minX = src.file.points()[index].x();
380 if (src.file.points()[index].x() > maxX) maxX = src.file.points()[index].x(); 384 if (src.file.points()[index].x() > maxX) maxX = src.file.points()[index].x();
381 if (src.file.points()[index].y() < minY) minY = src.file.points()[index].y(); 385 if (src.file.points()[index].y() < minY) minY = src.file.points()[index].y();
@@ -390,8 +394,9 @@ class RectFromPointsTransform : public UntrainableTransform @@ -390,8 +394,9 @@ class RectFromPointsTransform : public UntrainableTransform
390 width += deltaWidth; 394 width += deltaWidth;
391 395
392 double height = maxY-minY; 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 const int x = std::max(0.0, minX - deltaWidth/2.0); 401 const int x = std::max(0.0, minX - deltaWidth/2.0);
397 const int y = std::max(0.0, minY - deltaHeight/2.0); 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 if(${BR_WITH_STASM4}) 3 if(${BR_WITH_STASM4})
4 find_package(Stasm4 REQUIRED) 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 namespace br 3 namespace br
4 { 4 {
@@ -56,33 +56,6 @@ private: @@ -56,33 +56,6 @@ private:
56 56
57 BR_REGISTER(Transform, AggregateFrames) 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 } // namespace br 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"