Commit 9009392052d4b56b328c8003f2eae1314b6a1cc8
Merge branch 'master' of https://github.com/biometrics/openbr
Showing
5 changed files
with
89 additions
and
35 deletions
openbr/plugins/cluster.cpp
| @@ -14,9 +14,9 @@ | @@ -14,9 +14,9 @@ | ||
| 14 | * limitations under the License. * | 14 | * limitations under the License. * |
| 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
| 16 | 16 | ||
| 17 | -#include "openbr_internal.h" | ||
| 18 | #include <opencv2/flann/flann.hpp> | 17 | #include <opencv2/flann/flann.hpp> |
| 19 | 18 | ||
| 19 | +#include "openbr_internal.h" | ||
| 20 | #include "openbr/core/opencvutils.h" | 20 | #include "openbr/core/opencvutils.h" |
| 21 | 21 | ||
| 22 | using namespace cv; | 22 | using namespace cv; |
| @@ -26,39 +26,40 @@ namespace br | @@ -26,39 +26,40 @@ namespace br | ||
| 26 | 26 | ||
| 27 | /*! | 27 | /*! |
| 28 | * \ingroup transforms | 28 | * \ingroup transforms |
| 29 | - * \brief Wraps OpenCV kmeans | 29 | + * \brief Wraps OpenCV kmeans and flann. |
| 30 | * \author Josh Klontz \cite jklontz | 30 | * \author Josh Klontz \cite jklontz |
| 31 | */ | 31 | */ |
| 32 | class KMeansTransform : public Transform | 32 | class KMeansTransform : public Transform |
| 33 | { | 33 | { |
| 34 | Q_OBJECT | 34 | Q_OBJECT |
| 35 | - Q_PROPERTY(int k READ get_k WRITE set_k RESET reset_k) | ||
| 36 | - BR_PROPERTY(int, k, 1) | 35 | + Q_PROPERTY(int kTrain READ get_kTrain WRITE set_kTrain RESET reset_kTrain STORED false) |
| 36 | + Q_PROPERTY(int kSearch READ get_kSearch WRITE set_kSearch RESET reset_kSearch STORED false) | ||
| 37 | + BR_PROPERTY(int, kTrain, 256) | ||
| 38 | + BR_PROPERTY(int, kSearch, 1) | ||
| 37 | 39 | ||
| 38 | Mat centers; | 40 | Mat centers; |
| 39 | - QSharedPointer<flann::Index> index; | ||
| 40 | - QSharedPointer<QMutex> indexLock; | 41 | + mutable QScopedPointer<flann::Index> index; |
| 42 | + mutable QMutex mutex; | ||
| 41 | 43 | ||
| 42 | void reindex() | 44 | void reindex() |
| 43 | { | 45 | { |
| 44 | - index = QSharedPointer<flann::Index>(new flann::Index(centers, flann::LinearIndexParams())); | ||
| 45 | - indexLock = QSharedPointer<QMutex>(new QMutex()); | 46 | + index.reset(new flann::Index(centers, flann::LinearIndexParams())); |
| 46 | } | 47 | } |
| 47 | 48 | ||
| 48 | void train(const TemplateList &data) | 49 | void train(const TemplateList &data) |
| 49 | { | 50 | { |
| 50 | Mat bestLabels; | 51 | Mat bestLabels; |
| 51 | - const double compactness = kmeans(OpenCVUtils::toMatByRow(data.data()), k, bestLabels, TermCriteria(TermCriteria::MAX_ITER, 10, 0), 3, KMEANS_PP_CENTERS, centers); | ||
| 52 | - reindex(); | 52 | + const double compactness = kmeans(OpenCVUtils::toMatByRow(data.data()), kTrain, bestLabels, TermCriteria(TermCriteria::MAX_ITER, 10, 0), 3, KMEANS_PP_CENTERS, centers); |
| 53 | qDebug("KMeans compactness = %f", compactness); | 53 | qDebug("KMeans compactness = %f", compactness); |
| 54 | + reindex(); | ||
| 54 | } | 55 | } |
| 55 | 56 | ||
| 56 | void project(const Template &src, Template &dst) const | 57 | void project(const Template &src, Template &dst) const |
| 57 | { | 58 | { |
| 58 | - Mat dists; | ||
| 59 | - indexLock->lock(); | ||
| 60 | - index->knnSearch(src, dst, dists, 1); | ||
| 61 | - indexLock->unlock(); | 59 | + QMutexLocker locker(&mutex); |
| 60 | + Mat dists, indicies; | ||
| 61 | + index->knnSearch(src, indicies, dists, kSearch); | ||
| 62 | + dst = indicies.reshape(1, 1); | ||
| 62 | } | 63 | } |
| 63 | 64 | ||
| 64 | void load(QDataStream &stream) | 65 | void load(QDataStream &stream) |
openbr/plugins/draw.cpp
| @@ -31,11 +31,9 @@ namespace br | @@ -31,11 +31,9 @@ namespace br | ||
| 31 | class DrawTransform : public UntrainableTransform | 31 | class DrawTransform : public UntrainableTransform |
| 32 | { | 32 | { |
| 33 | Q_OBJECT | 33 | Q_OBJECT |
| 34 | - Q_PROPERTY(bool named READ get_named WRITE set_named RESET reset_named STORED false) | ||
| 35 | Q_PROPERTY(bool verbose READ get_verbose WRITE set_verbose RESET reset_verbose STORED false) | 34 | Q_PROPERTY(bool verbose READ get_verbose WRITE set_verbose RESET reset_verbose STORED false) |
| 36 | Q_PROPERTY(bool points READ get_points WRITE set_points RESET reset_points STORED false) | 35 | Q_PROPERTY(bool points READ get_points WRITE set_points RESET reset_points STORED false) |
| 37 | Q_PROPERTY(bool rects READ get_rects WRITE set_rects RESET reset_rects STORED false) | 36 | Q_PROPERTY(bool rects READ get_rects WRITE set_rects RESET reset_rects STORED false) |
| 38 | - BR_PROPERTY(bool, named, true) | ||
| 39 | BR_PROPERTY(bool, verbose, false) | 37 | BR_PROPERTY(bool, verbose, false) |
| 40 | BR_PROPERTY(bool, points, true) | 38 | BR_PROPERTY(bool, points, true) |
| 41 | BR_PROPERTY(bool, rects, true) | 39 | BR_PROPERTY(bool, rects, true) |
| @@ -47,7 +45,7 @@ class DrawTransform : public UntrainableTransform | @@ -47,7 +45,7 @@ class DrawTransform : public UntrainableTransform | ||
| 47 | dst = src.m().clone(); | 45 | dst = src.m().clone(); |
| 48 | 46 | ||
| 49 | if (points) { | 47 | if (points) { |
| 50 | - const QList<Point2f> pointsList = OpenCVUtils::toPoints(named ? src.file.namedPoints() : src.file.points()); | 48 | + const QList<Point2f> pointsList = OpenCVUtils::toPoints(src.file.namedPoints() + src.file.points()); |
| 51 | for (int i=0; i<pointsList.size(); i++) { | 49 | for (int i=0; i<pointsList.size(); i++) { |
| 52 | const Point2f &point = pointsList[i]; | 50 | const Point2f &point = pointsList[i]; |
| 53 | circle(dst, point, 3, color, -1); | 51 | circle(dst, point, 3, color, -1); |
| @@ -55,7 +53,7 @@ class DrawTransform : public UntrainableTransform | @@ -55,7 +53,7 @@ class DrawTransform : public UntrainableTransform | ||
| 55 | } | 53 | } |
| 56 | } | 54 | } |
| 57 | if (rects) { | 55 | if (rects) { |
| 58 | - foreach (const Rect &rect, OpenCVUtils::toRects(named ? src.file.namedRects() : src.file.rects())) | 56 | + foreach (const Rect &rect, OpenCVUtils::toRects(src.file.namedRects() + src.file.rects())) |
| 59 | rectangle(dst, rect, color); | 57 | rectangle(dst, rect, color); |
| 60 | } | 58 | } |
| 61 | } | 59 | } |
openbr/plugins/gallery.cpp
| @@ -36,6 +36,50 @@ namespace br | @@ -36,6 +36,50 @@ namespace br | ||
| 36 | 36 | ||
| 37 | /*! | 37 | /*! |
| 38 | * \ingroup galleries | 38 | * \ingroup galleries |
| 39 | + * \brief Weka ARFF file format. | ||
| 40 | + * \author Josh Klontz \cite jklontz | ||
| 41 | + */ | ||
| 42 | +class arffGallery : public Gallery | ||
| 43 | +{ | ||
| 44 | + Q_OBJECT | ||
| 45 | + QFile arffFile; | ||
| 46 | + | ||
| 47 | + TemplateList readBlock(bool *done) | ||
| 48 | + { | ||
| 49 | + (void) done; | ||
| 50 | + qFatal("Not implemented."); | ||
| 51 | + return TemplateList(); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + void write(const Template &t) | ||
| 55 | + { | ||
| 56 | + if (!arffFile.isOpen()) { | ||
| 57 | + arffFile.setFileName(file.name); | ||
| 58 | + arffFile.open(QFile::WriteOnly); | ||
| 59 | + arffFile.write("% OpenBR templates\n" | ||
| 60 | + "@RELATION OpenBR\n" | ||
| 61 | + "\n"); | ||
| 62 | + | ||
| 63 | + arffFile.write("@ATTRIBUTE filename STRING\n"); | ||
| 64 | + arffFile.write(qPrintable("@ATTRIBUTE class {" + QStringList(Globals->classes.keys()).join(',') + "}\n")); | ||
| 65 | + | ||
| 66 | + const int dimensions = t.m().rows * t.m().cols; | ||
| 67 | + for (int i=0; i<dimensions; i++) | ||
| 68 | + arffFile.write(qPrintable("@ATTRIBUTE v" + QString::number(i) + " NUMERIC\n")); | ||
| 69 | + | ||
| 70 | + arffFile.write("\n@DATA\n"); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + arffFile.write(qPrintable("'" + t.file.name + "',")); | ||
| 74 | + arffFile.write(qPrintable("'" + t.file.subject() + "',")); | ||
| 75 | + arffFile.write(qPrintable(OpenCVUtils::matrixToStringList(t).join(',')+"\n")); | ||
| 76 | + } | ||
| 77 | +}; | ||
| 78 | + | ||
| 79 | +BR_REGISTER(Gallery, arffGallery) | ||
| 80 | + | ||
| 81 | +/*! | ||
| 82 | + * \ingroup galleries | ||
| 39 | * \brief A binary gallery. | 83 | * \brief A binary gallery. |
| 40 | * \author Josh Klontz \cite jklontz | 84 | * \author Josh Klontz \cite jklontz |
| 41 | */ | 85 | */ |
| @@ -395,12 +439,19 @@ class csvGallery : public Gallery | @@ -395,12 +439,19 @@ class csvGallery : public Gallery | ||
| 395 | if (!file.exists()) return templates; | 439 | if (!file.exists()) return templates; |
| 396 | 440 | ||
| 397 | QStringList lines = QtUtils::readLines(file); | 441 | QStringList lines = QtUtils::readLines(file); |
| 398 | - if (!lines.isEmpty()) lines.removeFirst(); // Remove header | 442 | + QRegExp regexp("\\s*,\\s*"); |
| 443 | + QStringList headers; | ||
| 444 | + if (!lines.isEmpty()) headers = lines.takeFirst().split(regexp); | ||
| 399 | 445 | ||
| 400 | foreach (const QString &line, lines) { | 446 | foreach (const QString &line, lines) { |
| 401 | - QStringList words = line.split(','); | ||
| 402 | - if (words.isEmpty()) continue; | ||
| 403 | - templates.append(File(words[fileIndex], words.size() > 1 ? words.takeLast() : "")); | 447 | + QStringList words = line.split(regexp); |
| 448 | + if (words.size() != headers.size()) continue; | ||
| 449 | + File f; | ||
| 450 | + for (int i=0; i<words.size(); i++) { | ||
| 451 | + if (i == 0) f.name = words[i]; | ||
| 452 | + else f.set(headers[i], words[i]); | ||
| 453 | + } | ||
| 454 | + templates.append(f); | ||
| 404 | } | 455 | } |
| 405 | 456 | ||
| 406 | return templates; | 457 | return templates; |
| @@ -413,7 +464,11 @@ class csvGallery : public Gallery | @@ -413,7 +464,11 @@ class csvGallery : public Gallery | ||
| 413 | 464 | ||
| 414 | static QString getCSVElement(const QString &key, const QVariant &value, bool header) | 465 | static QString getCSVElement(const QString &key, const QVariant &value, bool header) |
| 415 | { | 466 | { |
| 416 | - if (value.canConvert<QString>()) { | 467 | + if ((key == "Label") && !header) { |
| 468 | + QString stringLabel = Globals->classes.key(value.value<int>()); | ||
| 469 | + if (stringLabel.isEmpty()) return value.value<QString>(); | ||
| 470 | + else return stringLabel; | ||
| 471 | + } else if (value.canConvert<QString>()) { | ||
| 417 | if (header) return key; | 472 | if (header) return key; |
| 418 | else return value.value<QString>(); | 473 | else return value.value<QString>(); |
| 419 | } else if (value.canConvert<QPointF>()) { | 474 | } else if (value.canConvert<QPointF>()) { |
openbr/plugins/keypoint.cpp
| @@ -58,7 +58,7 @@ class KeyPointDetectorTransform : public UntrainableTransform | @@ -58,7 +58,7 @@ class KeyPointDetectorTransform : public UntrainableTransform | ||
| 58 | 58 | ||
| 59 | QList<Rect> rects; | 59 | QList<Rect> rects; |
| 60 | foreach (const KeyPoint &keyPoint, keyPoints) | 60 | foreach (const KeyPoint &keyPoint, keyPoints) |
| 61 | - rects.append(Rect(keyPoint.pt.x, keyPoint.pt.y, keyPoint.size, keyPoint.size)); | 61 | + rects.append(Rect(keyPoint.pt.x-keyPoint.size/2, keyPoint.pt.y-keyPoint.size/2, keyPoint.size, keyPoint.size)); |
| 62 | dst.file.setRects(OpenCVUtils::fromRects(rects)); | 62 | dst.file.setRects(OpenCVUtils::fromRects(rects)); |
| 63 | } | 63 | } |
| 64 | }; | 64 | }; |
| @@ -90,13 +90,12 @@ class KeyPointDescriptorTransform : public UntrainableTransform | @@ -90,13 +90,12 @@ class KeyPointDescriptorTransform : public UntrainableTransform | ||
| 90 | void project(const Template &src, Template &dst) const | 90 | void project(const Template &src, Template &dst) const |
| 91 | { | 91 | { |
| 92 | std::vector<KeyPoint> keyPoints; | 92 | std::vector<KeyPoint> keyPoints; |
| 93 | - if (size == -1) { | 93 | + if (size == -1) |
| 94 | foreach (const QRectF &ROI, src.file.rects()) | 94 | foreach (const QRectF &ROI, src.file.rects()) |
| 95 | - keyPoints.push_back(KeyPoint(ROI.x(), ROI.y(), (ROI.width() + ROI.height())/2)); | ||
| 96 | - } else { | 95 | + keyPoints.push_back(KeyPoint(ROI.x()+ROI.width()/2, ROI.y()+ROI.height()/2, (ROI.width() + ROI.height())/2)); |
| 96 | + else | ||
| 97 | foreach (const QPointF &landmark, src.file.points()) | 97 | foreach (const QPointF &landmark, src.file.points()) |
| 98 | keyPoints.push_back(KeyPoint(landmark.x(), landmark.y(), size)); | 98 | keyPoints.push_back(KeyPoint(landmark.x(), landmark.y(), size)); |
| 99 | - } | ||
| 100 | descriptorExtractor->compute(src, keyPoints, dst); | 99 | descriptorExtractor->compute(src, keyPoints, dst); |
| 101 | } | 100 | } |
| 102 | }; | 101 | }; |
openbr/plugins/svm.cpp
| @@ -75,14 +75,15 @@ private: | @@ -75,14 +75,15 @@ private: | ||
| 75 | cv::Mat data = OpenCVUtils::toMat(_data.data()); | 75 | cv::Mat data = OpenCVUtils::toMat(_data.data()); |
| 76 | cv::Mat lab = OpenCVUtils::toMat(_data.labels<float>()); | 76 | cv::Mat lab = OpenCVUtils::toMat(_data.labels<float>()); |
| 77 | 77 | ||
| 78 | - // Scale labels to [-1,1] | ||
| 79 | - double min, max; | ||
| 80 | - cv::minMaxLoc(lab, &min, &max); | ||
| 81 | - if (max > min) { | ||
| 82 | - a = 2.0/(max-min); | ||
| 83 | - b = -(min*a+1); | ||
| 84 | - lab = (lab * a) + b; | 78 | + if ((type == EPS_SVR) || (type == NU_SVR)) { |
| 79 | + // Scale labels to [-1,1] | ||
| 80 | + double min, max; | ||
| 85 | cv::minMaxLoc(lab, &min, &max); | 81 | cv::minMaxLoc(lab, &min, &max); |
| 82 | + if (max > min) { | ||
| 83 | + a = 2.0/(max-min); | ||
| 84 | + b = -(min*a+1); | ||
| 85 | + lab = (lab * a) + b; | ||
| 86 | + } | ||
| 86 | } | 87 | } |
| 87 | 88 | ||
| 88 | if (data.type() != CV_32FC1) | 89 | if (data.type() != CV_32FC1) |