commit
c064042c33
13 changed files with 1315 additions and 0 deletions
@ -0,0 +1,4 @@ |
|||||||
|
set(the_description "Automatic driver assistance algorithms") |
||||||
|
ocv_define_module(adas opencv_xobjdetect) |
||||||
|
|
||||||
|
add_subdirectory(tools) |
@ -0,0 +1,40 @@ |
|||||||
|
/*
|
||||||
|
|
||||||
|
By downloading, copying, installing or using the software you agree to this |
||||||
|
license. If you do not agree to this license, do not download, install, |
||||||
|
copy or use the software. |
||||||
|
|
||||||
|
|
||||||
|
License Agreement |
||||||
|
For Open Source Computer Vision Library |
||||||
|
(3-clause BSD License) |
||||||
|
|
||||||
|
Copyright (C) 2013, OpenCV Foundation, all rights reserved. |
||||||
|
Third party copyrights are property of their respective owners. |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, |
||||||
|
are permitted provided that the following conditions are met: |
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer. |
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer in the documentation |
||||||
|
and/or other materials provided with the distribution. |
||||||
|
|
||||||
|
* Neither the names of the copyright holders nor the names of the contributors |
||||||
|
may be used to endorse or promote products derived from this software |
||||||
|
without specific prior written permission. |
||||||
|
|
||||||
|
This software is provided by the copyright holders and contributors "as is" and |
||||||
|
any express or implied warranties, including, but not limited to, the implied |
||||||
|
warranties of merchantability and fitness for a particular purpose are |
||||||
|
disclaimed. In no event shall copyright holders or contributors be liable for |
||||||
|
any direct, indirect, incidental, special, exemplary, or consequential damages |
||||||
|
(including, but not limited to, procurement of substitute goods or services; |
||||||
|
loss of use, data, or profits; or business interruption) however caused |
||||||
|
and on any theory of liability, whether in contract, strict liability, |
||||||
|
or tort (including negligence or otherwise) arising in any way out of |
||||||
|
the use of this software, even if advised of the possibility of such damage. |
||||||
|
|
||||||
|
*/ |
@ -0,0 +1,34 @@ |
|||||||
|
set(name fcw_train) |
||||||
|
set(the_target opencv_${name}) |
||||||
|
|
||||||
|
set(OPENCV_${the_target}_DEPS opencv_xobjdetect) |
||||||
|
|
||||||
|
ocv_check_dependencies(${OPENCV_${the_target}_DEPS}) |
||||||
|
|
||||||
|
if(NOT OCV_DEPENDENCIES_FOUND) |
||||||
|
return() |
||||||
|
endif() |
||||||
|
|
||||||
|
project(${the_target}) |
||||||
|
|
||||||
|
ocv_include_directories("${OpenCV_SOURCE_DIR}/include/opencv") |
||||||
|
ocv_include_modules(${OPENCV_${the_target}_DEPS}) |
||||||
|
|
||||||
|
file(GLOB ${the_target}_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) |
||||||
|
|
||||||
|
add_executable(${the_target} ${${the_target}_SOURCES}) |
||||||
|
|
||||||
|
target_link_libraries(${the_target} ${OPENCV_${the_target}_DEPS}) |
||||||
|
|
||||||
|
set_target_properties(${the_target} PROPERTIES |
||||||
|
DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" |
||||||
|
ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} |
||||||
|
RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} |
||||||
|
INSTALL_NAME_DIR lib |
||||||
|
OUTPUT_NAME ${the_target}) |
||||||
|
|
||||||
|
if(ENABLE_SOLUTION_FOLDERS) |
||||||
|
set_target_properties(${the_target} PROPERTIES FOLDER "applications") |
||||||
|
endif() |
||||||
|
|
||||||
|
install(TARGETS ${the_target} RUNTIME DESTINATION bin COMPONENT main) |
@ -0,0 +1,195 @@ |
|||||||
|
#include <cstdio> |
||||||
|
#include <cstring> |
||||||
|
|
||||||
|
#include <string> |
||||||
|
using std::string; |
||||||
|
|
||||||
|
#include <vector> |
||||||
|
using std::vector; |
||||||
|
|
||||||
|
#include <fstream> |
||||||
|
using std::ifstream; |
||||||
|
using std::getline; |
||||||
|
|
||||||
|
#include <sstream> |
||||||
|
using std::stringstream; |
||||||
|
|
||||||
|
#include <iostream> |
||||||
|
using std::cerr; |
||||||
|
using std::endl; |
||||||
|
|
||||||
|
#include <opencv2/core.hpp> |
||||||
|
using cv::Rect; |
||||||
|
|
||||||
|
#include <opencv2/xobjdetect.hpp> |
||||||
|
|
||||||
|
using cv::xobjdetect::ICFDetectorParams; |
||||||
|
using cv::xobjdetect::ICFDetector; |
||||||
|
using cv::xobjdetect::WaldBoost; |
||||||
|
using cv::xobjdetect::WaldBoostParams; |
||||||
|
using cv::Mat; |
||||||
|
|
||||||
|
static bool read_pos_int(const char *str, int *n) |
||||||
|
{ |
||||||
|
int pos = 0; |
||||||
|
if( sscanf(str, "%d%n", n, &pos) != 1 || str[pos] != '\0' || *n <= 0 ) |
||||||
|
{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
static bool read_model_size(char *str, int *rows, int *cols) |
||||||
|
{ |
||||||
|
int pos = 0; |
||||||
|
if( sscanf(str, "%dx%d%n", rows, cols, &pos) != 2 || str[pos] != '\0' || |
||||||
|
*rows <= 0 || *cols <= 0) |
||||||
|
{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
static bool read_overlap(const char *str, double *overlap) |
||||||
|
{ |
||||||
|
int pos = 0; |
||||||
|
if( sscanf(str, "%lf%n", overlap, &pos) != 1 || str[pos] != '\0' || |
||||||
|
*overlap < 0 || *overlap > 1) |
||||||
|
{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
static bool read_labels(const string& path, |
||||||
|
vector<string>& filenames, vector< vector<Rect> >& labels) |
||||||
|
{ |
||||||
|
string labels_path = path + "/gt.txt"; |
||||||
|
string filename, line; |
||||||
|
int x1, y1, x2, y2; |
||||||
|
char delim; |
||||||
|
ifstream ifs(labels_path.c_str()); |
||||||
|
if( !ifs.good() ) |
||||||
|
return false; |
||||||
|
|
||||||
|
while( getline(ifs, line) ) |
||||||
|
{ |
||||||
|
stringstream stream(line); |
||||||
|
stream >> filename; |
||||||
|
filenames.push_back(path + "/" + filename); |
||||||
|
vector<Rect> filename_labels; |
||||||
|
while( stream >> x1 >> y1 >> x2 >> y2 >> delim ) |
||||||
|
{ |
||||||
|
filename_labels.push_back(Rect(x1, y1, x2, y2)); |
||||||
|
} |
||||||
|
labels.push_back(filename_labels); |
||||||
|
filename_labels.clear(); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) |
||||||
|
{ |
||||||
|
if( argc == 1 ) |
||||||
|
{ |
||||||
|
printf("Usage: %s OPTIONS, where OPTIONS are:\n" |
||||||
|
"\n" |
||||||
|
"--path <path> - path to dir with data and labels\n" |
||||||
|
" (labels should have name gt.txt)\n" |
||||||
|
"\n" |
||||||
|
"--feature_count <count> - number of features to generate\n" |
||||||
|
"\n" |
||||||
|
"--weak_count <count> - number of weak classifiers in cascade\n" |
||||||
|
"\n" |
||||||
|
"--model_size <rowsxcols> - model size in pixels\n" |
||||||
|
"\n" |
||||||
|
"--overlap <measure> - number from [0, 1], means maximum\n" |
||||||
|
" overlap with objects while sampling background\n" |
||||||
|
"\n" |
||||||
|
"--model_filename <path> - filename for saving model\n", |
||||||
|
argv[0]); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
string path, model_path; |
||||||
|
ICFDetectorParams params; |
||||||
|
for( int i = 1; i < argc; ++i ) |
||||||
|
{ |
||||||
|
if( !strcmp("--path", argv[i]) ) |
||||||
|
{ |
||||||
|
i += 1; |
||||||
|
path = argv[i]; |
||||||
|
} |
||||||
|
else if( !strcmp("--feature_count", argv[i]) ) |
||||||
|
{ |
||||||
|
i += 1; |
||||||
|
if( !read_pos_int(argv[i], ¶ms.feature_count) ) |
||||||
|
{ |
||||||
|
fprintf(stderr, "Error reading feature count from `%s`\n", |
||||||
|
argv[i]); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
} |
||||||
|
else if( !strcmp("--weak_count", argv[i]) ) |
||||||
|
{ |
||||||
|
i += 1; |
||||||
|
if( !read_pos_int(argv[i], ¶ms.weak_count) ) |
||||||
|
{ |
||||||
|
fprintf(stderr, "Error reading weak count from `%s`\n", |
||||||
|
argv[i]); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
} |
||||||
|
else if( !strcmp("--model_size", argv[i]) ) |
||||||
|
{ |
||||||
|
i += 1; |
||||||
|
if( !read_model_size(argv[i], ¶ms.model_n_rows, |
||||||
|
¶ms.model_n_cols) ) |
||||||
|
{ |
||||||
|
fprintf(stderr, "Error reading model size from `%s`\n", |
||||||
|
argv[i]); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
} |
||||||
|
else if( !strcmp("--overlap", argv[i]) ) |
||||||
|
{ |
||||||
|
i += 1; |
||||||
|
if( !read_overlap(argv[i], ¶ms.overlap) ) |
||||||
|
{ |
||||||
|
fprintf(stderr, "Error reading overlap from `%s`\n", |
||||||
|
argv[i]); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
} |
||||||
|
else if( !strcmp("--model_filename", argv[i]) ) |
||||||
|
{ |
||||||
|
i += 1; |
||||||
|
model_path = argv[i]; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
fprintf(stderr, "Error: unknown argument `%s`\n", argv[i]); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
try |
||||||
|
{ |
||||||
|
ICFDetector detector; |
||||||
|
vector<string> filenames; |
||||||
|
vector< vector<Rect> > labels; |
||||||
|
read_labels(path, filenames, labels); |
||||||
|
|
||||||
|
detector.train(filenames, labels, params); |
||||||
|
} |
||||||
|
catch( const char *err ) |
||||||
|
{ |
||||||
|
cerr << err << endl; |
||||||
|
} |
||||||
|
catch( ... ) |
||||||
|
{ |
||||||
|
cerr << "Unknown error\n" << endl; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,2 @@ |
|||||||
|
set(the_description "Object detection algorithms") |
||||||
|
ocv_define_module(xobjdetect opencv_core opencv_imgproc opencv_highgui) |
@ -0,0 +1,179 @@ |
|||||||
|
/*
|
||||||
|
|
||||||
|
By downloading, copying, installing or using the software you agree to this |
||||||
|
license. If you do not agree to this license, do not download, install, |
||||||
|
copy or use the software. |
||||||
|
|
||||||
|
|
||||||
|
License Agreement |
||||||
|
For Open Source Computer Vision Library |
||||||
|
(3-clause BSD License) |
||||||
|
|
||||||
|
Copyright (C) 2013, OpenCV Foundation, all rights reserved. |
||||||
|
Third party copyrights are property of their respective owners. |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, |
||||||
|
are permitted provided that the following conditions are met: |
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer. |
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer in the documentation |
||||||
|
and/or other materials provided with the distribution. |
||||||
|
|
||||||
|
* Neither the names of the copyright holders nor the names of the contributors |
||||||
|
may be used to endorse or promote products derived from this software |
||||||
|
without specific prior written permission. |
||||||
|
|
||||||
|
This software is provided by the copyright holders and contributors "as is" and |
||||||
|
any express or implied warranties, including, but not limited to, the implied |
||||||
|
warranties of merchantability and fitness for a particular purpose are |
||||||
|
disclaimed. In no event shall copyright holders or contributors be liable for |
||||||
|
any direct, indirect, incidental, special, exemplary, or consequential damages |
||||||
|
(including, but not limited to, procurement of substitute goods or services; |
||||||
|
loss of use, data, or profits; or business interruption) however caused |
||||||
|
and on any theory of liability, whether in contract, strict liability, |
||||||
|
or tort (including negligence or otherwise) arising in any way out of |
||||||
|
the use of this software, even if advised of the possibility of such damage. |
||||||
|
|
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef __OPENCV_XOBJDETECT_XOBJDETECT_HPP__ |
||||||
|
#define __OPENCV_XOBJDETECT_XOBJDETECT_HPP__ |
||||||
|
|
||||||
|
#include <opencv2/core.hpp> |
||||||
|
#include <vector> |
||||||
|
#include <string> |
||||||
|
|
||||||
|
namespace cv |
||||||
|
{ |
||||||
|
namespace xobjdetect |
||||||
|
{ |
||||||
|
|
||||||
|
/* Compute channel pyramid for acf features
|
||||||
|
|
||||||
|
image — image, for which channels should be computed |
||||||
|
|
||||||
|
channels — output array for computed channels |
||||||
|
|
||||||
|
*/ |
||||||
|
void computeChannels(InputArray image, OutputArrayOfArrays channels); |
||||||
|
|
||||||
|
class CV_EXPORTS ACFFeatureEvaluator : public Algorithm |
||||||
|
{ |
||||||
|
public: |
||||||
|
/* Set channels for feature evaluation */ |
||||||
|
virtual void setChannels(InputArrayOfArrays channels) = 0; |
||||||
|
|
||||||
|
/* Set window position */ |
||||||
|
virtual void setPosition(Size position) = 0; |
||||||
|
|
||||||
|
/* Evaluate feature with given index for current channels
|
||||||
|
and window position */ |
||||||
|
virtual int evaluate(size_t feature_ind) const = 0; |
||||||
|
|
||||||
|
/* Evaluate all features for current channels and window position
|
||||||
|
|
||||||
|
Returns matrix-column of features |
||||||
|
*/ |
||||||
|
virtual void evaluateAll(OutputArray feature_values) const = 0; |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
/* Construct evaluator, set features to evaluate */ |
||||||
|
CV_EXPORTS Ptr<ACFFeatureEvaluator> |
||||||
|
createACFFeatureEvaluator(const std::vector<Point3i>& features); |
||||||
|
|
||||||
|
/* Generate acf features
|
||||||
|
|
||||||
|
window_size — size of window in which features should be evaluated |
||||||
|
|
||||||
|
count — number of features to generate. |
||||||
|
Max number of features is min(count, # possible distinct features) |
||||||
|
|
||||||
|
Returns vector of distinct acf features |
||||||
|
*/ |
||||||
|
std::vector<Point3i> |
||||||
|
generateFeatures(Size window_size, int count = INT_MAX); |
||||||
|
|
||||||
|
|
||||||
|
struct CV_EXPORTS WaldBoostParams |
||||||
|
{ |
||||||
|
int weak_count; |
||||||
|
float alpha; |
||||||
|
|
||||||
|
WaldBoostParams(): weak_count(100), alpha(0.01f) |
||||||
|
{} |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class CV_EXPORTS WaldBoost : public Algorithm |
||||||
|
{ |
||||||
|
public: |
||||||
|
/* Train WaldBoost cascade for given data
|
||||||
|
|
||||||
|
data — matrix of feature values, size M x N, one feature per row |
||||||
|
|
||||||
|
labels — matrix of sample class labels, size 1 x N. Labels can be from |
||||||
|
{-1, +1} |
||||||
|
|
||||||
|
Returns feature indices chosen for cascade. |
||||||
|
Feature enumeration starts from 0 |
||||||
|
*/ |
||||||
|
virtual std::vector<int> train(const Mat& data, |
||||||
|
const Mat& labels) = 0; |
||||||
|
|
||||||
|
/* Predict object class given object that can compute object features
|
||||||
|
|
||||||
|
feature_evaluator — object that can compute features by demand |
||||||
|
|
||||||
|
Returns confidence_value — measure of confidense that object |
||||||
|
is from class +1 |
||||||
|
*/ |
||||||
|
virtual float predict( |
||||||
|
const Ptr<ACFFeatureEvaluator>& feature_evaluator) const = 0; |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
CV_EXPORTS Ptr<WaldBoost> |
||||||
|
createWaldBoost(const WaldBoostParams& params = WaldBoostParams()); |
||||||
|
|
||||||
|
struct CV_EXPORTS ICFDetectorParams |
||||||
|
{ |
||||||
|
int feature_count; |
||||||
|
int weak_count; |
||||||
|
int model_n_rows; |
||||||
|
int model_n_cols; |
||||||
|
double overlap; |
||||||
|
|
||||||
|
ICFDetectorParams(): feature_count(UINT_MAX), weak_count(100), |
||||||
|
model_n_rows(40), model_n_cols(40), overlap(0.0) |
||||||
|
{} |
||||||
|
}; |
||||||
|
|
||||||
|
class CV_EXPORTS ICFDetector |
||||||
|
{ |
||||||
|
public: |
||||||
|
/* Train detector
|
||||||
|
|
||||||
|
image_filenames — filenames of images for training |
||||||
|
|
||||||
|
labelling — vector of object bounding boxes per every image |
||||||
|
|
||||||
|
params — parameters for detector training |
||||||
|
*/ |
||||||
|
void train(const std::vector<std::string>& image_filenames, |
||||||
|
const std::vector<std::vector<cv::Rect> >& labelling, |
||||||
|
ICFDetectorParams params = ICFDetectorParams()); |
||||||
|
|
||||||
|
/* Save detector in file, return true on success, false otherwise */ |
||||||
|
bool save(const std::string& filename); |
||||||
|
}; |
||||||
|
|
||||||
|
} /* namespace xobjdetect */ |
||||||
|
} /* namespace cv */ |
||||||
|
|
||||||
|
|
||||||
|
#endif /* __OPENCV_XOBJDETECT_XOBJDETECT_HPP__ */ |
@ -0,0 +1,62 @@ |
|||||||
|
#ifndef __OPENCV_XOBJDETECT_PRIVATE_HPP__ |
||||||
|
#define __OPENCV_XOBJDETECT_PRIVATE_HPP__ |
||||||
|
|
||||||
|
#ifndef __OPENCV_BUILD |
||||||
|
# error this is a private header, do not include it outside OpenCV |
||||||
|
#endif |
||||||
|
|
||||||
|
#include <opencv2/core.hpp> |
||||||
|
|
||||||
|
namespace cv |
||||||
|
{ |
||||||
|
namespace xobjdetect |
||||||
|
{ |
||||||
|
|
||||||
|
class CV_EXPORTS Stump |
||||||
|
{ |
||||||
|
public: |
||||||
|
|
||||||
|
/* Initialize zero stump */ |
||||||
|
Stump(): threshold_(0), polarity_(1), pos_value_(1), neg_value_(-1) {} |
||||||
|
|
||||||
|
/* Initialize stump with given threshold, polarity
|
||||||
|
and classification values */ |
||||||
|
Stump(int threshold, int polarity, float pos_value, float neg_value): |
||||||
|
threshold_(threshold), polarity_(polarity), |
||||||
|
pos_value_(pos_value), neg_value_(neg_value) {} |
||||||
|
|
||||||
|
/* Train stump for given data
|
||||||
|
|
||||||
|
data — matrix of feature values, size M x N, one feature per row |
||||||
|
|
||||||
|
labels — matrix of sample class labels, size 1 x N. Labels can be from |
||||||
|
{-1, +1} |
||||||
|
|
||||||
|
weights — matrix of sample weights, size 1 x N |
||||||
|
|
||||||
|
Returns chosen feature index. Feature enumeration starts from 0 |
||||||
|
*/ |
||||||
|
int train(const Mat& data, const Mat& labels, const Mat& weights); |
||||||
|
|
||||||
|
/* Predict object class given
|
||||||
|
|
||||||
|
value — feature value. Feature must be the same as was chosen |
||||||
|
during training stump |
||||||
|
|
||||||
|
Returns real value, sign(value) means class
|
||||||
|
*/ |
||||||
|
float predict(int value) const; |
||||||
|
|
||||||
|
private: |
||||||
|
/* Stump decision threshold */ |
||||||
|
int threshold_; |
||||||
|
/* Stump polarity, can be from {-1, +1} */ |
||||||
|
int polarity_; |
||||||
|
/* Classification values for positive and negative classes */ |
||||||
|
float pos_value_, neg_value_; |
||||||
|
}; |
||||||
|
|
||||||
|
} /* namespace xobjdetect */ |
||||||
|
} /* namespace cv */ |
||||||
|
|
||||||
|
#endif // __OPENCV_XOBJDETECT_PRIVATE_HPP__
|
@ -0,0 +1,203 @@ |
|||||||
|
/*
|
||||||
|
|
||||||
|
By downloading, copying, installing or using the software you agree to this |
||||||
|
license. If you do not agree to this license, do not download, install, |
||||||
|
copy or use the software. |
||||||
|
|
||||||
|
|
||||||
|
License Agreement |
||||||
|
For Open Source Computer Vision Library |
||||||
|
(3-clause BSD License) |
||||||
|
|
||||||
|
Copyright (C) 2013, OpenCV Foundation, all rights reserved. |
||||||
|
Third party copyrights are property of their respective owners. |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, |
||||||
|
are permitted provided that the following conditions are met: |
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer. |
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer in the documentation |
||||||
|
and/or other materials provided with the distribution. |
||||||
|
|
||||||
|
* Neither the names of the copyright holders nor the names of the contributors |
||||||
|
may be used to endorse or promote products derived from this software |
||||||
|
without specific prior written permission. |
||||||
|
|
||||||
|
This software is provided by the copyright holders and contributors "as is" and |
||||||
|
any express or implied warranties, including, but not limited to, the implied |
||||||
|
warranties of merchantability and fitness for a particular purpose are |
||||||
|
disclaimed. In no event shall copyright holders or contributors be liable for |
||||||
|
any direct, indirect, incidental, special, exemplary, or consequential damages |
||||||
|
(including, but not limited to, procurement of substitute goods or services; |
||||||
|
loss of use, data, or profits; or business interruption) however caused |
||||||
|
and on any theory of liability, whether in contract, strict liability, |
||||||
|
or tort (including negligence or otherwise) arising in any way out of |
||||||
|
the use of this software, even if advised of the possibility of such damage. |
||||||
|
|
||||||
|
*/ |
||||||
|
|
||||||
|
#include "precomp.hpp" |
||||||
|
|
||||||
|
using std::vector; |
||||||
|
|
||||||
|
using std::min; |
||||||
|
|
||||||
|
#include <iostream> |
||||||
|
using std::cout; |
||||||
|
using std::endl; |
||||||
|
|
||||||
|
namespace cv |
||||||
|
{ |
||||||
|
namespace xobjdetect |
||||||
|
{ |
||||||
|
|
||||||
|
class ACFFeatureEvaluatorImpl : public ACFFeatureEvaluator |
||||||
|
{ |
||||||
|
public: |
||||||
|
ACFFeatureEvaluatorImpl(const vector<Point3i>& features): |
||||||
|
features_(features), channels_(), position_() |
||||||
|
{ |
||||||
|
CV_Assert(features.size() > 0); |
||||||
|
} |
||||||
|
|
||||||
|
virtual void setChannels(InputArrayOfArrays channels); |
||||||
|
virtual void setPosition(Size position); |
||||||
|
virtual int evaluate(size_t feature_ind) const; |
||||||
|
virtual void evaluateAll(OutputArray feature_values) const; |
||||||
|
|
||||||
|
private: |
||||||
|
/* Features to evaluate */ |
||||||
|
std::vector<Point3i> features_; |
||||||
|
/* Channels for feature evaluation */ |
||||||
|
std::vector<Mat> channels_; |
||||||
|
/* Channels window position */ |
||||||
|
Size position_; |
||||||
|
}; |
||||||
|
|
||||||
|
void ACFFeatureEvaluatorImpl::setChannels(cv::InputArrayOfArrays channels) |
||||||
|
{ |
||||||
|
channels_.clear(); |
||||||
|
vector<Mat> ch; |
||||||
|
channels.getMatVector(ch); |
||||||
|
CV_Assert(ch.size() == 10); |
||||||
|
for( size_t i = 0; i < ch.size(); ++i ) |
||||||
|
{ |
||||||
|
const Mat &channel = ch[i]; |
||||||
|
Mat_<int> acf_channel(channel.rows / 4, channel.cols / 4); |
||||||
|
for( int row = 0; row < channel.rows; row += 4 ) |
||||||
|
{ |
||||||
|
for( int col = 0; col < channel.cols; col += 4 ) |
||||||
|
{ |
||||||
|
int sum = 0; |
||||||
|
for( int cell_row = row; cell_row < row + 4; ++cell_row ) |
||||||
|
for( int cell_col = col; cell_col < col + 4; ++cell_col ) |
||||||
|
sum += (int)channel.at<float>(cell_row, cell_col); |
||||||
|
|
||||||
|
acf_channel(row / 4, col / 4) = sum; |
||||||
|
} |
||||||
|
} |
||||||
|
channels_.push_back(acf_channel); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ACFFeatureEvaluatorImpl::setPosition(Size position) |
||||||
|
{ |
||||||
|
position_ = position; |
||||||
|
} |
||||||
|
|
||||||
|
int ACFFeatureEvaluatorImpl::evaluate(size_t feature_ind) const |
||||||
|
{ |
||||||
|
CV_Assert(channels_.size() == 10); |
||||||
|
CV_Assert(feature_ind < features_.size()); |
||||||
|
|
||||||
|
Point3i feature = features_.at(feature_ind); |
||||||
|
int x = feature.x; |
||||||
|
int y = feature.y; |
||||||
|
int n = feature.z; |
||||||
|
return channels_[n].at<int>(y, x); |
||||||
|
} |
||||||
|
|
||||||
|
void ACFFeatureEvaluatorImpl::evaluateAll(OutputArray feature_values) const |
||||||
|
{ |
||||||
|
Mat_<int> feature_vals(1, (int)features_.size()); |
||||||
|
for( int i = 0; i < (int)features_.size(); ++i ) |
||||||
|
{ |
||||||
|
feature_vals(0, i) = evaluate(i); |
||||||
|
} |
||||||
|
feature_values.setTo(feature_vals); |
||||||
|
} |
||||||
|
|
||||||
|
Ptr<ACFFeatureEvaluator> |
||||||
|
createACFFeatureEvaluator(const vector<Point3i>& features) |
||||||
|
{ |
||||||
|
return Ptr<ACFFeatureEvaluator>(new ACFFeatureEvaluatorImpl(features)); |
||||||
|
} |
||||||
|
|
||||||
|
vector<Point3i> generateFeatures(Size window_size, int count) |
||||||
|
{ |
||||||
|
CV_Assert(count > 0); |
||||||
|
int cur_count = 0; |
||||||
|
int max_count = window_size.width * window_size.height / 16; |
||||||
|
count = min(count, max_count); |
||||||
|
vector<Point3i> features; |
||||||
|
for( int x = 0; x < window_size.width / 4; ++x ) |
||||||
|
{ |
||||||
|
for( int y = 0; y < window_size.height / 4; ++y ) |
||||||
|
{ |
||||||
|
/* Assume there are 10 channel types */ |
||||||
|
for( int n = 0; n < 10; ++n ) |
||||||
|
{ |
||||||
|
features.push_back(Point3i(x, y, n)); |
||||||
|
if( (cur_count += 1) == count ) |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return features; |
||||||
|
} |
||||||
|
|
||||||
|
void computeChannels(cv::InputArray image, cv::OutputArrayOfArrays channels_) |
||||||
|
{ |
||||||
|
Mat src(image.getMat().rows, image.getMat().cols, CV_32FC3); |
||||||
|
image.getMat().convertTo(src, CV_32FC3, 1./255); |
||||||
|
|
||||||
|
Mat_<float> grad; |
||||||
|
Mat gray; |
||||||
|
cvtColor(src, gray, CV_RGB2GRAY); |
||||||
|
|
||||||
|
Mat_<float> row_der, col_der; |
||||||
|
Sobel(gray, row_der, CV_32F, 0, 1); |
||||||
|
Sobel(gray, col_der, CV_32F, 1, 0); |
||||||
|
|
||||||
|
magnitude(row_der, col_der, grad); |
||||||
|
|
||||||
|
Mat_<Vec6f> hist(grad.rows, grad.cols); |
||||||
|
const float to_deg = 180 / 3.1415926f; |
||||||
|
for (int row = 0; row < grad.rows; ++row) { |
||||||
|
for (int col = 0; col < grad.cols; ++col) { |
||||||
|
float angle = atan2(row_der(row, col), col_der(row, col)) * to_deg; |
||||||
|
if (angle < 0) |
||||||
|
angle += 180; |
||||||
|
int ind = (int)(angle / 30); |
||||||
|
hist(row, col)[ind] = grad(row, col); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
vector<Mat> channels; |
||||||
|
channels.push_back(gray); |
||||||
|
channels.push_back(grad); |
||||||
|
|
||||||
|
vector<Mat> hist_channels; |
||||||
|
split(hist, hist_channels); |
||||||
|
|
||||||
|
for( size_t i = 0; i < hist_channels.size(); ++i ) |
||||||
|
channels.push_back(hist_channels[i]); |
||||||
|
|
||||||
|
channels_.setTo(channels); |
||||||
|
} |
||||||
|
|
||||||
|
} /* namespace xobjdetect */ |
||||||
|
} /* namespace cv */ |
@ -0,0 +1,150 @@ |
|||||||
|
/*
|
||||||
|
|
||||||
|
By downloading, copying, installing or using the software you agree to this |
||||||
|
license. If you do not agree to this license, do not download, install, |
||||||
|
copy or use the software. |
||||||
|
|
||||||
|
|
||||||
|
License Agreement |
||||||
|
For Open Source Computer Vision Library |
||||||
|
(3-clause BSD License) |
||||||
|
|
||||||
|
Copyright (C) 2013, OpenCV Foundation, all rights reserved. |
||||||
|
Third party copyrights are property of their respective owners. |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, |
||||||
|
are permitted provided that the following conditions are met: |
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer. |
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer in the documentation |
||||||
|
and/or other materials provided with the distribution. |
||||||
|
|
||||||
|
* Neither the names of the copyright holders nor the names of the contributors |
||||||
|
may be used to endorse or promote products derived from this software |
||||||
|
without specific prior written permission. |
||||||
|
|
||||||
|
This software is provided by the copyright holders and contributors "as is" and |
||||||
|
any express or implied warranties, including, but not limited to, the implied |
||||||
|
warranties of merchantability and fitness for a particular purpose are |
||||||
|
disclaimed. In no event shall copyright holders or contributors be liable for |
||||||
|
any direct, indirect, incidental, special, exemplary, or consequential damages |
||||||
|
(including, but not limited to, procurement of substitute goods or services; |
||||||
|
loss of use, data, or profits; or business interruption) however caused |
||||||
|
and on any theory of liability, whether in contract, strict liability, |
||||||
|
or tort (including negligence or otherwise) arising in any way out of |
||||||
|
the use of this software, even if advised of the possibility of such damage. |
||||||
|
|
||||||
|
*/ |
||||||
|
|
||||||
|
#include "precomp.hpp" |
||||||
|
|
||||||
|
using std::vector; |
||||||
|
using std::string; |
||||||
|
|
||||||
|
using std::min; |
||||||
|
using std::max; |
||||||
|
|
||||||
|
namespace cv |
||||||
|
{ |
||||||
|
namespace xobjdetect |
||||||
|
{ |
||||||
|
|
||||||
|
static bool overlap(const Rect& r, const vector<Rect>& gt) |
||||||
|
{ |
||||||
|
for( size_t i = 0; i < gt.size(); ++i ) |
||||||
|
if( (r & gt[i]).area() ) |
||||||
|
return true; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
void ICFDetector::train(const vector<string>& image_filenames, |
||||||
|
const vector< vector<Rect> >& labelling, |
||||||
|
ICFDetectorParams params) |
||||||
|
{ |
||||||
|
Size model_size(params.model_n_cols, params.model_n_rows); |
||||||
|
|
||||||
|
vector<Mat> samples; /* positive samples + negative samples */ |
||||||
|
Mat sample, resized_sample; |
||||||
|
int pos_count = 0; |
||||||
|
for( size_t i = 0; i < image_filenames.size(); ++i, ++pos_count ) |
||||||
|
{ |
||||||
|
Mat img = imread(String(image_filenames[i].c_str())); |
||||||
|
for( size_t j = 0; j < labelling[i].size(); ++j ) |
||||||
|
{ |
||||||
|
Rect r = labelling[i][j]; |
||||||
|
if( r.x > img.cols || r.y > img.rows ) |
||||||
|
continue; |
||||||
|
|
||||||
|
sample = img.colRange(max(r.x, 0), min(r.width, img.cols)) |
||||||
|
.rowRange(max(r.y, 0), min(r.height, img.rows)); |
||||||
|
|
||||||
|
resize(sample, resized_sample, model_size); |
||||||
|
|
||||||
|
samples.push_back(resized_sample); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
int neg_count = 0; |
||||||
|
RNG rng; |
||||||
|
for( size_t i = 0; i < image_filenames.size(); ++i ) |
||||||
|
{ |
||||||
|
Mat img = imread(String(image_filenames[i].c_str())); |
||||||
|
for( int j = 0; j < (int)(pos_count / image_filenames.size() + 1); ) |
||||||
|
{ |
||||||
|
Rect r; |
||||||
|
r.x = rng.uniform(0, img.cols); |
||||||
|
r.width = rng.uniform(r.x + 1, img.cols); |
||||||
|
r.y = rng.uniform(0, img.rows); |
||||||
|
r.height = rng.uniform(r.y + 1, img.rows); |
||||||
|
|
||||||
|
if( !overlap(r, labelling[i]) ) |
||||||
|
{ |
||||||
|
sample = img.colRange(r.x, r.width).rowRange(r.y, r.height); |
||||||
|
//resize(sample, resized_sample);
|
||||||
|
samples.push_back(resized_sample); |
||||||
|
++neg_count; |
||||||
|
++j; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Mat_<int> labels(1, pos_count + neg_count); |
||||||
|
for( int i = 0; i < pos_count; ++i) |
||||||
|
labels(0, i) = 1; |
||||||
|
for( int i = pos_count; i < pos_count + neg_count; ++i ) |
||||||
|
labels(0, i) = -1; |
||||||
|
|
||||||
|
vector<Point3i> features = generateFeatures(model_size); |
||||||
|
Ptr<ACFFeatureEvaluator> feature_evaluator = createACFFeatureEvaluator(features); |
||||||
|
|
||||||
|
Mat_<int> data((int)features.size(), (int)samples.size()); |
||||||
|
Mat_<int> feature_col; |
||||||
|
|
||||||
|
vector<Mat> channels; |
||||||
|
for( int i = 0; i < (int)samples.size(); ++i ) |
||||||
|
{ |
||||||
|
computeChannels(samples[i], channels); |
||||||
|
feature_evaluator->setChannels(channels); |
||||||
|
feature_evaluator->evaluateAll(feature_col); |
||||||
|
for( int j = 0; j < feature_col.rows; ++j ) |
||||||
|
data(i, j) = feature_col(0, j); |
||||||
|
} |
||||||
|
|
||||||
|
WaldBoostParams wparams; |
||||||
|
wparams.weak_count = params.weak_count; |
||||||
|
wparams.alpha = 0.001f; |
||||||
|
|
||||||
|
Ptr<WaldBoost> waldboost = createWaldBoost(wparams); |
||||||
|
waldboost->train(data, labels); |
||||||
|
} |
||||||
|
|
||||||
|
bool ICFDetector::save(const string&) |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
} /* namespace xobjdetect */ |
||||||
|
} /* namespace cv */ |
@ -0,0 +1,56 @@ |
|||||||
|
/*
|
||||||
|
|
||||||
|
By downloading, copying, installing or using the software you agree to this |
||||||
|
license. If you do not agree to this license, do not download, install, |
||||||
|
copy or use the software. |
||||||
|
|
||||||
|
|
||||||
|
License Agreement |
||||||
|
For Open Source Computer Vision Library |
||||||
|
(3-clause BSD License) |
||||||
|
|
||||||
|
Copyright (C) 2013, OpenCV Foundation, all rights reserved. |
||||||
|
Third party copyrights are property of their respective owners. |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, |
||||||
|
are permitted provided that the following conditions are met: |
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer. |
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer in the documentation |
||||||
|
and/or other materials provided with the distribution. |
||||||
|
|
||||||
|
* Neither the names of the copyright holders nor the names of the contributors |
||||||
|
may be used to endorse or promote products derived from this software |
||||||
|
without specific prior written permission. |
||||||
|
|
||||||
|
This software is provided by the copyright holders and contributors "as is" and |
||||||
|
any express or implied warranties, including, but not limited to, the implied |
||||||
|
warranties of merchantability and fitness for a particular purpose are |
||||||
|
disclaimed. In no event shall copyright holders or contributors be liable for |
||||||
|
any direct, indirect, incidental, special, exemplary, or consequential damages |
||||||
|
(including, but not limited to, procurement of substitute goods or services; |
||||||
|
loss of use, data, or profits; or business interruption) however caused |
||||||
|
and on any theory of liability, whether in contract, strict liability, |
||||||
|
or tort (including negligence or otherwise) arising in any way out of |
||||||
|
the use of this software, even if advised of the possibility of such damage. |
||||||
|
|
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef __OPENCV_XOBJDETECT_PRECOMP_HPP__ |
||||||
|
#define __OPENCV_XOBJDETECT_PRECOMP_HPP__ |
||||||
|
|
||||||
|
#include <opencv2/xobjdetect.hpp> |
||||||
|
#include <opencv2/xobjdetect/private.hpp> |
||||||
|
|
||||||
|
#include <opencv2/imgproc.hpp> |
||||||
|
#include <opencv2/imgproc/types_c.h> |
||||||
|
|
||||||
|
#include <opencv2/highgui.hpp> |
||||||
|
|
||||||
|
#include <algorithm> |
||||||
|
#include <cmath> |
||||||
|
|
||||||
|
#endif /* __OPENCV_XOBJDETECT_PRECOMP_HPP__ */ |
@ -0,0 +1,203 @@ |
|||||||
|
/*
|
||||||
|
|
||||||
|
By downloading, copying, installing or using the software you agree to this |
||||||
|
license. If you do not agree to this license, do not download, install, |
||||||
|
copy or use the software. |
||||||
|
|
||||||
|
|
||||||
|
License Agreement |
||||||
|
For Open Source Computer Vision Library |
||||||
|
(3-clause BSD License) |
||||||
|
|
||||||
|
Copyright (C) 2013, OpenCV Foundation, all rights reserved. |
||||||
|
Third party copyrights are property of their respective owners. |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, |
||||||
|
are permitted provided that the following conditions are met: |
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer. |
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer in the documentation |
||||||
|
and/or other materials provided with the distribution. |
||||||
|
|
||||||
|
* Neither the names of the copyright holders nor the names of the contributors |
||||||
|
may be used to endorse or promote products derived from this software |
||||||
|
without specific prior written permission. |
||||||
|
|
||||||
|
This software is provided by the copyright holders and contributors "as is" and |
||||||
|
any express or implied warranties, including, but not limited to, the implied |
||||||
|
warranties of merchantability and fitness for a particular purpose are |
||||||
|
disclaimed. In no event shall copyright holders or contributors be liable for |
||||||
|
any direct, indirect, incidental, special, exemplary, or consequential damages |
||||||
|
(including, but not limited to, procurement of substitute goods or services; |
||||||
|
loss of use, data, or profits; or business interruption) however caused |
||||||
|
and on any theory of liability, whether in contract, strict liability, |
||||||
|
or tort (including negligence or otherwise) arising in any way out of |
||||||
|
the use of this software, even if advised of the possibility of such damage. |
||||||
|
|
||||||
|
*/ |
||||||
|
|
||||||
|
#include "precomp.hpp" |
||||||
|
|
||||||
|
namespace cv |
||||||
|
{ |
||||||
|
namespace xobjdetect |
||||||
|
{ |
||||||
|
|
||||||
|
/* Cumulative sum by rows */ |
||||||
|
static void cumsum(const Mat_<float>& src, Mat_<float> dst) |
||||||
|
{ |
||||||
|
CV_Assert(src.cols > 0); |
||||||
|
|
||||||
|
for( int row = 0; row < src.rows; ++row ) |
||||||
|
{ |
||||||
|
dst(row, 0) = src(row, 0); |
||||||
|
for( int col = 1; col < src.cols; ++col ) |
||||||
|
{ |
||||||
|
dst(row, col) = dst(row, col - 1) + src(row, col); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
int Stump::train(const Mat& data, const Mat& labels, const Mat& weights) |
||||||
|
{ |
||||||
|
CV_Assert(labels.rows == 1 && labels.cols == data.cols); |
||||||
|
CV_Assert(weights.rows == 1 && weights.cols == data.cols); |
||||||
|
/* Assert that data and labels have int type */ |
||||||
|
/* Assert that weights have float type */ |
||||||
|
|
||||||
|
|
||||||
|
/* Prepare labels for each feature rearranged according to sorted order */ |
||||||
|
Mat sorted_labels(data.rows, data.cols, labels.type()); |
||||||
|
Mat sorted_weights(data.rows, data.cols, weights.type()); |
||||||
|
Mat indices; |
||||||
|
sortIdx(data, indices, cv::SORT_EVERY_ROW | cv::SORT_ASCENDING); |
||||||
|
for( int row = 0; row < indices.rows; ++row ) |
||||||
|
{ |
||||||
|
for( int col = 0; col < indices.cols; ++col ) |
||||||
|
{ |
||||||
|
sorted_labels.at<int>(row, col) = |
||||||
|
labels.at<int>(0, indices.at<int>(row, col)); |
||||||
|
sorted_weights.at<float>(row, col) = |
||||||
|
weights.at<float>(0, indices.at<int>(row, col)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Sort feature values */ |
||||||
|
Mat sorted_data(data.rows, data.cols, data.type()); |
||||||
|
sort(data, sorted_data, cv::SORT_EVERY_ROW | cv::SORT_ASCENDING); |
||||||
|
|
||||||
|
/* Split positive and negative weights */ |
||||||
|
Mat pos_weights = Mat::zeros(sorted_weights.rows, sorted_weights.cols, |
||||||
|
sorted_weights.type()); |
||||||
|
Mat neg_weights = Mat::zeros(sorted_weights.rows, sorted_weights.cols, |
||||||
|
sorted_weights.type()); |
||||||
|
for( int row = 0; row < data.rows; ++row ) |
||||||
|
{ |
||||||
|
for( int col = 0; col < data.cols; ++col ) |
||||||
|
{ |
||||||
|
if( sorted_labels.at<int>(row, col) == +1 ) |
||||||
|
{ |
||||||
|
pos_weights.at<float>(row, col) = |
||||||
|
sorted_weights.at<float>(row, col); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
neg_weights.at<float>(row, col) = |
||||||
|
sorted_weights.at<float>(row, col); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Compute cumulative sums for fast stump error computation */ |
||||||
|
Mat pos_cum_weights = Mat::zeros(sorted_weights.rows, sorted_weights.cols, |
||||||
|
sorted_weights.type()); |
||||||
|
Mat neg_cum_weights = Mat::zeros(sorted_weights.rows, sorted_weights.cols, |
||||||
|
sorted_weights.type()); |
||||||
|
cumsum(pos_weights, pos_cum_weights); |
||||||
|
cumsum(neg_weights, neg_cum_weights); |
||||||
|
|
||||||
|
/* Compute total weights of positive and negative samples */ |
||||||
|
float pos_total_weight = pos_cum_weights.at<float>(0, weights.cols - 1); |
||||||
|
float neg_total_weight = neg_cum_weights.at<float>(0, weights.cols - 1); |
||||||
|
|
||||||
|
|
||||||
|
float eps = 1.0f / (4 * labels.cols); |
||||||
|
|
||||||
|
/* Compute minimal error */ |
||||||
|
float min_err = FLT_MAX; |
||||||
|
int min_row = -1; |
||||||
|
int min_col = -1; |
||||||
|
int min_polarity = 0; |
||||||
|
float min_pos_value = 1, min_neg_value = -1; |
||||||
|
|
||||||
|
for( int row = 0; row < sorted_weights.rows; ++row ) |
||||||
|
{ |
||||||
|
for( int col = 0; col < sorted_weights.cols - 1; ++col ) |
||||||
|
{ |
||||||
|
float err, h_pos, h_neg; |
||||||
|
|
||||||
|
// Direct polarity
|
||||||
|
|
||||||
|
float pos_wrong = pos_cum_weights.at<float>(row, col); |
||||||
|
float pos_right = pos_total_weight - pos_wrong; |
||||||
|
|
||||||
|
float neg_right = neg_cum_weights.at<float>(row, col); |
||||||
|
float neg_wrong = neg_total_weight - neg_right; |
||||||
|
|
||||||
|
h_pos = (float)(.5 * log((pos_right + eps) / (pos_wrong + eps))); |
||||||
|
h_neg = (float)(.5 * log((neg_wrong + eps) / (neg_right + eps))); |
||||||
|
|
||||||
|
err = sqrt(pos_right * neg_wrong) + sqrt(pos_wrong * neg_right); |
||||||
|
|
||||||
|
if( err < min_err ) |
||||||
|
{ |
||||||
|
min_err = err; |
||||||
|
min_row = row; |
||||||
|
min_col = col; |
||||||
|
min_polarity = +1; |
||||||
|
min_pos_value = h_pos; |
||||||
|
min_neg_value = h_neg; |
||||||
|
} |
||||||
|
|
||||||
|
// Opposite polarity
|
||||||
|
swap(pos_right, pos_wrong); |
||||||
|
swap(neg_right, neg_wrong); |
||||||
|
|
||||||
|
h_pos = -h_pos; |
||||||
|
h_neg = -h_neg; |
||||||
|
|
||||||
|
err = sqrt(pos_right * neg_wrong) + sqrt(pos_wrong * neg_right); |
||||||
|
|
||||||
|
|
||||||
|
if( err < min_err ) |
||||||
|
{ |
||||||
|
min_err = err; |
||||||
|
min_row = row; |
||||||
|
min_col = col; |
||||||
|
min_polarity = -1; |
||||||
|
min_pos_value = h_pos; |
||||||
|
min_neg_value = h_neg; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Compute threshold, store found values in fields */ |
||||||
|
threshold_ = ( sorted_data.at<int>(min_row, min_col) + |
||||||
|
sorted_data.at<int>(min_row, min_col + 1) ) / 2; |
||||||
|
polarity_ = min_polarity; |
||||||
|
pos_value_ = min_pos_value; |
||||||
|
neg_value_ = min_neg_value; |
||||||
|
|
||||||
|
return min_row; |
||||||
|
} |
||||||
|
|
||||||
|
float Stump::predict(int value) const |
||||||
|
{ |
||||||
|
return polarity_ * (value - threshold_) > 0 ? pos_value_ : neg_value_; |
||||||
|
} |
||||||
|
|
||||||
|
} /* namespace xobjdetect */ |
||||||
|
} /* namespace cv */ |
@ -0,0 +1,187 @@ |
|||||||
|
/*
|
||||||
|
|
||||||
|
By downloading, copying, installing or using the software you agree to this |
||||||
|
license. If you do not agree to this license, do not download, install, |
||||||
|
copy or use the software. |
||||||
|
|
||||||
|
|
||||||
|
License Agreement |
||||||
|
For Open Source Computer Vision Library |
||||||
|
(3-clause BSD License) |
||||||
|
|
||||||
|
Copyright (C) 2013, OpenCV Foundation, all rights reserved. |
||||||
|
Third party copyrights are property of their respective owners. |
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, |
||||||
|
are permitted provided that the following conditions are met: |
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer. |
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, |
||||||
|
this list of conditions and the following disclaimer in the documentation |
||||||
|
and/or other materials provided with the distribution. |
||||||
|
|
||||||
|
* Neither the names of the copyright holders nor the names of the contributors |
||||||
|
may be used to endorse or promote products derived from this software |
||||||
|
without specific prior written permission. |
||||||
|
|
||||||
|
This software is provided by the copyright holders and contributors "as is" and |
||||||
|
any express or implied warranties, including, but not limited to, the implied |
||||||
|
warranties of merchantability and fitness for a particular purpose are |
||||||
|
disclaimed. In no event shall copyright holders or contributors be liable for |
||||||
|
any direct, indirect, incidental, special, exemplary, or consequential damages |
||||||
|
(including, but not limited to, procurement of substitute goods or services; |
||||||
|
loss of use, data, or profits; or business interruption) however caused |
||||||
|
and on any theory of liability, whether in contract, strict liability, |
||||||
|
or tort (including negligence or otherwise) arising in any way out of |
||||||
|
the use of this software, even if advised of the possibility of such damage. |
||||||
|
|
||||||
|
*/ |
||||||
|
|
||||||
|
#include "precomp.hpp" |
||||||
|
|
||||||
|
using std::swap; |
||||||
|
|
||||||
|
using std::vector; |
||||||
|
|
||||||
|
namespace cv |
||||||
|
{ |
||||||
|
namespace xobjdetect |
||||||
|
{ |
||||||
|
|
||||||
|
class WaldBoostImpl : public WaldBoost |
||||||
|
{ |
||||||
|
public: |
||||||
|
/* Initialize WaldBoost cascade with default of specified parameters */ |
||||||
|
WaldBoostImpl(const WaldBoostParams& params): |
||||||
|
params_(params) |
||||||
|
{} |
||||||
|
|
||||||
|
virtual std::vector<int> train(const Mat& data, |
||||||
|
const Mat& labels); |
||||||
|
|
||||||
|
virtual float predict( |
||||||
|
const Ptr<ACFFeatureEvaluator>& feature_evaluator) const; |
||||||
|
|
||||||
|
private: |
||||||
|
/* Parameters for cascade training */ |
||||||
|
WaldBoostParams params_; |
||||||
|
/* Stumps in cascade */ |
||||||
|
std::vector<Stump> stumps_; |
||||||
|
/* Rejection thresholds for linear combination at every stump evaluation */ |
||||||
|
std::vector<float> thresholds_; |
||||||
|
}; |
||||||
|
|
||||||
|
vector<int> WaldBoostImpl::train(const Mat& data, const Mat& labels) |
||||||
|
{ |
||||||
|
CV_Assert(labels.rows == 1 && labels.cols == data.cols); |
||||||
|
|
||||||
|
int pos_count = 0, neg_count = 0; |
||||||
|
for( int col = 0; col < labels.cols; ++col ) |
||||||
|
{ |
||||||
|
if( labels.at<int>(0, col) == +1 ) |
||||||
|
pos_count += 1; |
||||||
|
else |
||||||
|
neg_count += 1; |
||||||
|
} |
||||||
|
|
||||||
|
Mat_<float> weights(labels.rows, labels.cols); |
||||||
|
float pos_weight = 1.0f / (2 * pos_count); |
||||||
|
float neg_weight = 1.0f / (2 * neg_count); |
||||||
|
for( int col = 0; col < weights.cols; ++col ) |
||||||
|
{ |
||||||
|
if( labels.at<int>(0, col) == +1 ) |
||||||
|
weights.at<float>(0, col) = pos_weight; |
||||||
|
else |
||||||
|
weights.at<float>(0, col) = neg_weight; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
vector<int> feature_indices; |
||||||
|
Mat_<float> trace = Mat_<float>::zeros(labels.rows, labels.cols); |
||||||
|
stumps_.clear(); |
||||||
|
thresholds_.clear(); |
||||||
|
for( int i = 0; i < params_.weak_count; ++i) |
||||||
|
{ |
||||||
|
Stump s; |
||||||
|
int feature_ind = s.train(data, labels, weights); |
||||||
|
stumps_.push_back(s); |
||||||
|
feature_indices.push_back(feature_ind); |
||||||
|
|
||||||
|
// Recompute weights
|
||||||
|
for( int col = 0; col < weights.cols; ++col ) |
||||||
|
{ |
||||||
|
float h = s.predict(data.at<int>(feature_ind, col)); |
||||||
|
trace(0, col) += h; |
||||||
|
int label = labels.at<int>(0, col); |
||||||
|
weights.at<float>(0, col) *= exp(-label * h); |
||||||
|
} |
||||||
|
|
||||||
|
// Normalize weights
|
||||||
|
float z = (float)sum(weights)[0]; |
||||||
|
for( int col = 0; col < weights.cols; ++col) |
||||||
|
{ |
||||||
|
weights.at<float>(0, col) /= z; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Sort trace
|
||||||
|
Mat indices; |
||||||
|
sortIdx(trace, indices, cv::SORT_EVERY_ROW | cv::SORT_ASCENDING); |
||||||
|
Mat new_weights = Mat_<float>::zeros(weights.rows, weights.cols); |
||||||
|
Mat new_labels = Mat_<int>::zeros(labels.rows, labels.cols); |
||||||
|
Mat new_trace; |
||||||
|
for( int col = 0; col < new_weights.cols; ++col ) |
||||||
|
{ |
||||||
|
new_weights.at<float>(0, col) = |
||||||
|
weights.at<float>(0, indices.at<int>(0, col)); |
||||||
|
new_labels.at<int>(0, col) = |
||||||
|
labels.at<int>(0, indices.at<int>(0, col)); |
||||||
|
} |
||||||
|
sort(trace, new_trace, cv::SORT_EVERY_ROW | cv::SORT_ASCENDING); |
||||||
|
|
||||||
|
|
||||||
|
// Compute threshold for trace
|
||||||
|
int col = 0; |
||||||
|
for( int pos_i = 0; |
||||||
|
pos_i < pos_count * params_.alpha && col < weights.cols; |
||||||
|
++col ) |
||||||
|
{ |
||||||
|
if( labels.at<int>(0, col) == +1 ) |
||||||
|
++pos_i; |
||||||
|
} |
||||||
|
|
||||||
|
thresholds_.push_back(new_trace.at<float>(0, col)); |
||||||
|
|
||||||
|
// Drop samples below threshold
|
||||||
|
new_trace.colRange(col, new_trace.cols).copyTo(trace); |
||||||
|
new_weights.colRange(col, new_weights.cols).copyTo(weights); |
||||||
|
new_labels.colRange(col, new_labels.cols).copyTo(labels); |
||||||
|
} |
||||||
|
return feature_indices; |
||||||
|
} |
||||||
|
|
||||||
|
float WaldBoostImpl::predict( |
||||||
|
const Ptr<ACFFeatureEvaluator>& feature_evaluator) const |
||||||
|
{ |
||||||
|
float trace = 0; |
||||||
|
for( size_t i = 0; i < stumps_.size(); ++i ) |
||||||
|
{ |
||||||
|
int value = feature_evaluator->evaluate(i); |
||||||
|
trace += stumps_[i].predict(value); |
||||||
|
if( trace < thresholds_[i] ) |
||||||
|
return -1; |
||||||
|
} |
||||||
|
return trace; |
||||||
|
} |
||||||
|
|
||||||
|
Ptr<WaldBoost> |
||||||
|
createWaldBoost(const WaldBoostParams& params) |
||||||
|
{ |
||||||
|
return Ptr<WaldBoost>(new WaldBoostImpl(params)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xobjdetect */ |
||||||
|
} /* namespace cv */ |
Loading…
Reference in new issue