diff --git a/openbr/openbr_plugin.cpp b/openbr/openbr_plugin.cpp index 533c5f3..15d6cdd 100644 --- a/openbr/openbr_plugin.cpp +++ b/openbr/openbr_plugin.cpp @@ -626,7 +626,11 @@ QStringList Object::prunedArguments(bool expanded) const if (className.endsWith(interfaceName)) className.chop(interfaceName.size()); - if (interfaceName == "Distance") + if (interfaceName == "Representation") + shellObject.reset(Factory::make(className)); + else if (interfaceName == "Classifier") + shellObject.reset(Factory::make(className)); + else if (interfaceName == "Distance") shellObject.reset(Factory::make(className)); else if (interfaceName == "Transform") shellObject.reset(Factory::make(className)); @@ -673,6 +677,12 @@ QString Object::argument(int index, bool expanded) const } else if (type == "QList") { foreach (Distance *distance, variant.value< QList >()) strings.append(distance->description(expanded)); + } else if (type == "QList") { + foreach (Representation *representation, variant.value< QList >()) + strings.append(representation->description(expanded)); + } else if (type == "QList") { + foreach (Classifier *classifier, variant.value< QList >()) + strings.append(classifier->description(expanded)); } else { qFatal("Unrecognized type: %s", qPrintable(type)); } @@ -682,6 +692,10 @@ QString Object::argument(int index, bool expanded) const return variant.value()->description(expanded); } else if (type == "br::Distance*") { return variant.value()->description(expanded); + } else if (type == "br::Representation*") { + return variant.value()->description(expanded); + } else if (type == "br::Classifier*") { + return variant.value()->description(expanded); } else if (type == "QStringList") { return "[" + variant.toStringList().join(",") + "]"; } @@ -713,10 +727,20 @@ void Object::store(QDataStream &stream) const } else if (type == "QList") { foreach (Distance *distance, property.read(this).value< QList >()) distance->store(stream); + } else if (type == "QList") { + foreach (Representation *representation, property.read(this).value< QList >()) + representation->store(stream); + } else if (type == "QList") { + foreach (Classifier *classifier, property.read(this).value< QList >()) + classifier->store(stream); } else if (type == "br::Transform*") { property.read(this).value()->store(stream); } else if (type == "br::Distance*") { property.read(this).value()->store(stream); + } else if (type == "br::Representation*") { + property.read(this).value()->store(stream); + } else if (type == "br::Classifier*") { + property.read(this).value()->store(stream); } else if (type == "bool") { stream << property.read(this).toBool(); } else if (type == "int") { @@ -750,10 +774,20 @@ void Object::load(QDataStream &stream) } else if (type == "QList") { foreach (Distance *distance, property.read(this).value< QList >()) distance->load(stream); + } else if (type == "QList") { + foreach (Representation *representation, property.read(this).value< QList >()) + representation->load(stream); + } else if (type == "QList") { + foreach (Classifier *classifier, property.read(this).value< QList >()) + classifier->load(stream); } else if (type == "br::Transform*") { property.read(this).value()->load(stream); } else if (type == "br::Distance*") { property.read(this).value()->load(stream); + } else if (type == "br::Representation*") { + property.read(this).value()->load(stream); + } else if (type == "br::Classifier*") { + property.read(this).value()->load(stream); } else if (type == "bool") { bool value; stream >> value; @@ -919,6 +953,18 @@ void Object::setProperty(const QString &name, QVariant value) if (element.canConvert()) parsedValues.append(Distance::make(element.toString(), this)); else parsedValues.append(element.value()); value.setValue(parsedValues); + } else if (type == "QList") { + QList parsedValues; + foreach (const QVariant &element, elements) + if (element.canConvert()) parsedValues.append(Representation::make(element.toString(), this)); + else parsedValues.append(element.value()); + value.setValue(parsedValues); + } else if (type == "QList") { + QList parsedValues; + foreach (const QVariant &element, elements) + if (element.canConvert()) parsedValues.append(Classifier::make(element.toString(), this)); + else parsedValues.append(element.value()); + value.setValue(parsedValues); } else { qFatal("Unrecognized type: %s", qPrintable(type)); } @@ -928,6 +974,12 @@ void Object::setProperty(const QString &name, QVariant value) } else if (type == "br::Distance*") { if (value.canConvert()) value.setValue(Distance::make(value.toString(), this)); + } else if (type == "br::Representation*") { + if (value.canConvert()) + value.setValue(Representation::make(value.toString(), this)); + } else if (type == "br::Classifier*") { + if (value.canConvert()) + value.setValue(Classifier::make(value.toString(), this)); } else if (type == "bool") { if (value.isNull()) value = true; else if (value == "false") value = false; @@ -1086,10 +1138,14 @@ void br::Context::initialize(int &argc, char *argv[], QString sdkPath, bool useG qRegisterMetaType(); qRegisterMetaType< br::Transform* >(); qRegisterMetaType< br::Distance* >(); + qRegisterMetaType< br::Representation* >(); + qRegisterMetaType< br::Classifier* >(); qRegisterMetaType< QList >(); qRegisterMetaType< QList >(); qRegisterMetaType< QList >(); qRegisterMetaType< QList >(); + qRegisterMetaType< QList >(); + qRegisterMetaType< QList >(); qRegisterMetaType< QAbstractSocket::SocketState> (); qRegisterMetaType< QLocalSocket::LocalSocketState> (); @@ -1196,6 +1252,15 @@ QStringList br::Context::objects(const char *abstractions, const char *implement if (implementationsRegExp.exactMatch(name)) objectList.append(name + (parameters ? "\t" + Factory::parameters(name) : "")); + if (abstractionsRegExp.exactMatch("Representation")) + foreach (const QString &name, Factory::names()) + if (implementationsRegExp.exactMatch(name)) + objectList.append(name + (parameters ? "\t" + Factory::parameters(name) : "")); + + if (abstractionsRegExp.exactMatch("Classifier")) + foreach (const QString &name, Factory::names()) + if (implementationsRegExp.exactMatch(name)) + objectList.append(name + (parameters ? "\t" + Factory::parameters(name) : "")); return objectList; } @@ -1607,3 +1672,29 @@ Transform *br::pipeTransforms(QList &transforms) res->setPropertyRecursive("transforms", QVariant::fromValue(transforms)); return res; } + +Representation *Representation::make(QString str, QObject *parent) +{ + // Check for custom transforms + if (Globals->abbreviations.contains(str)) + return make(Globals->abbreviations[str], parent); + + File f = "." + str; + Representation *rep = Factory::make(f); + + rep->setParent(parent); + return rep; +} + +Classifier *Classifier::make(QString str, QObject *parent) +{ + // Check for custom transforms + if (Globals->abbreviations.contains(str)) + return make(Globals->abbreviations[str], parent); + + File f = "." + str; + Classifier *classifier = Factory::make(f); + + classifier->setParent(parent); + return classifier; +} diff --git a/openbr/openbr_plugin.h b/openbr/openbr_plugin.h index 8788824..2d2d53e 100644 --- a/openbr/openbr_plugin.h +++ b/openbr/openbr_plugin.h @@ -1393,10 +1393,13 @@ class BR_EXPORT Representation : public Object public: virtual ~Representation() {} + static Representation *make(QString str, QObject *parent); /*!< \brief Make a representation from a string. */ virtual cv::Mat preprocess(const cv::Mat &image) const { return image; } + virtual void train(const QList &images, const QList &labels) { (void) images; (void)labels; } // By convention, an empty indices list will result in all feature responses being calculated // and returned. virtual cv::Mat evaluate(const cv::Mat &image, const QList &indices = QList()) const = 0; + virtual int numFeatures() const = 0; }; class BR_EXPORT Classifier : public Object @@ -1406,7 +1409,10 @@ class BR_EXPORT Classifier : public Object public: virtual ~Classifier() {} + static Classifier *make(QString str, QObject *parent); /*!< \brief Make a classifier from a string. */ virtual void train(const QList &images, const QList &labels) = 0; + // By convention, classify should return a value normalized such that the threshold is 0. Negative values + // can be interpreted as a negative classification and positive values as a positive classification. virtual float classify(const cv::Mat &image) const = 0; }; @@ -1497,10 +1503,14 @@ Q_DECLARE_METATYPE(br::Template) Q_DECLARE_METATYPE(br::TemplateList) Q_DECLARE_METATYPE(br::Transform*) Q_DECLARE_METATYPE(br::Distance*) +Q_DECLARE_METATYPE(br::Representation*) +Q_DECLARE_METATYPE(br::Classifier*) Q_DECLARE_METATYPE(QList) Q_DECLARE_METATYPE(QList) Q_DECLARE_METATYPE(QList) Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) #endif // __cplusplus