From 5d001f4dba69bccdeb5e3db905b69cdaf18235dd Mon Sep 17 00:00:00 2001 From: JordanCheney Date: Tue, 9 Dec 2014 15:30:30 -0500 Subject: [PATCH] Unimplemented header files for adaboost --- openbr/CMakeLists.txt | 3 ++- openbr/learning/adaboost.cpp | 5 +++++ openbr/learning/adaboost.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ openbr/learning/cascade.cpp | 5 +++++ openbr/learning/cascade.h | 29 +++++++++++++++++++++++++++++ openbr/learning/feature.cpp | 5 +++++ openbr/learning/feature.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ openbr/learning/trainingdata.cpp | 5 +++++ openbr/learning/trainingdata.h | 33 +++++++++++++++++++++++++++++++++ 9 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 openbr/learning/adaboost.cpp create mode 100644 openbr/learning/adaboost.h create mode 100644 openbr/learning/cascade.cpp create mode 100644 openbr/learning/cascade.h create mode 100644 openbr/learning/feature.cpp create mode 100644 openbr/learning/feature.h create mode 100644 openbr/learning/trainingdata.cpp create mode 100644 openbr/learning/trainingdata.h diff --git a/openbr/CMakeLists.txt b/openbr/CMakeLists.txt index 8f82b9f..d10d8b6 100644 --- a/openbr/CMakeLists.txt +++ b/openbr/CMakeLists.txt @@ -11,6 +11,7 @@ add_definitions(-DJANUS_LIBRARY) # Collect source files aux_source_directory(. SRC) aux_source_directory(core BR_CORE) +aux_source_directory(learning BR_LEARNING) include(plugins/plugins.cmake) # Optional GUI module @@ -21,7 +22,7 @@ if(NOT ${BR_EMBEDDED}) install(FILES ${HEADERS} DESTINATION include/openbr/gui) endif() -add_library(openbr SHARED ${SRC} ${BR_CORE} ${BR_JANUS} ${BR_GUI} ${BR_ICONS} ${BR_THIRDPARTY_SRC} ${BR_RESOURCES} ${NATURALSTRINGCOMPARE_SRC}) +add_library(openbr SHARED ${SRC} ${BR_CORE} ${BR_LEARNING} ${BR_JANUS} ${BR_GUI} ${BR_ICONS} ${BR_THIRDPARTY_SRC} ${BR_RESOURCES} ${NATURALSTRINGCOMPARE_SRC}) qt5_use_modules(openbr ${QT_DEPENDENCIES}) set_target_properties(openbr PROPERTIES DEFINE_SYMBOL BR_LIBRARY diff --git a/openbr/learning/adaboost.cpp b/openbr/learning/adaboost.cpp new file mode 100644 index 0000000..c788c92 --- /dev/null +++ b/openbr/learning/adaboost.cpp @@ -0,0 +1,5 @@ +#include "adaboost.h" + +AdaBoost::AdaBoost() +{ +} diff --git a/openbr/learning/adaboost.h b/openbr/learning/adaboost.h new file mode 100644 index 0000000..877f4c8 --- /dev/null +++ b/openbr/learning/adaboost.h @@ -0,0 +1,46 @@ +#ifndef ADABOOST_H +#define ADABOOST_H + +#include "trainingdata.h" +#include + +namespace br +{ + +struct Node +{ + Node(int feature_idx, float threshold, int polarity, float weight) : feature_idx(feature_idx), threshold(threshold), polarity(polarity), weight(weight) {} + int predict(float feature_response) const { return (polarity * (feature_response - threshold)) > 0 ? 1 : -1; } + + int feature_idx; // index of the feature corresponding to this weak classifier + float threshold; // threshold at which classifier predicts yes or no + int polarity; // 1 or -1. 1 if high responses correspond to positives, -1 if low values do. + float weight; // weight of this classifier. Higher weight = more accurate classifier +}; + +struct DecisionTree +{ + DecisionTree() {} + void append(Node node); // add a node to the tree + float predict(QList responses) const; // progress down the tree. Return value should be the + // sum of the weights of the correct nodes. + + QList tree; // List of the weak classifiers +}; + +class AdaBoost +{ +public: + AdaBoost(); + DecisionTree train(int num_classifiers); // mostly a wrapper to call selectBestNode() and updateWeights() num_classifiers times. + +private: + Node selectBestNode(); // search through all possible features to find one that improves performance the most + void updateWeights(); // successful classification lowers weights, unsuccesful raises weights. After changes weights are normalized between 0 and 1 + + TrainingData td; // training data to train on + DecisionTree classifier; // classifier to be trained +}; + +} +#endif // ADABOOST_H diff --git a/openbr/learning/cascade.cpp b/openbr/learning/cascade.cpp new file mode 100644 index 0000000..35e523d --- /dev/null +++ b/openbr/learning/cascade.cpp @@ -0,0 +1,5 @@ +#include "cascade.h" + +Cascade::Cascade() +{ +} diff --git a/openbr/learning/cascade.h b/openbr/learning/cascade.h new file mode 100644 index 0000000..d2a115a --- /dev/null +++ b/openbr/learning/cascade.h @@ -0,0 +1,29 @@ +#ifndef CASCADE_H +#define CASCADE_H + +#include "feature.h" +#include "adaboost.h" +#include + +namespace br +{ + +// I'm not sure if this class can be made general enough (i.e not just for face detection) to live here. +// Ideally, it should handle model i/o, and probably detection as well. Perhaps it is better in plugins/cascade.cpp +class Cascade +{ +public: + Cascade(const DecisionTree &classifier, const FeatureEvaluator &evaluator) : classifier(classifier), evaluator(evaluator) {} + void detect(const cv::Mat &img, QList &detections, QList &confidences); + + void write(QString path); + static Cascade read(QString path); + +private: + DecisionTree classifier; + FeatureEvaluator evaluator; +}; + +} + +#endif // CASCADE_H diff --git a/openbr/learning/feature.cpp b/openbr/learning/feature.cpp new file mode 100644 index 0000000..e343d86 --- /dev/null +++ b/openbr/learning/feature.cpp @@ -0,0 +1,5 @@ +#include "feature.h" + +Feature::Feature() +{ +} diff --git a/openbr/learning/feature.h b/openbr/learning/feature.h new file mode 100644 index 0000000..bfd9627 --- /dev/null +++ b/openbr/learning/feature.h @@ -0,0 +1,47 @@ +#ifndef FEATURE_H +#define FEATURE_H + +#include + +// These two classes should be subclassed to handle any type of feature. In a perfect world I would like to subclass +// only Feature, and have FeatureEvaluator just call randomize and evaluate (and thus not have to be subclassed) as +// that would be simpler. +namespace br +{ + +class Feature +{ +public: + Feature(); + QList get_definition() { return definition; } + + virtual void randomize(int height, int width, int channels) = 0; // Initialize the feature within these dimensions + virtual float evaluate(const QList &img, const cv::Size &pos) const = 0; // img is a list of mats to support multiple channels + // if the image is larger than the feature model (i.e + // a real image instead of a training image) pos determines + // the top left corner of the feature. + +protected: + QList definition; // The definition of the feature (usually these are coords) +}; + +class FeatureEvaluator +{ +public: + FeatureEvaluator(int num_features_) : num_features(num_features_) {} + int get_num_features() const { return num_features; } + QList get_features() const { return features; } + + virtual void generateRandomFeatures(int height, int width, int channels) = 0; // initialize num_features random features within these dimensions. + // will call Feature->randomize() + virtual QList evaluate(const QList &img, cv::Size pos) const = 0; // return the response of all features on the given image + // will call Feature->evaluate() + +private: + int num_features; + QList features; +}; + +} + +#endif // FEATURE_H diff --git a/openbr/learning/trainingdata.cpp b/openbr/learning/trainingdata.cpp new file mode 100644 index 0000000..f6a4030 --- /dev/null +++ b/openbr/learning/trainingdata.cpp @@ -0,0 +1,5 @@ +#include "trainingdata.h" + +TrainingData::TrainingData() +{ +} diff --git a/openbr/learning/trainingdata.h b/openbr/learning/trainingdata.h new file mode 100644 index 0000000..e9cc04d --- /dev/null +++ b/openbr/learning/trainingdata.h @@ -0,0 +1,33 @@ +#ifndef TRAININGDATA_H +#define TRAININGDATA_H + +#include "feature.h" +#include + +namespace br +{ + +struct FeatureResponse // Feature vectors need to be sorted to do boosting. This keeps the weights and labels properly associated with the response without headaches. +{ + FeatureResponse(float response, int label, float weight) : response(response), label(label), weight(weight) {} + + float response; + int label; + float weight; +}; + +typedef QList FeatureVector; + +class TrainingData +{ +public: + TrainingData(); + // This can have getters and setters to make manipulating feature vectors easier + +private: + QList data; + QList visited_features; +}; + +} +#endif // TRAININGDATA_H -- libgit2 0.21.4