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 | 14 | * limitations under the License. * |
| 15 | 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
| 16 | 16 | |
| 17 | -#include "openbr_internal.h" | |
| 18 | 17 | #include <opencv2/flann/flann.hpp> |
| 19 | 18 | |
| 19 | +#include "openbr_internal.h" | |
| 20 | 20 | #include "openbr/core/opencvutils.h" |
| 21 | 21 | |
| 22 | 22 | using namespace cv; |
| ... | ... | @@ -26,39 +26,40 @@ namespace br |
| 26 | 26 | |
| 27 | 27 | /*! |
| 28 | 28 | * \ingroup transforms |
| 29 | - * \brief Wraps OpenCV kmeans | |
| 29 | + * \brief Wraps OpenCV kmeans and flann. | |
| 30 | 30 | * \author Josh Klontz \cite jklontz |
| 31 | 31 | */ |
| 32 | 32 | class KMeansTransform : public Transform |
| 33 | 33 | { |
| 34 | 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 | 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 | 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 | 49 | void train(const TemplateList &data) |
| 49 | 50 | { |
| 50 | 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 | 53 | qDebug("KMeans compactness = %f", compactness); |
| 54 | + reindex(); | |
| 54 | 55 | } |
| 55 | 56 | |
| 56 | 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 | 65 | void load(QDataStream &stream) | ... | ... |
openbr/plugins/draw.cpp
| ... | ... | @@ -31,11 +31,9 @@ namespace br |
| 31 | 31 | class DrawTransform : public UntrainableTransform |
| 32 | 32 | { |
| 33 | 33 | Q_OBJECT |
| 34 | - Q_PROPERTY(bool named READ get_named WRITE set_named RESET reset_named STORED false) | |
| 35 | 34 | Q_PROPERTY(bool verbose READ get_verbose WRITE set_verbose RESET reset_verbose STORED false) |
| 36 | 35 | Q_PROPERTY(bool points READ get_points WRITE set_points RESET reset_points STORED false) |
| 37 | 36 | Q_PROPERTY(bool rects READ get_rects WRITE set_rects RESET reset_rects STORED false) |
| 38 | - BR_PROPERTY(bool, named, true) | |
| 39 | 37 | BR_PROPERTY(bool, verbose, false) |
| 40 | 38 | BR_PROPERTY(bool, points, true) |
| 41 | 39 | BR_PROPERTY(bool, rects, true) |
| ... | ... | @@ -47,7 +45,7 @@ class DrawTransform : public UntrainableTransform |
| 47 | 45 | dst = src.m().clone(); |
| 48 | 46 | |
| 49 | 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 | 49 | for (int i=0; i<pointsList.size(); i++) { |
| 52 | 50 | const Point2f &point = pointsList[i]; |
| 53 | 51 | circle(dst, point, 3, color, -1); |
| ... | ... | @@ -55,7 +53,7 @@ class DrawTransform : public UntrainableTransform |
| 55 | 53 | } |
| 56 | 54 | } |
| 57 | 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 | 57 | rectangle(dst, rect, color); |
| 60 | 58 | } |
| 61 | 59 | } | ... | ... |
openbr/plugins/gallery.cpp
| ... | ... | @@ -36,6 +36,50 @@ namespace br |
| 36 | 36 | |
| 37 | 37 | /*! |
| 38 | 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 | 83 | * \brief A binary gallery. |
| 40 | 84 | * \author Josh Klontz \cite jklontz |
| 41 | 85 | */ |
| ... | ... | @@ -395,12 +439,19 @@ class csvGallery : public Gallery |
| 395 | 439 | if (!file.exists()) return templates; |
| 396 | 440 | |
| 397 | 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 | 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 | 457 | return templates; |
| ... | ... | @@ -413,7 +464,11 @@ class csvGallery : public Gallery |
| 413 | 464 | |
| 414 | 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 | 472 | if (header) return key; |
| 418 | 473 | else return value.value<QString>(); |
| 419 | 474 | } else if (value.canConvert<QPointF>()) { | ... | ... |
openbr/plugins/keypoint.cpp
| ... | ... | @@ -58,7 +58,7 @@ class KeyPointDetectorTransform : public UntrainableTransform |
| 58 | 58 | |
| 59 | 59 | QList<Rect> rects; |
| 60 | 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 | 62 | dst.file.setRects(OpenCVUtils::fromRects(rects)); |
| 63 | 63 | } |
| 64 | 64 | }; |
| ... | ... | @@ -90,13 +90,12 @@ class KeyPointDescriptorTransform : public UntrainableTransform |
| 90 | 90 | void project(const Template &src, Template &dst) const |
| 91 | 91 | { |
| 92 | 92 | std::vector<KeyPoint> keyPoints; |
| 93 | - if (size == -1) { | |
| 93 | + if (size == -1) | |
| 94 | 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 | 97 | foreach (const QPointF &landmark, src.file.points()) |
| 98 | 98 | keyPoints.push_back(KeyPoint(landmark.x(), landmark.y(), size)); |
| 99 | - } | |
| 100 | 99 | descriptorExtractor->compute(src, keyPoints, dst); |
| 101 | 100 | } |
| 102 | 101 | }; | ... | ... |
openbr/plugins/svm.cpp
| ... | ... | @@ -75,14 +75,15 @@ private: |
| 75 | 75 | cv::Mat data = OpenCVUtils::toMat(_data.data()); |
| 76 | 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 | 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 | 89 | if (data.type() != CV_32FC1) | ... | ... |