Commit b34029cc89b22994e6464b16479488ee7a775525

Authored by Jordan Cheney
1 parent f645840e

Incremental progress for plugins reorg

Showing 113 changed files with 5111 additions and 4674 deletions

Too many changes.

To preserve performance only 100 of 113 files are displayed.

openbr/plugins/ebif.cpp renamed to openbr/plugins/classification/ebif.cpp
1 #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"