Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ if(NOT BR_PACKAGE_THIRDPARTY)

# Build additional OpenBR utilities
add_subdirectory(br-gui)

add_subdirectory(br-docs)
endif()
endif()
9 changes: 9 additions & 0 deletions app/br-docs/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_executable(br-docs br-docs.cpp ${BR_RESOURCES})

foreach(QT_DEPENDENCY IN LISTS QT_DEPENDENCIES)
target_link_libraries(br-docs "Qt6::${QT_DEPENDENCY}")
endforeach()

target_link_libraries(br-docs openbr ${BR_THIRDPARTY_LIBS} opencv_core)
install(TARGETS br-docs RUNTIME DESTINATION bin)
27 changes: 27 additions & 0 deletions app/br-docs/br-docs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

#include <QRegularExpression>
#include <stdio.h>

#include <openbr/openbr_plugin.h>

int main(int argc, char *argv[])
{
QRegularExpression regex;

for (int i = 1; i < argc; i++) {
QString arg = QString::fromLocal8Bit(argv[i]);
if (arg == "--help" || arg == "-h") {
printf("Usage: br-docs\n");
printf(" --regex <pattern> Only generate docs for transforms matching <pattern>\n");
return 0;
} else if (arg == "--regex") {
regex = QRegularExpression(QString::fromLocal8Bit(argv[++i]));
}
}

br::Context::initialize(argc, argv);

br::AllDocs(regex);

br::Context::finalize();
}
3 changes: 3 additions & 0 deletions app/br/br.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ class FakeMain : public QRunnable
else if (!strcmp(fun, "help")) {
check(parc == 0, "No parameters expected for 'help'.");
help();
} else if (!strcmp(fun, "docs")) {
check(parc == 0, "No parameters expected for 'docs'.");
printf("%s\n", br_docs());
} else if (!strcmp(fun, "gui")) {
// Do nothing because we checked for this flag prior to initialization
} else if (!strcmp(fun, "objects")) {
Expand Down
13 changes: 13 additions & 0 deletions docs/docs/api_docs/c_api/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@ Calls [Context](../cpp_api/context/context.md)::[about](../cpp_api/context/stati

---

## br_docs

Generates on-the-fly documentation (formatted using newline and indentation) for the transforms requested in the algorithm.

* **function definition:**

const char *br_docs()

* **parameters:** None
* **output:** (const char *) Returns a string including the documentation

---

## br_cat

Concatenates a list of galleries into 1 gallery.
Expand Down
10 changes: 10 additions & 0 deletions docs/docs/api_docs/cl_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,16 @@ Get a string with the name, version, and copyright of the project. This string i

* **wraps:** [br_about](c_api/functions.md#br_about)

### -docs {: #docs }

Get a string with the on-the-fly generated (formatted using newline and indentation) documentation for transforms requested by the algorithm string. This string is suitable for printing or terminal

* **arguments:**

-docs

* **wraps:** [br_docs](c_api/functions.md#br_docs)

### -version {: #version }

Get the current OpenBR version
Expand Down
34 changes: 28 additions & 6 deletions openbr/core/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,11 @@ struct AlgorithmCore

AlgorithmCore(const QString &name)
{
if (name == "algorithm") {
this->name = Globals->algorithm;
init(Globals->algorithm);
} else {
this->name = name;
init(name);
this->name = name == "algorithm" ? Globals->algorithm : name;
try {
init(this->name);
} catch (...) {
qFatal("Failed to initialize%s: %s", qPrintable(name == "algorithm" ? " algorithm" : ""), qPrintable(this->name));
}

progressCounter = QSharedPointer<Transform>(Transform::make("ProgressCounter", NULL));
Expand Down Expand Up @@ -653,6 +652,29 @@ void br::Train(const File &input, const File &model)
AlgorithmManager::getAlgorithm(model.get<QString>("algorithm"))->train(input, model);
}

QString br::Docs()
{
return AlgorithmManager::getAlgorithm("algorithm")->transform->docs(0);
}

void br::AllDocs(QRegularExpression regex)
{
QStringList names = Factory<Transform>::names();
printf("Registered Transforms: %d\n", names.size());

foreach (const QString &name, names) {
if (!regex.pattern().isEmpty() && !regex.match(name).hasMatch())
continue;
try {
br::Transform* transform = br::Factory<br::Transform>::make("." + name);
QString docs = transform->docs(4);
printf("%s", docs.toStdString().c_str());
} catch (...) {
printf(" %s(?\?\?)\n", name.toStdString().c_str());
}
}
}

void br::Enroll(const File &input, const File &gallery)
{
AlgorithmManager::getAlgorithm(gallery.get<QString>("algorithm"))->enroll(input, gallery);
Expand Down
11 changes: 10 additions & 1 deletion openbr/openbr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ void br_eval_eer(const char *predicted_xml, const char *gt_property, const char
EvalEER(predicted_xml, gt_property, distribution_property, pdf);
}

const char *br_docs()
{
return Docs().toLocal8Bit().constData();
}

void br_finalize()
{
Context::finalize();
Expand Down Expand Up @@ -293,7 +298,11 @@ void br_set_header(const char *matrix, const char *target_gallery, const char *q

void br_set_property(const char *key, const char *value)
{
Globals->setProperty(key, value);
try {
Globals->setProperty(key, value);
} catch (...) {
qFatal("Failed to set property %s to %s", key, value);
}
}

int br_time_remaining()
Expand Down
2 changes: 2 additions & 0 deletions openbr/openbr.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ extern "C" {

BR_EXPORT const char *br_about();

BR_EXPORT const char *br_docs();

BR_EXPORT void br_cat(int num_input_galleries, const char *input_galleries[], const char *output_gallery);

BR_EXPORT void br_deduplicate(const char *input_gallery, const char *output_gallery, const char *threshold);
Expand Down
32 changes: 26 additions & 6 deletions openbr/openbr_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ QString Object::argument(int index, bool expanded) const

return "[" + strings.join(",") + "]";
} else if (type == "br::Transform*") {
return variant.value<Transform*>()->description(expanded);
return variant.isNull() ? "" : variant.value<Transform*>()->description(expanded);
} else if (type == "br::Distance*") {
return variant.value<Distance*>()->description(expanded);
} else if (type == "br::Representation*") {
Expand Down Expand Up @@ -886,7 +886,10 @@ void Object::setProperty(const QString &name, QVariant value)
{
QString type;
int index = metaObject()->indexOfProperty(qPrintable(name));
if (index != -1) type = metaObject()->property(index).typeName();
if (index != -1)
type = metaObject()->property(index).typeName();
else
printf("Object %s does not have property %s! Can not set its value to %s!\n", metaObject()->className(), qPrintable(name), qPrintable(value.toString()));

if (metaObject()->property(index).isEnumType()) {
// This is necessary because setProperty can only set enums
Expand Down Expand Up @@ -995,8 +998,7 @@ void Object::setProperty(const QString &name, QVariant value)
}

if (!QObject::setProperty(qPrintable(name), value) && !type.isEmpty())
qFatal("Failed to set %s %s::%s to: %s",
qPrintable(type), metaObject()->className(), qPrintable(name), qPrintable(value.toString()));
throw QString("Failed to set %1 %2::%3 to: %4").arg(type).arg(metaObject()->className()).arg(name).arg(value.toString()).toStdString();
}

QStringList Object::parse(const QString &string, char split)
Expand Down Expand Up @@ -1271,8 +1273,13 @@ QStringList br::Context::objects(const char *abstractions, const char *implement
}
if (abstractionsRegExp.match("Transform").hasMatch()) {
foreach (const QString &name, Factory<Transform>::names())
if (implementationsRegExp.match(name).hasMatch())
objectList.append(name + (parameters ? "\t" + Factory<Transform>::parameters(name) : ""));
if (implementationsRegExp.match(name).hasMatch()) {
try {
objectList.append(name + (parameters ? "\t" + Factory<Transform>::parameters(name) : ""));
} catch (...) {
// Exclude transforms that fail to initialize
}
}
}
if (abstractionsRegExp.match("Representation").hasMatch()) {
foreach (const QString &name, Factory<Representation>::names())
Expand Down Expand Up @@ -1598,6 +1605,19 @@ void Transform::train(const QList<TemplateList> &data)
train(combined);
}


QString Transform::get_doc_header(QString doc, int indent) const
{
QString name = this->file.suffix();
QString params;
try {
params = Factory<Transform>::parameters("."+description(false));
} catch (...) {
params = "?\?\?";
}
return QString("%1%2(%3): %4\n").arg(QString(indent, ' ')).arg(name).arg(params).arg(doc);
}

/* Distance - public methods */
Distance *Distance::make(QString str, QObject *parent)
{
Expand Down
19 changes: 19 additions & 0 deletions openbr/openbr_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <QPoint>
#include <QPointF>
#include <QRectF>
#include <QRegularExpression>
#include <QScopedPointer>
#include <QSharedPointer>
#include <QString>
Expand Down Expand Up @@ -752,6 +753,20 @@ class BR_EXPORT Transform : public Object
virtual void train(const TemplateList &data);
virtual void train(const QList<TemplateList> &data);

QString get_doc_header(QString doc, int indent) const;

QString get_doc(QString doc, int indent) const {
return QString("%1%2\n").arg(QString(indent, ' ')).arg(doc);
}

virtual QString docs(int indent) const {
return get_doc_header(docs(), indent);
}

virtual const QString docs() const
{
return "";
}

virtual void project(const Template &src, Template &dst) const = 0;
virtual void project(const TemplateList &src, TemplateList &dst) const;
Expand Down Expand Up @@ -918,6 +933,10 @@ BR_EXPORT bool IsClassifier(const QString &algorithm);

BR_EXPORT void Train(const File &input, const File &model);

BR_EXPORT QString Docs();

BR_EXPORT void AllDocs(QRegularExpression regex);

BR_EXPORT void Enroll(const File &input, const File &gallery = File());

BR_EXPORT void Enroll(TemplateList &tmpl);
Expand Down
5 changes: 5 additions & 0 deletions openbr/plugins/core/discard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ class DiscardTransform : public UntrainableMetaTransform
{
dst.file = src.file;
}

const QString docs() const
{
return "Removes all matrices from a template.";
}
};

BR_REGISTER(Transform, DiscardTransform)
Expand Down
12 changes: 12 additions & 0 deletions openbr/plugins/core/fork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,18 @@ class ForkTransform : public CompositeTransform
}
}

QString docs(int indent) const
{
QString docs = get_doc_header("Project the input template(s) through each transform and concatenate the results", indent);
foreach (const Transform *f, transforms) {
// We need to create a new instance of the transform for any independent transforms
// because they are wrapped by MetaTransform until project() is called.
QString description = "." + f->description(false); // Needs to start with a .
docs += Factory<Transform>::make(description)->docs(indent + 4);
}
return docs;
}

protected:

// Apply each transform to src, concatenate the results
Expand Down
5 changes: 5 additions & 0 deletions openbr/plugins/core/identity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ class IdentityTransform : public UntrainableMetaTransform
{
dst = src;
}

const QString docs() const
{
return "Noop transform";
}
};

BR_REGISTER(Transform, IdentityTransform)
Expand Down
2 changes: 1 addition & 1 deletion openbr/plugins/core/independent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class IndependentTransform : public MetaTransform

QString description(bool expanded) const
{
return transform->description(expanded);
return transform != NULL ? transform->description(expanded) : "Identity";
}

// can't use general setPropertyRecursive because of transforms oddness
Expand Down
11 changes: 11 additions & 0 deletions openbr/plugins/core/pipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,17 @@ class PipeTransform : public CompositeTransform
return result;
}

QString docs(int indent) const
{
QString docs = get_doc_header("Project the output of each Transform into the next", indent);
foreach (const Transform *f, transforms) {
// We need to create a new instance of the transform for any independent transforms
// because they are wrapped by MetaTransform until project() is called.
QString description = "." + f->description(false); // Needs to start with a .
docs += Factory<Transform>::make(description)->docs(indent + 4);
}
return docs;
}
protected:
// Template list project -- process templates in parallel through Transform::project
// or if parallelism is disabled, handle them sequentially
Expand Down
3 changes: 2 additions & 1 deletion openbr/plugins/distance/dist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ class DistDistance : public UntrainableDistance
L1,
L2,
Cosine,
Dot};
Dot,
Default = L2};

private:
BR_PROPERTY(Metric, metric, L2)
Expand Down
12 changes: 4 additions & 8 deletions openbr/plugins/gui/show.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,10 +611,8 @@ class ShowTransform : public TimeVaryingTransform
template<typename WindowType>
void initActual()
{
if (!Globals->useGui) {
qWarning("GUI transform %s created without enabling GUI support.\nRun \"br -gui ...\" to enable GUI support from the command line, or set\nGlobals->useGui to true.", this->metaObject()->className());
return;
}
if (!Globals->useGui)
throw QString("GUI transform %1 created without enabling GUI support.\nRun \"br -gui ...\" to enable GUI support from the command line, or set\nGlobals->useGui to true.").arg(this->metaObject()->className()).toStdString();

if (displayBuffer)
delete displayBuffer;
Expand Down Expand Up @@ -863,10 +861,8 @@ class ElicitTransform : public ShowTransform
template<typename GUIType>
void initActual()
{
if (!Globals->useGui) {
qWarning("GUI transform %s created without enabling GUI support.\nRun \"br -gui ...\" to enable GUI support from the command line, or set\nGlobals->useGui to true.", this->metaObject()->className());
return;
}
if (!Globals->useGui)
throw QString("GUI transform %1 created without enabling GUI support.\nRun \"br -gui ...\" to enable GUI support from the command line, or set\nGlobals->useGui to true.").arg(this->metaObject()->className()).toStdString();

TimeVaryingTransform::init();

Expand Down
5 changes: 5 additions & 0 deletions openbr/plugins/imgproc/cvtfloat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ class CvtFloatTransform : public UntrainableTransform
{
src.m().convertTo(dst, CV_32F);
}

const QString docs() const
{
return "Convert the matrix to float32";
}
};

BR_REGISTER(Transform, CvtFloatTransform)
Expand Down
Loading