diff --git a/app/examples/face_recognition.cpp b/app/examples/face_recognition.cpp index 3da6a3f..d1d7cbc 100644 --- a/app/examples/face_recognition.cpp +++ b/app/examples/face_recognition.cpp @@ -30,10 +30,9 @@ static void printTemplate(const br::Template &t) { - printf("%s eyes: (%d, %d) (%d, %d)\n", - qPrintable(t.file.fileName()), - t.file.get("Affine_0_X"), t.file.get("Affine_0_Y"), - t.file.get("Affine_1_X"), t.file.get("Affine_1_Y")); + const QPoint firstEye = t.file.get("Affine_0"); + const QPoint secondEye = t.file.get("Affine_1"); + printf("%s eyes: (%d, %d) (%d, %d)\n", qPrintable(t.file.fileName()), firstEye.x(), firstEye.y(), secondEye.x(), secondEye.y()); } int main(int argc, char *argv[]) diff --git a/app/openbr-gui/templateviewer.cpp b/app/openbr-gui/templateviewer.cpp index e1cd18a..7c5b0af 100644 --- a/app/openbr-gui/templateviewer.cpp +++ b/app/openbr-gui/templateviewer.cpp @@ -39,10 +39,8 @@ void TemplateViewer::setFile(const File &file_) // Update landmarks landmarks.clear(); - if (file.contains("Affine_0_X") && file.contains("Affine_0_Y")) - landmarks.append(QPointF(file.get("Affine_0_X"), file.get("Affine_0_Y"))); - if (file.contains("Affine_1_X") && file.contains("Affine_1_Y")) - landmarks.append(QPointF(file.get("Affine_1_X"), file.get("Affine_1_Y"))); + if (file.contains("Affine_0")) landmarks.append(file.get("Affine_0")); + if (file.contains("Affine_1")) landmarks.append(file.get("Affine_1")); while (landmarks.size() < NumLandmarks) landmarks.append(QPointF()); nearestLandmark = -1; diff --git a/sdk/openbr_plugin.cpp b/sdk/openbr_plugin.cpp index 20b913f..d54f016 100644 --- a/sdk/openbr_plugin.cpp +++ b/sdk/openbr_plugin.cpp @@ -148,84 +148,72 @@ float File::label() const return ok ? val : -1; } -QList File::landmarks() const +QList File::namedPoints() const { QList landmarks; - foreach (const QVariant &landmark, value("Landmarks").toList()) - landmarks.append(landmark.toPointF()); - return landmarks; -} - -QList File::namedLandmarks() const -{ - QList landmarks; - QStringList keys = localMetadata().keys(); - foreach (const QString &key, keys) { - if (!key.endsWith("_X")) - continue; - QString keyBaseName = key.left(key.size()-2); - if (!keys.contains(keyBaseName+"_Y") || - keys.contains(keyBaseName+"_Width") || - keys.contains(keyBaseName+"_Height") || - keys.contains(keyBaseName+"_Radius")) - continue; - landmarks.append(QPointF(get(keyBaseName+"_X"), get(keyBaseName+"_Y"))); + foreach (const QString &key, localMetadata().keys()) { + const QVariant &variant = m_metadata[key]; + if (variant.canConvert()) + landmarks.append(variant.value()); } return landmarks; } -void File::appendLandmark(const QPointF &landmark) +QList File::points() const { - QList newLandmarks = m_metadata["Landmarks"].toList(); - newLandmarks.append(landmark); - m_metadata["Landmarks"] = newLandmarks; + QList points; + foreach (const QVariant &point, m_metadata["Points"].toList()) + points.append(point.toPointF()); + return points; } -void File::appendLandmarks(const QList &landmarks) +void File::appendPoint(const QPointF &point) { - QList newLandmarks = m_metadata["Landmarks"].toList(); - foreach (const QPointF &landmark, landmarks) - newLandmarks.append(landmark); - m_metadata["Landmarks"] = newLandmarks; + QList newPoints = m_metadata["Points"].toList(); + newPoints.append(point); + m_metadata["Points"] = newPoints; } -void File::setLandmarks(const QList &landmarks) +void File::appendPoints(const QList &points) { - QList landmarkList; landmarkList.reserve(landmarks.size()); - foreach (const QPointF &landmark, landmarks) - landmarkList.append(landmark); - m_metadata["Landmarks"] = landmarkList; + QList newPoints = m_metadata["Points"].toList(); + foreach (const QPointF &point, points) + newPoints.append(point); + m_metadata["Points"] = newPoints; } -QList File::ROIs() const +QList File::namedRects() const { - QList ROIs; - foreach (const QVariant &ROI, value("ROIs").toList()) - ROIs.append(ROI.toRect()); - return ROIs; + QList rects; + foreach (const QString &key, localMetadata().keys()) { + const QVariant &variant = m_metadata[key]; + if (variant.canConvert()) + rects.append(variant.value()); + } + return rects; } -void File::appendROI(const QRectF &ROI) +QList File::rects() const { - QList newROIs = m_metadata["ROIs"].toList(); - newROIs.append(ROI); - m_metadata["ROIs"] = newROIs; + QList rects; + foreach (const QVariant &rect, m_metadata["Rects"].toList()) + rects.append(rect.toRect()); + return rects; } -void File::appendROIs(const QList &ROIs) +void File::appendRect(const QRectF &rect) { - QList newROIs = m_metadata["ROIs"].toList(); - foreach (const QRectF &ROI, ROIs) - newROIs.append(ROI); - m_metadata["ROIs"] = newROIs; + QList newRects = m_metadata["Rects"].toList(); + newRects.append(rect); + m_metadata["Rects"] = newRects; } -void File::setROIs(const QList &ROIs) +void File::appendRects(const QList &rects) { - QList ROIList; ROIList.reserve(ROIs.size()); - foreach (const QRectF &ROI, ROIs) - ROIList.append(ROI); - m_metadata["ROIs"] = ROIList; + QList newRects = m_metadata["Rects"].toList(); + foreach (const QRectF &rect, rects) + newRects.append(rect); + m_metadata["Rects"] = newRects; } /* File - private methods */ diff --git a/sdk/openbr_plugin.h b/sdk/openbr_plugin.h index 67ec34d..89cdd24 100644 --- a/sdk/openbr_plugin.h +++ b/sdk/openbr_plugin.h @@ -128,8 +128,6 @@ void reset_##NAME() { NAME = DEFAULT; } * * Key | Value | Description * --- | ---- | ----------- - * path | QString | Resolve complete file paths from file names - * enrollAll | bool | Enroll zero or more templates per file * separator | QString | Seperate #name into multiple files * Index | int | Index of a template in a template list * Label | float | Classification/Regression class @@ -145,8 +143,8 @@ void reset_##NAME() { NAME = DEFAULT; } * Roll | float | Pose * Pitch | float | Pose * Yaw | float | Pose - * Landmarks | QList | Landmark list - * ROIs | QList | Region Of Interest (ROI) list + * Points | QList | List of unnamed points + * Rects | QList | List of unnamed rects * Age | QString | Age used for demographic filtering * _* | * | Reserved for internal use */ @@ -225,18 +223,19 @@ struct BR_EXPORT File inline void setLabel(float label) { set("Label", label); } /*!< \brief Convenience function for setting the file's \c Label. */ inline bool failed() const { return get("FTE", false) || get("FTO", false); } /*!< \brief Returns \c true if the file failed to open or enroll, \c false otherwise. */ - QList landmarks() const; /*!< \brief Returns the file's landmark list. */ - QList namedLandmarks() const; /*!< \brief Returns landmarks derived from metadata keys. */ - void appendLandmark(const QPointF &landmark); /*!< \brief Adds a landmark to the file's landmark list. */ - void appendLandmarks(const QList &landmarks); /*!< \brief Adds landmarks to the file's landmark list. */ - inline void clearLandmarks() { m_metadata["Landmarks"] = QList(); } /*!< \brief Clears the file's landmark list. */ - void setLandmarks(const QList &landmarks); /*!< \brief Assigns the file's landmark list. */ - - QList ROIs() const; /*!< \brief Returns the file's ROI list. */ - void appendROI(const QRectF &ROI); /*!< \brief Adds a ROI to the file's ROI list. */ - void appendROIs(const QList &ROIs); /*!< \brief Adds ROIs to the file's ROI list. */ - inline void clearROIs() { m_metadata["ROIs"] = QList(); } /*!< \brief Clears the file's landmark list. */ - void setROIs(const QList &ROIs); /*!< \brief Assigns the file's landmark list. */ + QList namedPoints() const; /*!< \brief Returns points convertible from metadata keys. */ + QList points() const; /*!< \brief Returns the file's points list. */ + void appendPoint(const QPointF &point); /*!< \brief Adds a point to the file's point list. */ + void appendPoints(const QList &points); /*!< \brief Adds landmarks to the file's landmark list. */ + inline void clearPoints() { m_metadata["Points"] = QList(); } /*!< \brief Clears the file's landmark list. */ + inline void setPoints(const QList &points) { clearPoints(); appendPoints(points); } /*!< \brief Overwrites the file's landmark list. */ + + QList namedRects() const; /*!< \brief Returns rects convertible from metadata values. */ + QList rects() const; /*!< \brief Returns the file's rects list. */ + void appendRect(const QRectF &rect); /*!< \brief Adds a rect to the file's rect list. */ + void appendRects(const QList &rects); /*!< \brief Adds rects to the file's rect list. */ + inline void clearRects() { m_metadata["Rects"] = QList(); } /*!< \brief Clears the file's rect list. */ + inline void setRects(const QList &rects) { clearRects(); appendRects(rects); } /*!< \brief Overwrites the file's rect list. */ private: QMap m_metadata; diff --git a/sdk/plugins/cascade.cpp b/sdk/plugins/cascade.cpp index 0097191..2e7cdcb 100644 --- a/sdk/plugins/cascade.cpp +++ b/sdk/plugins/cascade.cpp @@ -83,7 +83,7 @@ class CascadeTransform : public UntrainableTransform foreach (const Rect &rect, rects) { dst += src; - dst.file.appendROI(OpenCVUtils::fromRect(rect)); + dst.file.appendRect(OpenCVUtils::fromRect(rect)); } } }; diff --git a/sdk/plugins/crop.cpp b/sdk/plugins/crop.cpp index ca128aa..b881201 100644 --- a/sdk/plugins/crop.cpp +++ b/sdk/plugins/crop.cpp @@ -26,7 +26,7 @@ namespace br /*! * \ingroup transforms - * \brief Crops the regions of interest. + * \brief Crops the rectangular regions of interest. * \author Josh Klontz \cite jklontz */ class ROITransform : public UntrainableTransform @@ -35,8 +35,8 @@ class ROITransform : public UntrainableTransform void project(const Template &src, Template &dst) const { - foreach (const QRectF ROI, src.file.ROIs()) - dst += src.m()(OpenCVUtils::toRect(ROI)); + foreach (const QRectF &rect, src.file.rects()) + dst += src.m()(OpenCVUtils::toRect(rect)); } }; diff --git a/sdk/plugins/draw.cpp b/sdk/plugins/draw.cpp index 51e85ce..529b218 100644 --- a/sdk/plugins/draw.cpp +++ b/sdk/plugins/draw.cpp @@ -47,19 +47,19 @@ class DrawTransform : public UntrainableTransform const Scalar verboseColor(255, 255, 0); dst = src.m().clone(); - QList landmarks = OpenCVUtils::toPoints(src.file.landmarks()); + QList landmarks = OpenCVUtils::toPoints(src.file.points()); if (unnamed) { foreach (const Point2f &landmark, landmarks) circle(dst, landmark, 3, color, -1); } if (named) { - QList namedLandmarks = OpenCVUtils::toPoints(src.file.namedLandmarks()); + QList namedLandmarks = OpenCVUtils::toPoints(src.file.namedPoints()); foreach (const Point2f &landmark, namedLandmarks) circle(dst, landmark, 3, color); } if (ROI) { - QList ROIs = OpenCVUtils::toRects(src.file.ROIs()); + QList ROIs = OpenCVUtils::toRects(src.file.rects()); foreach (const Rect ROI, ROIs) rectangle(dst, ROI, color); } @@ -154,11 +154,11 @@ class EditTransform : public UntrainableTransform { (void) event; if (flags) { - QList ROIs = currentTemplate.file.ROIs(); - for (int i=ROIs.size()-1; i>=0; i--) - if (ROIs[i].contains(x,y)) - ROIs.removeAt(i); - currentTemplate.file.setROIs(ROIs); + QList rects = currentTemplate.file.rects(); + for (int i=rects.size()-1; i>=0; i--) + if (rects[i].contains(x,y)) + rects.removeAt(i); + currentTemplate.file.setRects(rects); } Template temp; diff --git a/sdk/plugins/eyes.cpp b/sdk/plugins/eyes.cpp index bd604b0..20f67ed 100644 --- a/sdk/plugins/eyes.cpp +++ b/sdk/plugins/eyes.cpp @@ -147,7 +147,7 @@ public: private: void project(const Template &src, Template &dst) const { - Rect roi = OpenCVUtils::toRect(src.file.ROIs().first()); + Rect roi = OpenCVUtils::toRect(src.file.rects().first()); Mat gray; OpenCVUtils::cvtGray(src.m()(roi), gray); @@ -183,12 +183,10 @@ private: float second_eye_y = (right_rect.y + maxLoc.y)*gray.rows/height+roi.y; dst = src; - dst.file.appendLandmark(QPointF(first_eye_x, first_eye_y)); - dst.file.appendLandmark(QPointF(second_eye_x, second_eye_y)); - dst.file.set("ASEF_Right_Eye_X", first_eye_x); - dst.file.set("ASEF_Right_Eye_Y", first_eye_y); - dst.file.set("ASEF_Left_Eye_X", second_eye_x); - dst.file.set("ASEF_Left_Eye_Y", second_eye_y); + dst.file.appendPoint(QPointF(first_eye_x, first_eye_y)); + dst.file.appendPoint(QPointF(second_eye_x, second_eye_y)); + dst.file.set("ASEF_Right_Eye", QPointF(first_eye_x, first_eye_y)); + dst.file.set("ASEF_Left_Eye", QPointF(second_eye_x, second_eye_y)); } }; diff --git a/sdk/plugins/hist.cpp b/sdk/plugins/hist.cpp index 3829d7f..39d0b44 100644 --- a/sdk/plugins/hist.cpp +++ b/sdk/plugins/hist.cpp @@ -174,7 +174,7 @@ class VarianceChangeDetectorTransform : public UntrainableTransform int *buffer = new int[bins]; float bestRatio = -std::numeric_limits::max(); - QRect bestROI; + QRectF bestRect; const int rows = m.rows; const int cols = m.cols/bins; @@ -202,7 +202,7 @@ class VarianceChangeDetectorTransform : public UntrainableTransform if (ratio > bestRatio) { bestRatio = ratio; - bestROI = QRect(j*radius, i*radius, scale*radius, scale*radius); + bestRect = QRect(j*radius, i*radius, scale*radius, scale*radius); } } } @@ -210,7 +210,7 @@ class VarianceChangeDetectorTransform : public UntrainableTransform } delete[] buffer; - dst.file.appendROI(bestROI); + dst.file.appendRect(bestRect); dst.file.setLabel(bestRatio); } }; diff --git a/sdk/plugins/keypoint.cpp b/sdk/plugins/keypoint.cpp index ac5c54e..4adcfcd 100644 --- a/sdk/plugins/keypoint.cpp +++ b/sdk/plugins/keypoint.cpp @@ -57,10 +57,10 @@ class KeyPointDetectorTransform : public UntrainableTransform dst.file.set("FTE", true); } - QList ROIs; + QList rects; foreach (const KeyPoint &keyPoint, keyPoints) - ROIs.append(Rect(keyPoint.pt.x, keyPoint.pt.y, keyPoint.size, keyPoint.size)); - dst.file.setROIs(OpenCVUtils::fromRects(ROIs)); + rects.append(Rect(keyPoint.pt.x, keyPoint.pt.y, keyPoint.size, keyPoint.size)); + dst.file.setRects(OpenCVUtils::fromRects(rects)); } }; @@ -92,10 +92,10 @@ class KeyPointDescriptorTransform : public UntrainableTransform { std::vector keyPoints; if (size == -1) { - foreach (const QRectF &ROI, src.file.ROIs()) + foreach (const QRectF &ROI, src.file.rects()) keyPoints.push_back(KeyPoint(ROI.x(), ROI.y(), (ROI.width() + ROI.height())/2)); } else { - foreach (const QPointF &landmark, src.file.landmarks()) + foreach (const QPointF &landmark, src.file.points()) keyPoints.push_back(KeyPoint(landmark.x(), landmark.y(), size)); } descriptorExtractor->compute(src, keyPoints, dst); @@ -166,7 +166,7 @@ class SIFTDescriptorTransform : public UntrainableTransform void project(const Template &src, Template &dst) const { std::vector keyPoints; - foreach (const QPointF &val, src.file.landmarks()) + foreach (const QPointF &val, src.file.points()) keyPoints.push_back(KeyPoint(val.x(), val.y(), size)); Mat m; @@ -200,7 +200,7 @@ class GridTransform : public UntrainableTransform for (float j=column_step/2; j("FTE", false); - QList landmarks = t.file.landmarks(); - QList ROIs = t.file.ROIs(); - if (landmarks.size() % t.size() != 0) qFatal("Uneven landmark count."); - if (ROIs.size() % t.size() != 0) qFatal("Uneven ROI count."); - const int landmarkStep = landmarks.size() / t.size(); - const int ROIStep = ROIs.size() / t.size(); + QList points = t.file.points(); + QList rects = t.file.rects(); + if (points.size() % t.size() != 0) qFatal("Uneven point count."); + if (rects.size() % t.size() != 0) qFatal("Uneven rect count."); + const int pointStep = points.size() / t.size(); + const int rectStep = rects.size() / t.size(); for (int i=0; i("enrollAll", false)) { expanded.append(Template(t.file, t[i])); - expanded.last().file.setROIs(ROIs.mid(i*ROIStep, ROIStep)); - expanded.last().file.setLandmarks(landmarks.mid(i*landmarkStep, landmarkStep)); + expanded.last().file.setRects(rects.mid(i*rectStep, rectStep)); + expanded.last().file.setPoints(points.mid(i*pointStep, pointStep)); } } } diff --git a/sdk/plugins/random.cpp b/sdk/plugins/random.cpp index a8b4d93..827fd77 100644 --- a/sdk/plugins/random.cpp +++ b/sdk/plugins/random.cpp @@ -155,7 +155,7 @@ class RndPointTransform : public Transform void project(const Template &src, Template &dst) const { dst = src; - dst.file.appendLandmark(QPointF(src.m().cols * x, src.m().rows * y)); + dst.file.appendPoint(QPointF(src.m().cols * x, src.m().rows * y)); } }; diff --git a/sdk/plugins/regions.cpp b/sdk/plugins/regions.cpp index 7f9aeb1..7f13a9e 100644 --- a/sdk/plugins/regions.cpp +++ b/sdk/plugins/regions.cpp @@ -148,7 +148,7 @@ class RectFromLandmarksTransform : public UntrainableTransform void project(const Template &src, Template &dst) const { - if (src.file.landmarks().isEmpty()) { + if (src.file.points().isEmpty()) { qWarning("No landmarks"); dst = src; return; @@ -160,12 +160,12 @@ class RectFromLandmarksTransform : public UntrainableTransform maxX = maxY = -std::numeric_limits::max(); foreach(int index, indices) { - if (src.file.landmarks().size() > index+1) { - if (src.file.landmarks()[index].x() < minX) minX = src.file.landmarks()[index].x(); - if (src.file.landmarks()[index].x() > maxX) maxX = src.file.landmarks()[index].x(); - if (src.file.landmarks()[index].y() < minY) minY = src.file.landmarks()[index].y(); - if (src.file.landmarks()[index].y() > maxY) maxY = src.file.landmarks()[index].y(); - dst.file.appendLandmark(src.file.landmarks()[index]); + if (src.file.points().size() > index+1) { + if (src.file.points()[index].x() < minX) minX = src.file.points()[index].x(); + if (src.file.points()[index].x() > maxX) maxX = src.file.points()[index].x(); + if (src.file.points()[index].y() < minY) minY = src.file.points()[index].y(); + if (src.file.points()[index].y() > maxY) maxY = src.file.points()[index].y(); + dst.file.appendPoint(src.file.points()[index]); } } diff --git a/sdk/plugins/register.cpp b/sdk/plugins/register.cpp index bd96176..d6e0355 100644 --- a/sdk/plugins/register.cpp +++ b/sdk/plugins/register.cpp @@ -67,17 +67,14 @@ class AffineTransform : public UntrainableTransform else dstPoints[2] = Point2f(x3*width, y3*height); Point2f srcPoints[3]; - if (src.file.contains("Affine_0_X") && - src.file.contains("Affine_0_Y") && - src.file.contains("Affine_1_X") && - src.file.contains("Affine_1_Y") && - (src.file.contains("Affine_2_X") || twoPoints) && - (src.file.contains("Affine_2_Y") || twoPoints)) { - srcPoints[0] = Point2f(src.file.get("Affine_0_X"), src.file.get("Affine_0_Y")); - srcPoints[1] = Point2f(src.file.get("Affine_1_X"), src.file.get("Affine_1_Y")); - if (!twoPoints) srcPoints[2] = Point2f(src.file.get("Affine_2_X"), src.file.get("Affine_2_Y")); + if (src.file.contains("Affine_0") && + src.file.contains("Affine_1") && + (src.file.contains("Affine_2") || twoPoints)) { + srcPoints[0] = OpenCVUtils::toPoint(src.file.get("Affine_0")); + srcPoints[1] = OpenCVUtils::toPoint(src.file.get("Affine_1")); + if (!twoPoints) srcPoints[2] = OpenCVUtils::toPoint(src.file.get("Affine_2")); } else { - const QList landmarks = OpenCVUtils::toPoints(src.file.landmarks()); + const QList landmarks = OpenCVUtils::toPoints(src.file.points()); if ((landmarks.size() < 2) || (!twoPoints && (landmarks.size() < 3))) { resize(src, dst, Size(width, height)); @@ -87,14 +84,9 @@ class AffineTransform : public UntrainableTransform srcPoints[1] = landmarks[1]; if (!twoPoints) srcPoints[2] = landmarks[2]; - dst.file.set("Affine_0_X", landmarks[0].x); - dst.file.set("Affine_0_Y", landmarks[0].y); - dst.file.set("Affine_1_X", landmarks[1].x); - dst.file.set("Affine_1_Y", landmarks[1].y); - if (!twoPoints) { - dst.file.set("Affine_2_X", landmarks[2].x); - dst.file.set("Affine_2_Y", landmarks[2].y); - } + dst.file.set("Affine_0", OpenCVUtils::fromPoint(landmarks[0])); + dst.file.set("Affine_1", OpenCVUtils::fromPoint(landmarks[1])); + if (!twoPoints) dst.file.set("Affine_2", OpenCVUtils::fromPoint(landmarks[2])); } } if (twoPoints) srcPoints[2] = getThirdAffinePoint(srcPoints[0], srcPoints[1]); diff --git a/sdk/plugins/wavelet.cpp b/sdk/plugins/wavelet.cpp index f1d924a..a5ac86c 100644 --- a/sdk/plugins/wavelet.cpp +++ b/sdk/plugins/wavelet.cpp @@ -189,11 +189,11 @@ class GaborJetTransform : public UntrainableTransform void project(const Template &src, Template &dst) const { - const QList landmarks = src.file.landmarks(); - dst = Mat(landmarks.size(), kReals.size(), CV_32FC1); - for (int i=0; i points = src.file.points(); + dst = Mat(points.size(), kReals.size(), CV_32FC1); + for (int i=0; i(i,j) = response(src, landmarks[i], kReals[j], kImaginaries[j], component); + dst.m().at(i,j) = response(src, points[i], kReals[j], kImaginaries[j], component); } };