Merge pull request #291 from shahurik:master
commit
cdbe335258
26 changed files with 1447 additions and 1844 deletions
@ -1,8 +0,0 @@ |
|||||||
if(IOS) |
|
||||||
ocv_module_disable(adas) |
|
||||||
endif() |
|
||||||
|
|
||||||
set(the_description "Automatic driver assistance algorithms") |
|
||||||
ocv_define_module(adas opencv_xobjdetect) |
|
||||||
|
|
||||||
add_subdirectory(tools) |
|
@ -1,2 +0,0 @@ |
|||||||
ADAS: Advanced Driver Assistance Systems module with Forward Collision Warning |
|
||||||
============================================================================== |
|
@ -1,2 +0,0 @@ |
|||||||
add_subdirectory(fcw_train) |
|
||||||
add_subdirectory(fcw_detect) |
|
@ -1,35 +0,0 @@ |
|||||||
set(name fcw_detect) |
|
||||||
set(the_target opencv_${name}) |
|
||||||
|
|
||||||
set(OPENCV_${the_target}_DEPS opencv_core opencv_imgcodecs opencv_videoio |
|
||||||
opencv_highgui 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_recurse(${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} OPTIONAL RUNTIME DESTINATION bin COMPONENT main) |
|
@ -1,132 +0,0 @@ |
|||||||
#include <string> |
|
||||||
using std::string; |
|
||||||
|
|
||||||
#include <vector> |
|
||||||
using std::vector; |
|
||||||
|
|
||||||
#include <iostream> |
|
||||||
using std::cerr; |
|
||||||
using std::endl; |
|
||||||
|
|
||||||
#include <opencv2/core.hpp> |
|
||||||
using cv::Rect; |
|
||||||
using cv::Size; |
|
||||||
using cv::Mat; |
|
||||||
using cv::Mat_; |
|
||||||
using cv::Vec3b; |
|
||||||
|
|
||||||
#include <opencv2/highgui.hpp> |
|
||||||
using cv::imread; |
|
||||||
using cv::imwrite; |
|
||||||
|
|
||||||
#include <opencv2/core/utility.hpp> |
|
||||||
using cv::CommandLineParser; |
|
||||||
using cv::FileStorage; |
|
||||||
|
|
||||||
#include <opencv2/xobjdetect.hpp> |
|
||||||
using cv::xobjdetect::ICFDetector; |
|
||||||
|
|
||||||
static Mat visualize(const Mat &image, const vector<Rect> &objects) |
|
||||||
{ |
|
||||||
CV_Assert(image.type() == CV_8UC3); |
|
||||||
Mat_<Vec3b> img = image.clone(); |
|
||||||
for( size_t j = 0; j < objects.size(); ++j ) |
|
||||||
{ |
|
||||||
Rect obj = objects[j]; |
|
||||||
int x = obj.x; |
|
||||||
int y = obj.y; |
|
||||||
int width = obj.width; |
|
||||||
int height = obj.height; |
|
||||||
for( int i = y; i <= y + height; ++i ) { |
|
||||||
img(i, x) = Vec3b(255, 0, 0); |
|
||||||
img(i, x + width) = Vec3b(255, 0, 0); |
|
||||||
} |
|
||||||
for( int i = x; i <= x + width; ++i) { |
|
||||||
img(y, i) = Vec3b(255, 0, 0); |
|
||||||
img(y + height, i) = Vec3b(255, 0, 0); |
|
||||||
} |
|
||||||
} |
|
||||||
return img; |
|
||||||
} |
|
||||||
static bool read_window_size(const 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; |
|
||||||
} |
|
||||||
|
|
||||||
int main(int argc, char *argv[]) |
|
||||||
{ |
|
||||||
const string keys = |
|
||||||
"{help | | print this message}" |
|
||||||
"{model_filename | model.xml | filename for reading model}" |
|
||||||
"{image_path | test.png | path to image for detection}" |
|
||||||
"{out_image_path | out.png | path to image for output}" |
|
||||||
"{threshold | 0.0 | threshold for cascade}" |
|
||||||
"{step | 8 | sliding window step}" |
|
||||||
"{min_window_size | 40x40 | min window size in pixels}" |
|
||||||
"{max_window_size | 300x300 | max window size in pixels}" |
|
||||||
"{is_grayscale | false | read the image as grayscale}" |
|
||||||
; |
|
||||||
|
|
||||||
CommandLineParser parser(argc, argv, keys); |
|
||||||
parser.about("FCW detection"); |
|
||||||
|
|
||||||
if( parser.has("help") || argc == 1) |
|
||||||
{ |
|
||||||
parser.printMessage(); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
string model_filename = parser.get<string>("model_filename"); |
|
||||||
string image_path = parser.get<string>("image_path"); |
|
||||||
string out_image_path = parser.get<string>("out_image_path"); |
|
||||||
bool is_grayscale = parser.get<bool>("is_grayscale"); |
|
||||||
float threshold = parser.get<float>("threshold"); |
|
||||||
int step = parser.get<int>("step"); |
|
||||||
|
|
||||||
int min_rows, min_cols, max_rows, max_cols; |
|
||||||
string min_window_size = parser.get<string>("min_window_size"); |
|
||||||
if( !read_window_size(min_window_size.c_str(), &min_rows, |
|
||||||
&min_cols) ) |
|
||||||
{ |
|
||||||
cerr << "Error reading min window size from `" << min_window_size << "`" << endl; |
|
||||||
return 1; |
|
||||||
} |
|
||||||
string max_window_size = parser.get<string>("max_window_size"); |
|
||||||
if( !read_window_size(max_window_size.c_str(), &max_rows, |
|
||||||
&max_cols) ) |
|
||||||
{ |
|
||||||
cerr << "Error reading max window size from `" << max_window_size << "`" << endl; |
|
||||||
return 1; |
|
||||||
} |
|
||||||
|
|
||||||
int color; |
|
||||||
if(is_grayscale == false) |
|
||||||
color = cv::IMREAD_COLOR; |
|
||||||
else |
|
||||||
color = cv::IMREAD_GRAYSCALE; |
|
||||||
|
|
||||||
|
|
||||||
if( !parser.check() ) |
|
||||||
{ |
|
||||||
parser.printErrors(); |
|
||||||
return 1; |
|
||||||
} |
|
||||||
|
|
||||||
ICFDetector detector; |
|
||||||
FileStorage fs(model_filename, FileStorage::READ); |
|
||||||
detector.read(fs["icfdetector"]); |
|
||||||
fs.release(); |
|
||||||
vector<Rect> objects; |
|
||||||
Mat img = imread(image_path, color); |
|
||||||
std::vector<float> values; |
|
||||||
detector.detect(img, objects, 1.1f, Size(min_cols, min_rows), Size(max_cols, max_rows), threshold, step, values); |
|
||||||
imwrite(out_image_path, visualize(img, objects)); |
|
||||||
|
|
||||||
|
|
||||||
} |
|
@ -1,187 +0,0 @@ |
|||||||
#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; |
|
||||||
using cv::Size; |
|
||||||
#include <opencv2/highgui.hpp> |
|
||||||
using cv::imread; |
|
||||||
#include <opencv2/core/utility.hpp> |
|
||||||
using cv::CommandLineParser; |
|
||||||
using cv::FileStorage; |
|
||||||
#include <opencv2/core/utility.hpp> |
|
||||||
|
|
||||||
#include <ctime> // std::time |
|
||||||
#include <cstdlib> // std::rand, std::srand |
|
||||||
|
|
||||||
#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_model_size(const 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 int randomPred (int i) { return std::rand()%i;} |
|
||||||
|
|
||||||
int main(int argc, char *argv[]) |
|
||||||
{ |
|
||||||
|
|
||||||
const string keys = |
|
||||||
"{help | | print this message}" |
|
||||||
"{pos_path | pos | path to training object samples}" |
|
||||||
"{bg_path | bg | path to background images}" |
|
||||||
"{bg_per_image | 5 | number of windows to sample per bg image}" |
|
||||||
"{feature_count | 10000 | number of features to generate}" |
|
||||||
"{weak_count | 100 | number of weak classifiers in cascade}" |
|
||||||
"{model_size | 40x40 | model size in pixels}" |
|
||||||
"{model_filename | model.xml | filename for saving model}" |
|
||||||
"{features_type | icf | features type, \"icf\" or \"acf\"}" |
|
||||||
"{alpha | 0.02 | alpha value}" |
|
||||||
"{is_grayscale | false | read the image as grayscale}" |
|
||||||
"{use_fast_log | false | use fast log function}" |
|
||||||
"{limit_ps | -1 | limit to positive samples (-1 means all)}" |
|
||||||
"{limit_bg | -1 | limit to negative samples (-1 means all)}" |
|
||||||
; |
|
||||||
|
|
||||||
|
|
||||||
CommandLineParser parser(argc, argv, keys); |
|
||||||
parser.about("FCW trainer"); |
|
||||||
|
|
||||||
if( parser.has("help") || argc == 1) |
|
||||||
{ |
|
||||||
parser.printMessage(); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
string pos_path = parser.get<string>("pos_path"); |
|
||||||
string bg_path = parser.get<string>("bg_path"); |
|
||||||
string model_filename = parser.get<string>("model_filename"); |
|
||||||
|
|
||||||
ICFDetectorParams params; |
|
||||||
params.feature_count = parser.get<int>("feature_count"); |
|
||||||
params.weak_count = parser.get<int>("weak_count"); |
|
||||||
params.bg_per_image = parser.get<int>("bg_per_image"); |
|
||||||
params.features_type = parser.get<string>("features_type"); |
|
||||||
params.alpha = parser.get<float>("alpha"); |
|
||||||
params.is_grayscale = parser.get<bool>("is_grayscale"); |
|
||||||
params.use_fast_log = parser.get<bool>("use_fast_log"); |
|
||||||
|
|
||||||
int limit_ps = parser.get<int>("limit_ps"); |
|
||||||
int limit_bg = parser.get<int>("limit_bg");
|
|
||||||
|
|
||||||
string model_size = parser.get<string>("model_size"); |
|
||||||
if( !read_model_size(model_size.c_str(), ¶ms.model_n_rows, |
|
||||||
¶ms.model_n_cols) ) |
|
||||||
{ |
|
||||||
cerr << "Error reading model size from `" << model_size << "`" << endl; |
|
||||||
return 1; |
|
||||||
} |
|
||||||
|
|
||||||
if( params.feature_count <= 0 ) |
|
||||||
{ |
|
||||||
cerr << "feature_count must be positive number" << endl; |
|
||||||
return 1; |
|
||||||
} |
|
||||||
|
|
||||||
if( params.weak_count <= 0 ) |
|
||||||
{ |
|
||||||
cerr << "weak_count must be positive number" << endl; |
|
||||||
return 1; |
|
||||||
} |
|
||||||
|
|
||||||
if( params.features_type != "icf" && params.features_type != "acf" ) |
|
||||||
{ |
|
||||||
cerr << "features_type must be \"icf\" or \"acf\"" << endl; |
|
||||||
return 1; |
|
||||||
} |
|
||||||
if( params.alpha <= 0 ) |
|
||||||
{ |
|
||||||
cerr << "alpha must be positive float number" << endl; |
|
||||||
return 1; |
|
||||||
} |
|
||||||
if( !parser.check() ) |
|
||||||
{ |
|
||||||
parser.printErrors(); |
|
||||||
return 1; |
|
||||||
} |
|
||||||
|
|
||||||
std::vector<cv::String> pos_filenames; |
|
||||||
glob(pos_path, pos_filenames); |
|
||||||
|
|
||||||
std::vector<cv::String> bg_filenames; |
|
||||||
glob(bg_path, bg_filenames); |
|
||||||
|
|
||||||
if(limit_ps != -1 && (int)pos_filenames.size() > limit_ps) |
|
||||||
pos_filenames.erase(pos_filenames.begin()+limit_ps, pos_filenames.end()); |
|
||||||
if(limit_bg != -1 && (int)bg_filenames.size() > limit_bg) |
|
||||||
bg_filenames.erase(bg_filenames.begin()+limit_bg, bg_filenames.end()); |
|
||||||
|
|
||||||
//random pick input images
|
|
||||||
bool random_shuffle = false; |
|
||||||
if(random_shuffle) |
|
||||||
{ |
|
||||||
std::srand ( unsigned ( std::time(0) ) ); |
|
||||||
std::random_shuffle ( pos_filenames.begin(), pos_filenames.end(), randomPred ); |
|
||||||
std::random_shuffle ( bg_filenames.begin(), bg_filenames.end(), randomPred ); |
|
||||||
} |
|
||||||
|
|
||||||
int samples_size = (int)((params.bg_per_image * bg_filenames.size()) + pos_filenames.size()); |
|
||||||
int features_size = params.feature_count; |
|
||||||
int max_features_allowed = (int)(INT_MAX/(sizeof(int)* samples_size)); |
|
||||||
int max_samples_allowed = (int)(INT_MAX/(sizeof(int)* features_size)); |
|
||||||
int total_samples = (int)((params.bg_per_image * bg_filenames.size()) + pos_filenames.size()); |
|
||||||
|
|
||||||
|
|
||||||
if(total_samples >max_samples_allowed) |
|
||||||
{ |
|
||||||
CV_Error_(1, ("exceeded maximum number of samples. Maximum number of samples with %d features is %d, you have %d (%d positive samples + (%d bg * %d bg_per_image))\n",features_size,max_samples_allowed,total_samples,pos_filenames.size(),bg_filenames.size(),params.bg_per_image )); |
|
||||||
} |
|
||||||
|
|
||||||
if(params.feature_count >max_features_allowed) |
|
||||||
{ |
|
||||||
CV_Error_(1, ("exceeded maximum number of features. Maximum number of features with %d samples is %d, you have %d\n",samples_size,max_features_allowed, features_size )); |
|
||||||
} |
|
||||||
|
|
||||||
std::cout<<pos_filenames.size()<<std::endl; |
|
||||||
std::cout<<bg_filenames.size()<<std::endl; |
|
||||||
|
|
||||||
ICFDetector detector;
|
|
||||||
|
|
||||||
|
|
||||||
detector.train(pos_filenames, bg_filenames, params); |
|
||||||
|
|
||||||
FileStorage fs(model_filename, FileStorage::WRITE); |
|
||||||
fs << "icfdetector"; |
|
||||||
detector.write(fs); |
|
||||||
fs.release(); |
|
||||||
} |
|
@ -1,2 +1,3 @@ |
|||||||
set(the_description "Object detection algorithms") |
set(the_description "Object detection algorithms") |
||||||
ocv_define_module(xobjdetect opencv_core opencv_imgproc opencv_highgui WRAP python) |
ocv_define_module(xobjdetect opencv_core opencv_imgproc opencv_highgui opencv_objdetect WRAP python) |
||||||
|
add_subdirectory(tools) |
||||||
|
@ -1,88 +0,0 @@ |
|||||||
#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 |
|
||||||
|
|
||||||
visited_features: vector of already visited features (ignored in successive calls) |
|
||||||
|
|
||||||
Returns chosen feature index. Feature enumeration starts from 0 |
|
||||||
*/ |
|
||||||
int train(const Mat& data, const Mat& labels, const Mat& weights, const std::vector<int>& visited_features, bool use_fast_log = false); |
|
||||||
|
|
||||||
/* 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; |
|
||||||
|
|
||||||
/* Write stump in FileStorage */ |
|
||||||
void write(FileStorage& fs) const |
|
||||||
{ |
|
||||||
fs << "{" |
|
||||||
<< "threshold" << threshold_ |
|
||||||
<< "polarity" << polarity_ |
|
||||||
<< "pos_value" << pos_value_ |
|
||||||
<< "neg_value" << neg_value_ |
|
||||||
<< "}"; |
|
||||||
} |
|
||||||
|
|
||||||
/* Read stump */ |
|
||||||
void read(const FileNode& node) |
|
||||||
{ |
|
||||||
threshold_ = (int)node["threshold"]; |
|
||||||
polarity_ = (int)node["polarity"]; |
|
||||||
pos_value_ = (float)node["pos_value"]; |
|
||||||
neg_value_ = (float)node["neg_value"]; |
|
||||||
} |
|
||||||
|
|
||||||
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_; |
|
||||||
}; |
|
||||||
|
|
||||||
void read(const FileNode& node, Stump& s, const Stump& default_value=Stump()); |
|
||||||
|
|
||||||
void write(FileStorage& fs, String&, const Stump& s); |
|
||||||
|
|
||||||
} /* namespace xobjdetect */ |
|
||||||
} /* namespace cv */ |
|
||||||
|
|
||||||
#endif // __OPENCV_XOBJDETECT_PRIVATE_HPP__
|
|
@ -1,344 +0,0 @@ |
|||||||
/*
|
|
||||||
|
|
||||||
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 |
|
||||||
{ |
|
||||||
|
|
||||||
static bool isNull(const Mat_<int> &m) |
|
||||||
{ |
|
||||||
bool null_data = true; |
|
||||||
for( int row = 0; row < m.rows; ++row ) |
|
||||||
{ |
|
||||||
for( int col = 0; col < m.cols; ++col ) |
|
||||||
if( m.at<int>(row, col) ) |
|
||||||
null_data = false; |
|
||||||
} |
|
||||||
return null_data; |
|
||||||
} |
|
||||||
|
|
||||||
class FeatureEvaluatorImpl : public FeatureEvaluator |
|
||||||
{ |
|
||||||
public: |
|
||||||
FeatureEvaluatorImpl(const vector<vector<int> >& features): |
|
||||||
features_(features), channels_(), position_() |
|
||||||
{ |
|
||||||
CV_Assert(features.size() > 0); |
|
||||||
} |
|
||||||
|
|
||||||
virtual void assertChannels() |
|
||||||
{ |
|
||||||
bool null_data = true; |
|
||||||
for( size_t i = 0; i < channels_.size(); ++i ) |
|
||||||
null_data &= isNull(channels_[i]); |
|
||||||
CV_Assert(!null_data); |
|
||||||
} |
|
||||||
|
|
||||||
virtual void 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.assign(feature_vals); |
|
||||||
} |
|
||||||
|
|
||||||
protected: |
|
||||||
/* Features to evaluate */ |
|
||||||
vector<vector<int> > features_; |
|
||||||
/* Channels for feature evaluation */ |
|
||||||
std::vector<Mat> channels_; |
|
||||||
/* Channels window position */ |
|
||||||
Size position_; |
|
||||||
}; |
|
||||||
|
|
||||||
class ICFFeatureEvaluatorImpl : public FeatureEvaluatorImpl |
|
||||||
{ |
|
||||||
public: |
|
||||||
ICFFeatureEvaluatorImpl(const vector<vector<int> >& features): |
|
||||||
FeatureEvaluatorImpl(features) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
virtual void setChannels(InputArrayOfArrays channels); |
|
||||||
virtual void setPosition(Size position); |
|
||||||
virtual int evaluate(size_t feature_ind) const; |
|
||||||
}; |
|
||||||
|
|
||||||
void ICFFeatureEvaluatorImpl::setChannels(InputArrayOfArrays channels) |
|
||||||
{ |
|
||||||
channels_.clear(); |
|
||||||
vector<Mat> ch; |
|
||||||
channels.getMatVector(ch); |
|
||||||
|
|
||||||
for( size_t i = 0; i < ch.size(); ++i ) |
|
||||||
{ |
|
||||||
const Mat &channel = ch[i]; |
|
||||||
Mat integral_channel; |
|
||||||
integral(channel, integral_channel, CV_32F); |
|
||||||
integral_channel.convertTo(integral_channel, CV_32S); |
|
||||||
channels_.push_back(integral_channel.clone()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void ICFFeatureEvaluatorImpl::setPosition(Size position) |
|
||||||
{ |
|
||||||
position_ = position; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
int ICFFeatureEvaluatorImpl::evaluate(size_t feature_ind) const |
|
||||||
{ |
|
||||||
/*
|
|
||||||
|
|
||||||
//following return is equal to this commented code, left here for readability. The new code runs much faster.
|
|
||||||
*
|
|
||||||
const vector<int>& feature = features_[feature_ind]; |
|
||||||
int x = feature[0] + position_.height; |
|
||||||
int y = feature[1] + position_.width; |
|
||||||
int x_to = feature[2] + position_.height; |
|
||||||
int y_to = feature[3] + position_.width; |
|
||||||
int n = feature[4]; |
|
||||||
const Mat_<int>& ch = channels_[n]; |
|
||||||
return ch(y_to + 1, x_to + 1) - ch(y, x_to + 1) - ch(y_to + 1, x) + ch(y, x); |
|
||||||
*/ |
|
||||||
|
|
||||||
CV_Assert(feature_ind < features_.size()); |
|
||||||
|
|
||||||
return *(channels_[features_[feature_ind][4]].ptr<int>()+((channels_[features_[feature_ind][4]].cols*(features_[feature_ind][3] + position_.width+1))+ features_[feature_ind][2] + position_.height + 1)) -
|
|
||||||
*(channels_[features_[feature_ind][4]].ptr<int>()+((channels_[features_[feature_ind][4]].cols*(features_[feature_ind][1] + position_.width))+ features_[feature_ind][2] + position_.height + 1)) - |
|
||||||
*(channels_[features_[feature_ind][4]].ptr<int>()+((channels_[features_[feature_ind][4]].cols*(features_[feature_ind][3] + position_.width+1))+ features_[feature_ind][0] + position_.height)) + |
|
||||||
*(channels_[features_[feature_ind][4]].ptr<int>()+((channels_[features_[feature_ind][4]].cols*(features_[feature_ind][1] + position_.width))+ features_[feature_ind][0] + position_.height)); |
|
||||||
} |
|
||||||
|
|
||||||
class ACFFeatureEvaluatorImpl : public FeatureEvaluatorImpl |
|
||||||
{ |
|
||||||
public: |
|
||||||
ACFFeatureEvaluatorImpl(const vector<vector<int> >& features): |
|
||||||
FeatureEvaluatorImpl(features) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
virtual void setChannels(InputArrayOfArrays channels); |
|
||||||
virtual void setPosition(Size position); |
|
||||||
virtual int evaluate(size_t feature_ind) const; |
|
||||||
}; |
|
||||||
|
|
||||||
void ACFFeatureEvaluatorImpl::setChannels(InputArrayOfArrays channels) |
|
||||||
{ |
|
||||||
channels_.clear(); |
|
||||||
vector<Mat> ch; |
|
||||||
channels.getMatVector(ch); |
|
||||||
|
|
||||||
for( size_t i = 0; i < ch.size(); ++i ) |
|
||||||
{ |
|
||||||
const Mat &channel = ch[i]; |
|
||||||
Mat_<int> acf_channel = Mat_<int>::zeros(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.clone()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void ACFFeatureEvaluatorImpl::setPosition(Size position) |
|
||||||
{ |
|
||||||
position_ = Size(position.width / 4, position.height / 4); |
|
||||||
} |
|
||||||
|
|
||||||
int ACFFeatureEvaluatorImpl::evaluate(size_t feature_ind) const |
|
||||||
{ |
|
||||||
CV_Assert(feature_ind < features_.size()); |
|
||||||
|
|
||||||
const vector<int>& feature = features_[feature_ind]; |
|
||||||
int x = feature[0]; |
|
||||||
int y = feature[1]; |
|
||||||
int n = feature[2]; |
|
||||||
return channels_[n].at<int>(y + position_.width, x + position_.height); |
|
||||||
} |
|
||||||
|
|
||||||
Ptr<FeatureEvaluator> createFeatureEvaluator( |
|
||||||
const vector<vector<int> >& features, const std::string& type) |
|
||||||
{ |
|
||||||
FeatureEvaluator *evaluator = NULL; |
|
||||||
if( type == "acf" ) |
|
||||||
evaluator = new ACFFeatureEvaluatorImpl(features); |
|
||||||
else if( type == "icf" ) |
|
||||||
evaluator = new ICFFeatureEvaluatorImpl(features); |
|
||||||
else |
|
||||||
CV_Error(CV_StsBadArg, "type value is either acf or icf"); |
|
||||||
|
|
||||||
return Ptr<FeatureEvaluator>(evaluator); |
|
||||||
} |
|
||||||
|
|
||||||
vector<vector<int> > generateFeatures(Size window_size, const std::string& type, |
|
||||||
int count, int channel_count) |
|
||||||
{ |
|
||||||
CV_Assert(count > 0); |
|
||||||
vector<vector<int> > features; |
|
||||||
if( type == "acf" ) |
|
||||||
{ |
|
||||||
int cur_count = 0; |
|
||||||
int max_count = window_size.width * window_size.height / 16; |
|
||||||
count = min(count, max_count); |
|
||||||
for( int x = 0; x < window_size.width / 4; ++x ) |
|
||||||
for( int y = 0; y < window_size.height / 4; ++y ) |
|
||||||
for( int n = 0; n < channel_count; ++n ) |
|
||||||
{ |
|
||||||
int f[] = {x, y, n}; |
|
||||||
vector<int> feature(f, f + sizeof(f) / sizeof(*f)); |
|
||||||
features.push_back(feature); |
|
||||||
if( (cur_count += 1) == count ) |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
else if( type == "icf" ) |
|
||||||
{ |
|
||||||
RNG rng; |
|
||||||
for( int i = 0; i < count; ++i ) |
|
||||||
{ |
|
||||||
int x = rng.uniform(0, window_size.width - 1); |
|
||||||
int y = rng.uniform(0, window_size.height - 1); |
|
||||||
int x_to = rng.uniform(x, window_size.width - 1); |
|
||||||
int y_to = rng.uniform(y, window_size.height - 1); |
|
||||||
int n = rng.uniform(0, channel_count - 1); |
|
||||||
int f[] = {x, y, x_to, y_to, n}; |
|
||||||
vector<int> feature(f, f + sizeof(f) / sizeof(*f)); |
|
||||||
features.push_back(feature); |
|
||||||
} |
|
||||||
} |
|
||||||
else |
|
||||||
CV_Error(CV_StsBadArg, "type value is either acf or icf"); |
|
||||||
|
|
||||||
return features; |
|
||||||
} |
|
||||||
|
|
||||||
void computeChannels(InputArray image, vector<Mat>& channels) |
|
||||||
{ |
|
||||||
Mat_<float> grad; |
|
||||||
Mat_<float> angles; |
|
||||||
Mat luv, gray, src; |
|
||||||
|
|
||||||
if(image.getMat().channels() > 1) |
|
||||||
{ |
|
||||||
src = Mat(image.getMat().rows, image.getMat().cols, CV_32FC3); |
|
||||||
image.getMat().convertTo(src, CV_32FC3, 1./255); |
|
||||||
|
|
||||||
cvtColor(src, gray, CV_RGB2GRAY); |
|
||||||
cvtColor(src, luv, CV_RGB2Luv); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
src = Mat(image.getMat().rows, image.getMat().cols, CV_32FC1); |
|
||||||
image.getMat().convertTo(src, CV_32FC1, 1./255); |
|
||||||
src.copyTo(gray); |
|
||||||
} |
|
||||||
|
|
||||||
Mat_<float> row_der, col_der; |
|
||||||
Sobel(gray, row_der, CV_32F, 0, 1); |
|
||||||
Sobel(gray, col_der, CV_32F, 1, 0); |
|
||||||
|
|
||||||
cartToPolar(col_der, row_der, grad, angles, true); |
|
||||||
//magnitude(row_der, col_der, grad);
|
|
||||||
|
|
||||||
Mat_<Vec6f> hist = Mat_<Vec6f>::zeros(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;
|
|
||||||
float angle = angles(row, col); |
|
||||||
if (angle > 180) |
|
||||||
angle -= 180; |
|
||||||
if (angle < 0) |
|
||||||
angle += 180; |
|
||||||
int ind = (int)(angle / 30); |
|
||||||
|
|
||||||
// If angle == 180, prevent index overflow
|
|
||||||
if (ind == 6) |
|
||||||
ind = 5; |
|
||||||
|
|
||||||
hist(row, col)[ind] = grad(row, col) * 255; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
channels.clear(); |
|
||||||
|
|
||||||
if(image.getMat().channels() > 1) |
|
||||||
{ |
|
||||||
Mat luv_channels[3]; |
|
||||||
split(luv, luv_channels); |
|
||||||
for( int i = 0; i < 3; ++i ) |
|
||||||
channels.push_back(luv_channels[i]); |
|
||||||
} |
|
||||||
|
|
||||||
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]); |
|
||||||
} |
|
||||||
|
|
||||||
} /* namespace xobjdetect */ |
|
||||||
} /* namespace cv */ |
|
@ -0,0 +1,95 @@ |
|||||||
|
/*
|
||||||
|
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) 2000-2015, Intel Corporation, all rights reserved. |
||||||
|
Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. |
||||||
|
Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. |
||||||
|
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. |
||||||
|
Copyright (C) 2015, OpenCV Foundation, all rights reserved. |
||||||
|
Copyright (C) 2015, Itseez Inc., 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_CASCADECLASSIFIER_H_ |
||||||
|
#define _OPENCV_CASCADECLASSIFIER_H_ |
||||||
|
|
||||||
|
#include "precomp.hpp" |
||||||
|
|
||||||
|
#define CC_CASCADE_FILENAME "cascade.xml" |
||||||
|
#define CC_PARAMS_FILENAME "params.xml" |
||||||
|
|
||||||
|
#define CC_CASCADE_PARAMS "cascadeParams" |
||||||
|
#define CC_STAGE_TYPE "stageType" |
||||||
|
#define CC_FEATURE_TYPE "featureType" |
||||||
|
#define CC_HEIGHT "height" |
||||||
|
#define CC_WIDTH "width" |
||||||
|
|
||||||
|
#define CC_STAGE_NUM "stageNum" |
||||||
|
#define CC_STAGES "stages" |
||||||
|
#define CC_STAGE_PARAMS "stageParams" |
||||||
|
|
||||||
|
#define CC_BOOST "BOOST" |
||||||
|
#define CC_BOOST_TYPE "boostType" |
||||||
|
#define CC_DISCRETE_BOOST "DAB" |
||||||
|
#define CC_REAL_BOOST "RAB" |
||||||
|
#define CC_LOGIT_BOOST "LB" |
||||||
|
#define CC_GENTLE_BOOST "GAB" |
||||||
|
#define CC_MINHITRATE "minHitRate" |
||||||
|
#define CC_MAXFALSEALARM "maxFalseAlarm" |
||||||
|
#define CC_TRIM_RATE "weightTrimRate" |
||||||
|
#define CC_MAX_DEPTH "maxDepth" |
||||||
|
#define CC_WEAK_COUNT "maxWeakCount" |
||||||
|
#define CC_STAGE_THRESHOLD "stageThreshold" |
||||||
|
#define CC_WEAK_CLASSIFIERS "weakClassifiers" |
||||||
|
#define CC_INTERNAL_NODES "internalNodes" |
||||||
|
#define CC_LEAF_VALUES "leafValues" |
||||||
|
|
||||||
|
#define CC_FEATURES FEATURES |
||||||
|
#define CC_FEATURE_PARAMS "featureParams" |
||||||
|
#define CC_MAX_CAT_COUNT "maxCatCount" |
||||||
|
#define CC_FEATURE_SIZE "featSize" |
||||||
|
|
||||||
|
#define CC_HAAR "HAAR" |
||||||
|
#define CC_MODE "mode" |
||||||
|
#define CC_MODE_BASIC "BASIC" |
||||||
|
#define CC_MODE_CORE "CORE" |
||||||
|
#define CC_MODE_ALL "ALL" |
||||||
|
#define CC_RECTS "rects" |
||||||
|
#define CC_TILTED "tilted" |
||||||
|
|
||||||
|
#define CC_LBP "LBP" |
||||||
|
#define CC_RECT "rect" |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,131 @@ |
|||||||
|
/*
|
||||||
|
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) 2000-2015, Intel Corporation, all rights reserved. |
||||||
|
Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. |
||||||
|
Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. |
||||||
|
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. |
||||||
|
Copyright (C) 2015, OpenCV Foundation, all rights reserved. |
||||||
|
Copyright (C) 2015, Itseez Inc., 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 { |
||||||
|
|
||||||
|
float calcNormFactor( const Mat& sum, const Mat& sqSum ) |
||||||
|
{ |
||||||
|
CV_DbgAssert( sum.cols > 3 && sqSum.rows > 3 ); |
||||||
|
Rect normrect( 1, 1, sum.cols - 3, sum.rows - 3 ); |
||||||
|
size_t p0, p1, p2, p3; |
||||||
|
CV_SUM_OFFSETS( p0, p1, p2, p3, normrect, sum.step1() ) |
||||||
|
double area = normrect.width * normrect.height; |
||||||
|
const int *sp = sum.ptr<int>(); |
||||||
|
int valSum = sp[p0] - sp[p1] - sp[p2] + sp[p3]; |
||||||
|
const double *sqp = sqSum.ptr<double>(); |
||||||
|
double valSqSum = sqp[p0] - sqp[p1] - sqp[p2] + sqp[p3]; |
||||||
|
return (float) sqrt( (double) (area * valSqSum - (double)valSum * valSum) ); |
||||||
|
} |
||||||
|
|
||||||
|
CvParams::CvParams() : name( "params" ) {} |
||||||
|
void CvParams::printDefaults() const |
||||||
|
{ std::cout << "--" << name << "--" << std::endl; } |
||||||
|
void CvParams::printAttrs() const {} |
||||||
|
bool CvParams::scanAttr( const std::string, const std::string ) { return false; } |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------- FeatureParams --------------------------------------
|
||||||
|
|
||||||
|
CvFeatureParams::CvFeatureParams() : maxCatCount( 0 ), featSize( 1 ) |
||||||
|
{ |
||||||
|
name = CC_FEATURE_PARAMS; |
||||||
|
} |
||||||
|
|
||||||
|
void CvFeatureParams::init( const CvFeatureParams& fp ) |
||||||
|
{ |
||||||
|
maxCatCount = fp.maxCatCount; |
||||||
|
featSize = fp.featSize; |
||||||
|
} |
||||||
|
|
||||||
|
void CvFeatureParams::write( FileStorage &fs ) const |
||||||
|
{ |
||||||
|
fs << CC_MAX_CAT_COUNT << maxCatCount; |
||||||
|
fs << CC_FEATURE_SIZE << featSize; |
||||||
|
} |
||||||
|
|
||||||
|
bool CvFeatureParams::read( const FileNode &node ) |
||||||
|
{ |
||||||
|
if ( node.empty() ) |
||||||
|
return false; |
||||||
|
maxCatCount = node[CC_MAX_CAT_COUNT]; |
||||||
|
featSize = node[CC_FEATURE_SIZE]; |
||||||
|
return ( maxCatCount >= 0 && featSize >= 1 ); |
||||||
|
} |
||||||
|
|
||||||
|
Ptr<CvFeatureParams> CvFeatureParams::create() |
||||||
|
{ |
||||||
|
return Ptr<CvFeatureParams>(new CvLBPFeatureParams); |
||||||
|
} |
||||||
|
|
||||||
|
//------------------------------------- FeatureEvaluator ---------------------------------------
|
||||||
|
|
||||||
|
void CvFeatureEvaluator::init(const CvFeatureParams *_featureParams, |
||||||
|
int _maxSampleCount, Size _winSize ) |
||||||
|
{ |
||||||
|
CV_Assert(_maxSampleCount > 0); |
||||||
|
featureParams = (CvFeatureParams *)_featureParams; |
||||||
|
winSize = _winSize; |
||||||
|
numFeatures = 0; |
||||||
|
cls.create( (int)_maxSampleCount, 1, CV_32FC1 ); |
||||||
|
generateFeatures(); |
||||||
|
} |
||||||
|
|
||||||
|
void CvFeatureEvaluator::setImage(const Mat &, uchar clsLabel, int idx, const std::vector<int>&) |
||||||
|
{ |
||||||
|
//CV_Assert(img.cols == winSize.width);
|
||||||
|
//CV_Assert(img.rows == winSize.height);
|
||||||
|
CV_Assert(idx < cls.rows); |
||||||
|
cls.ptr<float>(idx)[0] = clsLabel; |
||||||
|
} |
||||||
|
|
||||||
|
Ptr<CvFeatureEvaluator> CvFeatureEvaluator::create() |
||||||
|
{ |
||||||
|
return Ptr<CvFeatureEvaluator>(new CvLBPEvaluator); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,151 @@ |
|||||||
|
/*
|
||||||
|
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) 2000-2015, Intel Corporation, all rights reserved. |
||||||
|
Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. |
||||||
|
Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. |
||||||
|
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. |
||||||
|
Copyright (C) 2015, OpenCV Foundation, all rights reserved. |
||||||
|
Copyright (C) 2015, Itseez Inc., 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_FEATURES_H_ |
||||||
|
#define _OPENCV_FEATURES_H_ |
||||||
|
|
||||||
|
#include <stdio.h> |
||||||
|
|
||||||
|
#define FEATURES "features" |
||||||
|
|
||||||
|
#define CV_SUM_OFFSETS( p0, p1, p2, p3, rect, step ) \ |
||||||
|
/* (x, y) */ \
|
||||||
|
(p0) = (rect).x + (step) * (rect).y; \
|
||||||
|
/* (x + w, y) */ \
|
||||||
|
(p1) = (rect).x + (rect).width + (step) * (rect).y; \
|
||||||
|
/* (x + w, y) */ \
|
||||||
|
(p2) = (rect).x + (step) * ((rect).y + (rect).height); \
|
||||||
|
/* (x + w, y + h) */ \
|
||||||
|
(p3) = (rect).x + (rect).width + (step) * ((rect).y + (rect).height); |
||||||
|
|
||||||
|
#define CV_TILTED_OFFSETS( p0, p1, p2, p3, rect, step ) \ |
||||||
|
/* (x, y) */ \
|
||||||
|
(p0) = (rect).x + (step) * (rect).y; \
|
||||||
|
/* (x - h, y + h) */ \
|
||||||
|
(p1) = (rect).x - (rect).height + (step) * ((rect).y + (rect).height);\
|
||||||
|
/* (x + w, y + w) */ \
|
||||||
|
(p2) = (rect).x + (rect).width + (step) * ((rect).y + (rect).width); \
|
||||||
|
/* (x + w - h, y + w + h) */ \
|
||||||
|
(p3) = (rect).x + (rect).width - (rect).height \
|
||||||
|
+ (step) * ((rect).y + (rect).width + (rect).height); |
||||||
|
|
||||||
|
namespace cv { |
||||||
|
namespace xobjdetect { |
||||||
|
|
||||||
|
float calcNormFactor( const cv::Mat& sum, const cv::Mat& sqSum ); |
||||||
|
|
||||||
|
template<class Feature> |
||||||
|
void _writeFeatures( const std::vector<Feature> features, cv::FileStorage &fs, const cv::Mat& featureMap ) |
||||||
|
{ |
||||||
|
fs << FEATURES << "["; |
||||||
|
const cv::Mat_<int>& featureMap_ = (const cv::Mat_<int>&)featureMap; |
||||||
|
for ( int fi = 0; fi < featureMap.cols; fi++ ) |
||||||
|
if ( featureMap_(0, fi) >= 0 ) |
||||||
|
{ |
||||||
|
fs << "{"; |
||||||
|
features[fi].write( fs ); |
||||||
|
fs << "}"; |
||||||
|
} |
||||||
|
fs << "]"; |
||||||
|
} |
||||||
|
|
||||||
|
class CvParams |
||||||
|
{ |
||||||
|
public: |
||||||
|
CvParams(); |
||||||
|
virtual ~CvParams() {} |
||||||
|
// from|to file
|
||||||
|
virtual void write( cv::FileStorage &fs ) const = 0; |
||||||
|
virtual bool read( const cv::FileNode &node ) = 0; |
||||||
|
// from|to screen
|
||||||
|
virtual void printDefaults() const; |
||||||
|
virtual void printAttrs() const; |
||||||
|
virtual bool scanAttr( const std::string prmName, const std::string val ); |
||||||
|
std::string name; |
||||||
|
}; |
||||||
|
|
||||||
|
class CvFeatureParams : public CvParams |
||||||
|
{ |
||||||
|
public: |
||||||
|
enum { HAAR = 0, LBP = 1, HOG = 2 }; |
||||||
|
CvFeatureParams(); |
||||||
|
virtual void init( const CvFeatureParams& fp ); |
||||||
|
virtual void write( cv::FileStorage &fs ) const; |
||||||
|
virtual bool read( const cv::FileNode &node ); |
||||||
|
static cv::Ptr<CvFeatureParams> create(); |
||||||
|
int maxCatCount; // 0 in case of numerical features
|
||||||
|
int featSize; // 1 in case of simple features (HAAR, LBP) and N_BINS(9)*N_CELLS(4) in case of Dalal's HOG features
|
||||||
|
}; |
||||||
|
|
||||||
|
class CvFeatureEvaluator |
||||||
|
{ |
||||||
|
public: |
||||||
|
virtual ~CvFeatureEvaluator() {} |
||||||
|
virtual void init(const CvFeatureParams *_featureParams, |
||||||
|
int _maxSampleCount, cv::Size _winSize ); |
||||||
|
virtual void setImage(const cv::Mat& img, uchar clsLabel, int idx, const std::vector<int> &feature_ind); |
||||||
|
virtual void setWindow(const cv::Point& p) = 0; |
||||||
|
virtual void writeFeatures( cv::FileStorage &fs, const cv::Mat& featureMap ) const = 0; |
||||||
|
virtual float operator()(int featureIdx) = 0; |
||||||
|
static cv::Ptr<CvFeatureEvaluator> create(); |
||||||
|
|
||||||
|
int getNumFeatures() const { return numFeatures; } |
||||||
|
int getMaxCatCount() const { return featureParams->maxCatCount; } |
||||||
|
int getFeatureSize() const { return featureParams->featSize; } |
||||||
|
const cv::Mat& getCls() const { return cls; } |
||||||
|
float getCls(int si) const { return cls.at<float>(si, 0); } |
||||||
|
protected: |
||||||
|
virtual void generateFeatures() = 0; |
||||||
|
|
||||||
|
int npos, nneg; |
||||||
|
int numFeatures; |
||||||
|
cv::Size winSize; |
||||||
|
CvFeatureParams *featureParams; |
||||||
|
cv::Mat cls; |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -1,316 +0,0 @@ |
|||||||
/*
|
|
||||||
|
|
||||||
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 <sstream> |
|
||||||
using std::ostringstream; |
|
||||||
|
|
||||||
#include <iomanip> |
|
||||||
using std::setfill; |
|
||||||
using std::setw; |
|
||||||
|
|
||||||
#include <iostream> |
|
||||||
using std::cout; |
|
||||||
using std::endl; |
|
||||||
|
|
||||||
#include "precomp.hpp" |
|
||||||
|
|
||||||
using std::vector; |
|
||||||
using std::string; |
|
||||||
|
|
||||||
using std::min; |
|
||||||
using std::max; |
|
||||||
|
|
||||||
|
|
||||||
namespace cv |
|
||||||
{ |
|
||||||
|
|
||||||
namespace xobjdetect |
|
||||||
{ |
|
||||||
|
|
||||||
|
|
||||||
void ICFDetector::train(const vector<String>& pos_filenames, |
|
||||||
const vector<String>& bg_filenames, |
|
||||||
ICFDetectorParams params) |
|
||||||
{ |
|
||||||
|
|
||||||
int color; |
|
||||||
if(params.is_grayscale == false) |
|
||||||
color = IMREAD_COLOR; |
|
||||||
else |
|
||||||
color = IMREAD_GRAYSCALE; |
|
||||||
|
|
||||||
model_n_rows_ = params.model_n_rows; |
|
||||||
model_n_cols_ = params.model_n_cols; |
|
||||||
ftype_ = params.features_type; |
|
||||||
|
|
||||||
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 < pos_filenames.size(); ++i, ++pos_count ) |
|
||||||
{ |
|
||||||
cout << setw(6) << (i + 1) << "/" << pos_filenames.size() << "\r"; |
|
||||||
Mat img = imread(pos_filenames[i], color); |
|
||||||
resize(img, resized_sample, model_size); |
|
||||||
samples.push_back(resized_sample.clone()); |
|
||||||
} |
|
||||||
cout << "\n"; |
|
||||||
|
|
||||||
int neg_count = 0; |
|
||||||
RNG rng; |
|
||||||
for( size_t i = 0; i < bg_filenames.size(); ++i ) |
|
||||||
{ |
|
||||||
cout << setw(6) << (i + 1) << "/" << bg_filenames.size() << "\r"; |
|
||||||
Mat img = imread(bg_filenames[i], color); |
|
||||||
for( int j = 0; j < params.bg_per_image; ++j, ++neg_count) |
|
||||||
{ |
|
||||||
Rect r; |
|
||||||
r.x = rng.uniform(0, img.cols-model_size.width); |
|
||||||
r.width = model_size.width; |
|
||||||
r.y = rng.uniform(0, img.rows-model_size.height); |
|
||||||
r.height = model_size.height; |
|
||||||
sample = img.colRange(r.x, r.x + r.width).rowRange(r.y, r.y + r.height); |
|
||||||
samples.push_back(sample.clone()); |
|
||||||
} |
|
||||||
} |
|
||||||
cout << "\n"; |
|
||||||
|
|
||||||
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<vector<int> > features; |
|
||||||
if(params.is_grayscale == false) |
|
||||||
features = generateFeatures(model_size, params.features_type, params.feature_count, 10); |
|
||||||
else |
|
||||||
features = generateFeatures(model_size, params.features_type, params.feature_count, 7); |
|
||||||
|
|
||||||
Ptr<FeatureEvaluator> evaluator = createFeatureEvaluator(features, params.features_type); |
|
||||||
|
|
||||||
|
|
||||||
Mat_<int> data = Mat_<int>::zeros((int)features.size(), (int)samples.size()); |
|
||||||
Mat_<int> feature_col(1, (int)samples.size()); |
|
||||||
|
|
||||||
vector<Mat> channels; |
|
||||||
for( int i = 0; i < (int)samples.size(); ++i ) |
|
||||||
{ |
|
||||||
cout << setw(6) << i << "/" << samples.size() << "\r"; |
|
||||||
computeChannels(samples[i], channels); |
|
||||||
evaluator->setChannels(channels); |
|
||||||
//evaluator->assertChannels();
|
|
||||||
evaluator->evaluateAll(feature_col); |
|
||||||
|
|
||||||
CV_Assert(feature_col.cols == (int)features.size()); |
|
||||||
|
|
||||||
for( int j = 0; j < feature_col.cols; ++j ) |
|
||||||
data(j, i) = feature_col(0, j); |
|
||||||
} |
|
||||||
cout << "\n"; |
|
||||||
samples.clear(); |
|
||||||
|
|
||||||
WaldBoostParams wparams; |
|
||||||
wparams.weak_count = params.weak_count; |
|
||||||
wparams.alpha = params.alpha; |
|
||||||
|
|
||||||
waldboost_ = createWaldBoost(wparams); |
|
||||||
vector<int> indices = waldboost_->train(data, labels, params.use_fast_log); |
|
||||||
cout << "indices: "; |
|
||||||
for( size_t i = 0; i < indices.size(); ++i ) |
|
||||||
cout << indices[i] << " "; |
|
||||||
cout << endl; |
|
||||||
|
|
||||||
features_.clear(); |
|
||||||
for( size_t i = 0; i < indices.size(); ++i ) |
|
||||||
features_.push_back(features[indices[i]]); |
|
||||||
} |
|
||||||
|
|
||||||
void ICFDetector::write(FileStorage& fs) const |
|
||||||
{ |
|
||||||
fs << "{"; |
|
||||||
fs << "model_n_rows" << model_n_rows_; |
|
||||||
fs << "model_n_cols" << model_n_cols_; |
|
||||||
fs << "ftype" << String(ftype_.c_str()); |
|
||||||
fs << "waldboost"; |
|
||||||
waldboost_->write(fs); |
|
||||||
fs << "features" << "["; |
|
||||||
for( size_t i = 0; i < features_.size(); ++i ) |
|
||||||
{ |
|
||||||
fs << features_[i]; |
|
||||||
} |
|
||||||
fs << "]"; |
|
||||||
fs << "}"; |
|
||||||
} |
|
||||||
|
|
||||||
void ICFDetector::read(const FileNode& node) |
|
||||||
{ |
|
||||||
waldboost_ = Ptr<WaldBoost>(createWaldBoost(WaldBoostParams())); |
|
||||||
String f_temp; |
|
||||||
node["model_n_rows"] >> model_n_rows_; |
|
||||||
node["model_n_cols"] >> model_n_cols_; |
|
||||||
f_temp = (String)node["ftype"];
|
|
||||||
this->ftype_ = (string)f_temp.c_str(); |
|
||||||
waldboost_->read(node["waldboost"]); |
|
||||||
FileNode features = node["features"]; |
|
||||||
features_.clear(); |
|
||||||
vector<int> p; |
|
||||||
for( FileNodeIterator n = features.begin(); n != features.end(); ++n ) |
|
||||||
{ |
|
||||||
(*n) >> p; |
|
||||||
features_.push_back(p); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void ICFDetector::detect(const Mat& img, vector<Rect>& objects, |
|
||||||
float scaleFactor, Size minSize, Size maxSize, float threshold, int slidingStep, std::vector<float>& values) |
|
||||||
{ |
|
||||||
|
|
||||||
|
|
||||||
float scale_from = min(model_n_cols_ / (float)maxSize.width, |
|
||||||
model_n_rows_ / (float)maxSize.height); |
|
||||||
float scale_to = max(model_n_cols_ / (float)minSize.width, |
|
||||||
model_n_rows_ / (float)minSize.height); |
|
||||||
objects.clear(); |
|
||||||
Ptr<FeatureEvaluator> evaluator = createFeatureEvaluator(features_, ftype_); |
|
||||||
Mat rescaled_image; |
|
||||||
vector<Mat> channels; |
|
||||||
|
|
||||||
for( float scale = scale_from; scale < scale_to + 0.001; scale *= scaleFactor ) |
|
||||||
{ |
|
||||||
int new_width = int(img.cols * scale); |
|
||||||
new_width -= new_width % 4; |
|
||||||
int new_height = int(img.rows * scale); |
|
||||||
new_height -= new_height % 4; |
|
||||||
|
|
||||||
resize(img, rescaled_image, Size(new_width, new_height)); |
|
||||||
computeChannels(rescaled_image, channels); |
|
||||||
evaluator->setChannels(channels); |
|
||||||
for( int row = 0; row <= rescaled_image.rows - model_n_rows_; row += slidingStep) |
|
||||||
{ |
|
||||||
for( int col = 0; col <= rescaled_image.cols - model_n_cols_; |
|
||||||
col += slidingStep ) |
|
||||||
{ |
|
||||||
evaluator->setPosition(Size(row, col)); |
|
||||||
float value = waldboost_->predict(evaluator); |
|
||||||
if( value > threshold ) |
|
||||||
{ |
|
||||||
values.push_back(value); |
|
||||||
int x = (int)(col / scale); |
|
||||||
int y = (int)(row / scale); |
|
||||||
int width = (int)(model_n_cols_ / scale); |
|
||||||
int height = (int)(model_n_rows_ / scale); |
|
||||||
objects.push_back(Rect(x, y, width, height)); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void ICFDetector::detect(const Mat& img, vector<Rect>& objects, |
|
||||||
float minScaleFactor, float maxScaleFactor, float factorStep, float threshold, int slidingStep, std::vector<float>& values) |
|
||||||
{ |
|
||||||
|
|
||||||
if(factorStep <= 0) |
|
||||||
{ |
|
||||||
CV_Error_(CV_StsBadArg, ("factorStep must be > 0")); |
|
||||||
} |
|
||||||
|
|
||||||
objects.clear(); |
|
||||||
Ptr<FeatureEvaluator> evaluator = createFeatureEvaluator(features_, ftype_); |
|
||||||
Mat rescaled_image; |
|
||||||
vector<Mat> channels; |
|
||||||
|
|
||||||
for( float scale = minScaleFactor; scale < maxScaleFactor + 0.001; scale += factorStep ) |
|
||||||
{ |
|
||||||
if(scale < 1.0) |
|
||||||
resize(img, rescaled_image, Size(),scale, scale, INTER_AREA); |
|
||||||
else if (scale > 1.0) |
|
||||||
resize(img, rescaled_image, Size(),scale, scale, INTER_CUBIC); |
|
||||||
else //scale == 1.0
|
|
||||||
img.copyTo(rescaled_image); |
|
||||||
|
|
||||||
computeChannels(rescaled_image, channels); |
|
||||||
evaluator->setChannels(channels); |
|
||||||
for( int row = 0; row <= rescaled_image.rows - model_n_rows_; row += slidingStep) |
|
||||||
{ |
|
||||||
for( int col = 0; col <= rescaled_image.cols - model_n_cols_; |
|
||||||
col += slidingStep ) |
|
||||||
{ |
|
||||||
evaluator->setPosition(Size(row, col)); |
|
||||||
float value = waldboost_->predict(evaluator); |
|
||||||
if( value > threshold ) |
|
||||||
{ |
|
||||||
values.push_back(value); |
|
||||||
int x = (int)(col / scale); |
|
||||||
int y = (int)(row / scale); |
|
||||||
int width = (int)(model_n_cols_ / scale); |
|
||||||
int height = (int)(model_n_rows_ / scale); |
|
||||||
objects.push_back(Rect(x, y, width, height)); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void write(FileStorage& fs, String&, const ICFDetector& detector) |
|
||||||
{ |
|
||||||
detector.write(fs); |
|
||||||
} |
|
||||||
|
|
||||||
void read(const FileNode& node, ICFDetector& d, |
|
||||||
const ICFDetector& default_value) |
|
||||||
{ |
|
||||||
if( node.empty() ) |
|
||||||
d = default_value; |
|
||||||
else |
|
||||||
d.read(node); |
|
||||||
} |
|
||||||
|
|
||||||
} /* namespace xobjdetect */ |
|
||||||
} /* namespace cv */ |
|
@ -0,0 +1,128 @@ |
|||||||
|
|
||||||
|
/*
|
||||||
|
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) 2000-2015, Intel Corporation, all rights reserved. |
||||||
|
Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. |
||||||
|
Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. |
||||||
|
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. |
||||||
|
Copyright (C) 2015, OpenCV Foundation, all rights reserved. |
||||||
|
Copyright (C) 2015, Itseez Inc., 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 { |
||||||
|
|
||||||
|
CvLBPFeatureParams::CvLBPFeatureParams() |
||||||
|
{ |
||||||
|
maxCatCount = 256; |
||||||
|
name = LBPF_NAME; |
||||||
|
} |
||||||
|
|
||||||
|
void CvLBPEvaluator::init(const CvFeatureParams *_featureParams, int _maxSampleCount, Size _winSize) |
||||||
|
{ |
||||||
|
CV_Assert( _maxSampleCount > 0); |
||||||
|
sum.create((int)_maxSampleCount, (_winSize.width + 1) * (_winSize.height + 1), CV_32SC1); |
||||||
|
CvFeatureEvaluator::init( _featureParams, _maxSampleCount, _winSize ); |
||||||
|
} |
||||||
|
|
||||||
|
void CvLBPEvaluator::setImage(const Mat &img, uchar clsLabel, int idx, |
||||||
|
const std::vector<int> &feature_ind) |
||||||
|
{ |
||||||
|
CV_DbgAssert( !sum.empty() ); |
||||||
|
CvFeatureEvaluator::setImage( img, clsLabel, idx, feature_ind ); |
||||||
|
integral( img, sum ); |
||||||
|
cur_sum = sum; |
||||||
|
offset_ = int(sum.ptr<int>(1) - sum.ptr<int>()); |
||||||
|
for (size_t i = 0; i < feature_ind.size(); ++i) { |
||||||
|
features[feature_ind[i]].calcPoints(offset_); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void CvLBPEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const |
||||||
|
{ |
||||||
|
_writeFeatures( features, fs, featureMap ); |
||||||
|
} |
||||||
|
|
||||||
|
void CvLBPEvaluator::generateFeatures() |
||||||
|
{ |
||||||
|
int offset = winSize.width + 1; |
||||||
|
for( int x = 0; x < winSize.width; x++ ) |
||||||
|
for( int y = 0; y < winSize.height; y++ ) |
||||||
|
for( int w = 1; w <= winSize.width / 3; w++ ) |
||||||
|
for( int h = 1; h <= winSize.height / 3; h++ ) |
||||||
|
if ( (x+3*w <= winSize.width) && (y+3*h <= winSize.height) ) |
||||||
|
features.push_back( Feature(offset, x, y, w, h ) ); |
||||||
|
numFeatures = (int)features.size(); |
||||||
|
} |
||||||
|
|
||||||
|
CvLBPEvaluator::Feature::Feature() |
||||||
|
{ |
||||||
|
rect = cvRect(0, 0, 0, 0); |
||||||
|
} |
||||||
|
|
||||||
|
CvLBPEvaluator::Feature::Feature( int offset, int x, int y, int _blockWidth, int _blockHeight ) |
||||||
|
{ |
||||||
|
x_ = x; |
||||||
|
y_ = y; |
||||||
|
block_w_ = _blockWidth; |
||||||
|
block_h_ = _blockHeight; |
||||||
|
offset_ = offset; |
||||||
|
calcPoints(offset); |
||||||
|
} |
||||||
|
|
||||||
|
void CvLBPEvaluator::Feature::calcPoints(int offset) |
||||||
|
{ |
||||||
|
Rect tr = rect = cvRect(x_, y_, block_w_, block_h_); |
||||||
|
CV_SUM_OFFSETS( p[0], p[1], p[4], p[5], tr, offset ) |
||||||
|
tr.x += 2*rect.width; |
||||||
|
CV_SUM_OFFSETS( p[2], p[3], p[6], p[7], tr, offset ) |
||||||
|
tr.y +=2*rect.height; |
||||||
|
CV_SUM_OFFSETS( p[10], p[11], p[14], p[15], tr, offset ) |
||||||
|
tr.x -= 2*rect.width; |
||||||
|
CV_SUM_OFFSETS( p[8], p[9], p[12], p[13], tr, offset ) |
||||||
|
offset_ = offset; |
||||||
|
} |
||||||
|
|
||||||
|
void CvLBPEvaluator::Feature::write(FileStorage &fs) const |
||||||
|
{ |
||||||
|
fs << CC_RECT << "[:" << rect.x << rect.y << rect.width << rect.height << "]"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,116 @@ |
|||||||
|
/*
|
||||||
|
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) 2000-2015, Intel Corporation, all rights reserved. |
||||||
|
Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. |
||||||
|
Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. |
||||||
|
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. |
||||||
|
Copyright (C) 2015, OpenCV Foundation, all rights reserved. |
||||||
|
Copyright (C) 2015, Itseez Inc., 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_LBPFEATURES_H_ |
||||||
|
#define _OPENCV_LBPFEATURES_H_ |
||||||
|
|
||||||
|
#include "precomp.hpp" |
||||||
|
|
||||||
|
|
||||||
|
#define LBPF_NAME "lbpFeatureParams" |
||||||
|
|
||||||
|
namespace cv { |
||||||
|
namespace xobjdetect { |
||||||
|
|
||||||
|
struct CvLBPFeatureParams : CvFeatureParams |
||||||
|
{ |
||||||
|
CvLBPFeatureParams(); |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
class CvLBPEvaluator : public CvFeatureEvaluator |
||||||
|
{ |
||||||
|
public: |
||||||
|
virtual ~CvLBPEvaluator() {} |
||||||
|
virtual void init(const CvFeatureParams *_featureParams, |
||||||
|
int _maxSampleCount, cv::Size _winSize ); |
||||||
|
virtual void setImage(const cv::Mat& img, uchar clsLabel, int idx, const std::vector<int> &feature_ind); |
||||||
|
virtual void setWindow(const cv::Point& p) |
||||||
|
{ cur_sum = sum.rowRange(p.y, p.y + winSize.height).colRange(p.x, p.x + winSize.width); } |
||||||
|
virtual float operator()(int featureIdx) |
||||||
|
{ return (float)features[featureIdx].calc( cur_sum ); } |
||||||
|
virtual void writeFeatures( cv::FileStorage &fs, const cv::Mat& featureMap ) const; |
||||||
|
protected: |
||||||
|
virtual void generateFeatures(); |
||||||
|
|
||||||
|
class Feature |
||||||
|
{ |
||||||
|
public: |
||||||
|
Feature(); |
||||||
|
Feature( int offset, int x, int y, int _block_w, int _block_h ); |
||||||
|
uchar calc( const cv::Mat& _sum ); |
||||||
|
void write( cv::FileStorage &fs ) const; |
||||||
|
|
||||||
|
cv::Rect rect; |
||||||
|
int p[16]; |
||||||
|
|
||||||
|
int x_, y_, block_w_, block_h_, offset_; |
||||||
|
void calcPoints(int offset); |
||||||
|
}; |
||||||
|
std::vector<Feature> features; |
||||||
|
|
||||||
|
cv::Mat sum, cur_sum; |
||||||
|
int offset_; |
||||||
|
}; |
||||||
|
|
||||||
|
inline uchar CvLBPEvaluator::Feature::calc(const cv::Mat &_sum) |
||||||
|
{ |
||||||
|
const int* psum = _sum.ptr<int>(); |
||||||
|
|
||||||
|
int cval = psum[p[5]] - psum[p[6]] - psum[p[9]] + psum[p[10]]; |
||||||
|
|
||||||
|
return (uchar)((psum[p[0]] - psum[p[1]] - psum[p[4]] + psum[p[5]] >= cval ? 128 : 0) | // 0
|
||||||
|
(psum[p[1]] - psum[p[2]] - psum[p[5]] + psum[p[6]] >= cval ? 64 : 0) | // 1
|
||||||
|
(psum[p[2]] - psum[p[3]] - psum[p[6]] + psum[p[7]] >= cval ? 32 : 0) | // 2
|
||||||
|
(psum[p[6]] - psum[p[7]] - psum[p[10]] + psum[p[11]] >= cval ? 16 : 0) | // 5
|
||||||
|
(psum[p[10]] - psum[p[11]] - psum[p[14]] + psum[p[15]] >= cval ? 8 : 0) | // 8
|
||||||
|
(psum[p[9]] - psum[p[10]] - psum[p[13]] + psum[p[14]] >= cval ? 4 : 0) | // 7
|
||||||
|
(psum[p[8]] - psum[p[9]] - psum[p[12]] + psum[p[13]] >= cval ? 2 : 0) | // 6
|
||||||
|
(psum[p[4]] - psum[p[5]] - psum[p[8]] + psum[p[9]] >= cval ? 1 : 0)); // 3
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -1,236 +0,0 @@ |
|||||||
/*
|
|
||||||
|
|
||||||
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); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//fast log implementation. A bit less accurate but ~5x faster
|
|
||||||
inline float fast_log2 (float val) |
|
||||||
{ |
|
||||||
int * const exp_ptr = reinterpret_cast <int *> (&val); |
|
||||||
int x = *exp_ptr; |
|
||||||
const int log_2 = ((x >> 23) & 255) - 128; |
|
||||||
x &= ~(255 << 23); |
|
||||||
x += 127 << 23; |
|
||||||
*exp_ptr = x; |
|
||||||
|
|
||||||
val = ((-1.0f/3) * val + 2) * val - 2.0f/3; // (1)
|
|
||||||
|
|
||||||
return (val + log_2); |
|
||||||
}
|
|
||||||
|
|
||||||
inline float fast_log (const float &val) |
|
||||||
{ |
|
||||||
return (fast_log2 (val) * 0.69314718f); |
|
||||||
} |
|
||||||
|
|
||||||
int Stump::train(const Mat& data, const Mat& labels, const Mat& weights, const std::vector<int>& visited_features, bool use_fast_log) |
|
||||||
{ |
|
||||||
CV_Assert(labels.rows == 1 && labels.cols == data.cols); |
|
||||||
CV_Assert(weights.rows == 1 && weights.cols == data.cols); |
|
||||||
CV_Assert(data.cols > 1); |
|
||||||
/* Assert that data and labels have int type */ |
|
||||||
/* Assert that weights have float type */ |
|
||||||
|
|
||||||
Mat_<int> d = Mat_<int>::zeros(1, data.cols); |
|
||||||
const Mat_<int>& l = labels; |
|
||||||
const Mat_<float>& w = weights; |
|
||||||
|
|
||||||
Mat_<int> indices(1, l.cols); |
|
||||||
|
|
||||||
Mat_<int> sorted_d(1, data.cols); |
|
||||||
Mat_<int> sorted_l(1, l.cols); |
|
||||||
Mat_<float> sorted_w(1, w.cols); |
|
||||||
|
|
||||||
|
|
||||||
Mat_<float> pos_c_w = Mat_<float>::zeros(1, w.cols); |
|
||||||
Mat_<float> neg_c_w = Mat_<float>::zeros(1, w.cols); |
|
||||||
|
|
||||||
|
|
||||||
float min_err = FLT_MAX; |
|
||||||
int min_row = -1; |
|
||||||
int min_thr = -1; |
|
||||||
int min_pol = -1; |
|
||||||
float min_pos = 1; |
|
||||||
float min_neg = -1; |
|
||||||
float eps = 1.0f / (4 * l.cols); |
|
||||||
|
|
||||||
/* For every feature */ |
|
||||||
for( int row = 0; row < data.rows; ++row ) |
|
||||||
{ |
|
||||||
if(std::find(visited_features.begin(), visited_features.end(), row) != visited_features.end()) { |
|
||||||
//feature discarded
|
|
||||||
continue; |
|
||||||
} |
|
||||||
data.row(row).copyTo(d.row(0)); |
|
||||||
|
|
||||||
sortIdx(d, indices, cv::SORT_EVERY_ROW | cv::SORT_ASCENDING); |
|
||||||
|
|
||||||
for( int col = 0; col < indices.cols; ++col ) |
|
||||||
{ |
|
||||||
int ind = indices(0, col); |
|
||||||
sorted_d(0, col) = d(0, ind); |
|
||||||
sorted_l(0, col) = l(0, ind); |
|
||||||
sorted_w(0, col) = w(0, ind); |
|
||||||
} |
|
||||||
|
|
||||||
Mat_<float> pos_w = Mat_<float>::zeros(1, w.cols); |
|
||||||
Mat_<float> neg_w = Mat_<float>::zeros(1, w.cols); |
|
||||||
for( int col = 0; col < d.cols; ++col ) |
|
||||||
{ |
|
||||||
float weight = sorted_w(0, col); |
|
||||||
if( sorted_l(0, col) == +1) |
|
||||||
pos_w(0, col) = weight; |
|
||||||
else |
|
||||||
neg_w(0, col) = weight; |
|
||||||
} |
|
||||||
|
|
||||||
cumsum(pos_w, pos_c_w); |
|
||||||
cumsum(neg_w, neg_c_w); |
|
||||||
|
|
||||||
float pos_total_w = pos_c_w(0, w.cols - 1); |
|
||||||
float neg_total_w = neg_c_w(0, w.cols - 1); |
|
||||||
|
|
||||||
for( int col = 0; col < w.cols - 1; ++col ) |
|
||||||
{ |
|
||||||
float err, h_pos, h_neg; |
|
||||||
float pos_wrong, pos_right; |
|
||||||
float neg_wrong, neg_right; |
|
||||||
|
|
||||||
/* Direct polarity */ |
|
||||||
|
|
||||||
pos_wrong = pos_c_w(0, col); |
|
||||||
pos_right = pos_total_w - pos_wrong; |
|
||||||
|
|
||||||
neg_right = neg_c_w(0, col); |
|
||||||
neg_wrong = neg_total_w - neg_right; |
|
||||||
|
|
||||||
err = sqrt(pos_right * neg_wrong) + sqrt(pos_wrong * neg_right); |
|
||||||
|
|
||||||
if(use_fast_log) |
|
||||||
{ |
|
||||||
h_pos = .5f * fast_log((pos_right + eps) / (pos_wrong + eps)); |
|
||||||
h_neg = .5f * fast_log((neg_wrong + eps) / (neg_right + eps)); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
h_pos = .5f * log((pos_right + eps) / (pos_wrong + eps)); |
|
||||||
h_neg = .5f * log((neg_wrong + eps) / (neg_right + eps)); |
|
||||||
} |
|
||||||
|
|
||||||
if( err < min_err ) |
|
||||||
{ |
|
||||||
min_err = err; |
|
||||||
min_row = row; |
|
||||||
min_thr = (sorted_d(0, col) + sorted_d(0, col + 1)) / 2; |
|
||||||
min_pol = +1; |
|
||||||
min_pos = h_pos; |
|
||||||
min_neg = h_neg; |
|
||||||
} |
|
||||||
|
|
||||||
/* Opposite polarity */ |
|
||||||
|
|
||||||
swap(pos_right, pos_wrong); |
|
||||||
swap(neg_right, neg_wrong); |
|
||||||
|
|
||||||
err = sqrt(pos_right * neg_wrong) + sqrt(pos_wrong * neg_right); |
|
||||||
|
|
||||||
if( err < min_err ) |
|
||||||
{ |
|
||||||
min_err = err; |
|
||||||
min_row = row; |
|
||||||
min_thr = (sorted_d(0, col) + sorted_d(0, col + 1)) / 2; |
|
||||||
min_pol = -1; |
|
||||||
min_pos = -h_pos; |
|
||||||
min_neg = -h_neg; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
threshold_ = min_thr; |
|
||||||
polarity_ = min_pol; |
|
||||||
pos_value_ = min_pos; |
|
||||||
neg_value_ = min_neg; |
|
||||||
|
|
||||||
return min_row; |
|
||||||
} |
|
||||||
|
|
||||||
float Stump::predict(int value) const |
|
||||||
{ |
|
||||||
return polarity_ * (value - threshold_) > 0 ? pos_value_ : neg_value_; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void read(const FileNode& node, Stump& s, const Stump& default_value) |
|
||||||
{ |
|
||||||
if( node.empty() ) |
|
||||||
s = default_value; |
|
||||||
else |
|
||||||
s.read(node); |
|
||||||
} |
|
||||||
|
|
||||||
void write(FileStorage& fs, String&, const Stump& s) |
|
||||||
{ |
|
||||||
s.write(fs); |
|
||||||
} |
|
||||||
|
|
||||||
} /* namespace xobjdetect */ |
|
||||||
} /* namespace cv */ |
|
@ -0,0 +1,94 @@ |
|||||||
|
/*
|
||||||
|
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) 2000-2015, Intel Corporation, all rights reserved. |
||||||
|
Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. |
||||||
|
Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. |
||||||
|
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. |
||||||
|
Copyright (C) 2015, OpenCV Foundation, all rights reserved. |
||||||
|
Copyright (C) 2015, Itseez Inc., 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_WALDBOOST_HPP__ |
||||||
|
#define __OPENCV_XOBJDETECT_WALDBOOST_HPP__ |
||||||
|
|
||||||
|
#include "precomp.hpp" |
||||||
|
|
||||||
|
namespace cv { |
||||||
|
namespace xobjdetect { |
||||||
|
|
||||||
|
class WaldBoost { |
||||||
|
public: |
||||||
|
WaldBoost(int weak_count); |
||||||
|
WaldBoost(); |
||||||
|
std::vector<int> get_feature_indices(); |
||||||
|
|
||||||
|
void detect(Ptr<CvFeatureEvaluator> eval, |
||||||
|
const Mat& img, |
||||||
|
const std::vector<float>& scales, |
||||||
|
std::vector<Rect>& bboxes, |
||||||
|
Mat1f& confidences); |
||||||
|
|
||||||
|
void detect(Ptr<CvFeatureEvaluator> eval, |
||||||
|
const Mat& img, |
||||||
|
const std::vector<float>& scales, |
||||||
|
std::vector<Rect>& bboxes, |
||||||
|
std::vector<double>& confidences); |
||||||
|
|
||||||
|
void fit(Mat& data_pos, Mat& data_neg); |
||||||
|
int predict(Ptr<CvFeatureEvaluator> eval, float *h) const; |
||||||
|
void save(const std::string& filename); |
||||||
|
void load(const std::string& filename); |
||||||
|
|
||||||
|
void read(const FileNode &node); |
||||||
|
void write(FileStorage &fs) const; |
||||||
|
|
||||||
|
void reset(int weak_count); |
||||||
|
~WaldBoost(); |
||||||
|
|
||||||
|
private: |
||||||
|
int weak_count_; |
||||||
|
std::vector<float> thresholds_; |
||||||
|
std::vector<float> alphas_; |
||||||
|
std::vector<int> feature_indices_; |
||||||
|
std::vector<int> polarities_; |
||||||
|
std::vector<float> cascade_thresholds_; |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,222 @@ |
|||||||
|
/*
|
||||||
|
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) 2000-2015, Intel Corporation, all rights reserved. |
||||||
|
Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. |
||||||
|
Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. |
||||||
|
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. |
||||||
|
Copyright (C) 2015, OpenCV Foundation, all rights reserved. |
||||||
|
Copyright (C) 2015, Itseez Inc., 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::cerr; |
||||||
|
using std::endl; |
||||||
|
using std::vector; |
||||||
|
using std::string; |
||||||
|
|
||||||
|
namespace cv { |
||||||
|
namespace xobjdetect { |
||||||
|
|
||||||
|
static vector<Mat> sample_patches( |
||||||
|
const string& path, |
||||||
|
int n_rows, |
||||||
|
int n_cols, |
||||||
|
size_t n_patches) |
||||||
|
{ |
||||||
|
vector<String> filenames; |
||||||
|
glob(path, filenames); |
||||||
|
vector<Mat> patches; |
||||||
|
size_t patch_count = 0; |
||||||
|
for (size_t i = 0; i < filenames.size(); ++i) { |
||||||
|
Mat img = imread(filenames[i], CV_LOAD_IMAGE_GRAYSCALE); |
||||||
|
for (int row = 0; row + n_rows < img.rows; row += n_rows) { |
||||||
|
for (int col = 0; col + n_cols < img.cols; col += n_cols) { |
||||||
|
patches.push_back(img(Rect(col, row, n_cols, n_rows)).clone()); |
||||||
|
patch_count += 1; |
||||||
|
if (patch_count == n_patches) { |
||||||
|
goto sampling_finished; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
sampling_finished: |
||||||
|
return patches; |
||||||
|
} |
||||||
|
|
||||||
|
static vector<Mat> read_imgs(const string& path) |
||||||
|
{ |
||||||
|
vector<String> filenames; |
||||||
|
glob(path, filenames); |
||||||
|
vector<Mat> imgs; |
||||||
|
for (size_t i = 0; i < filenames.size(); ++i) { |
||||||
|
imgs.push_back(imread(filenames[i], CV_LOAD_IMAGE_GRAYSCALE)); |
||||||
|
} |
||||||
|
return imgs; |
||||||
|
} |
||||||
|
|
||||||
|
void WBDetectorImpl::read(const FileNode& node) |
||||||
|
{ |
||||||
|
boost_.read(node); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void WBDetectorImpl::write(FileStorage &fs) const |
||||||
|
{ |
||||||
|
boost_.write(fs); |
||||||
|
} |
||||||
|
|
||||||
|
void WBDetectorImpl::train( |
||||||
|
const string& pos_samples_path, |
||||||
|
const string& neg_imgs_path) |
||||||
|
{ |
||||||
|
|
||||||
|
vector<Mat> pos_imgs = read_imgs(pos_samples_path); |
||||||
|
vector<Mat> neg_imgs = sample_patches(neg_imgs_path, 24, 24, pos_imgs.size() * 10); |
||||||
|
|
||||||
|
assert(pos_imgs.size()); |
||||||
|
assert(neg_imgs.size()); |
||||||
|
|
||||||
|
int n_features; |
||||||
|
Mat pos_data, neg_data; |
||||||
|
|
||||||
|
Ptr<CvFeatureEvaluator> eval = CvFeatureEvaluator::create(); |
||||||
|
eval->init(CvFeatureParams::create(), 1, Size(24, 24)); |
||||||
|
n_features = eval->getNumFeatures(); |
||||||
|
|
||||||
|
const int stages[] = {64, 128, 256, 512, 1024}; |
||||||
|
const int stage_count = sizeof(stages) / sizeof(*stages); |
||||||
|
const int stage_neg = (int)(pos_imgs.size() * 5); |
||||||
|
const int max_per_image = 100; |
||||||
|
|
||||||
|
const float scales_arr[] = {.3f, .4f, .5f, .6f, .7f, .8f, .9f, 1.0f}; |
||||||
|
const vector<float> scales(scales_arr, |
||||||
|
scales_arr + sizeof(scales_arr) / sizeof(*scales_arr)); |
||||||
|
|
||||||
|
vector<String> neg_filenames; |
||||||
|
glob(neg_imgs_path, neg_filenames); |
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < stage_count; ++i) { |
||||||
|
|
||||||
|
cerr << "compute features" << endl; |
||||||
|
|
||||||
|
pos_data = Mat1b(n_features, (int)pos_imgs.size()); |
||||||
|
neg_data = Mat1b(n_features, (int)neg_imgs.size()); |
||||||
|
|
||||||
|
for (size_t k = 0; k < pos_imgs.size(); ++k) { |
||||||
|
eval->setImage(pos_imgs[k], +1, 0, boost_.get_feature_indices()); |
||||||
|
for (int j = 0; j < n_features; ++j) { |
||||||
|
pos_data.at<uchar>(j, (int)k) = (uchar)(*eval)(j); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
for (size_t k = 0; k < neg_imgs.size(); ++k) { |
||||||
|
eval->setImage(neg_imgs[k], 0, 0, boost_.get_feature_indices()); |
||||||
|
for (int j = 0; j < n_features; ++j) { |
||||||
|
neg_data.at<uchar>(j, (int)k) = (uchar)(*eval)(j); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
boost_.reset(stages[i]); |
||||||
|
boost_.fit(pos_data, neg_data); |
||||||
|
|
||||||
|
if (i + 1 == stage_count) { |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
int bootstrap_count = 0; |
||||||
|
size_t img_i = 0; |
||||||
|
for (; img_i < neg_filenames.size(); ++img_i) { |
||||||
|
cerr << "win " << bootstrap_count << "/" << stage_neg |
||||||
|
<< " img " << (img_i + 1) << "/" << neg_filenames.size() << "\r"; |
||||||
|
Mat img = imread(neg_filenames[img_i], CV_LOAD_IMAGE_GRAYSCALE); |
||||||
|
vector<Rect> bboxes; |
||||||
|
Mat1f confidences; |
||||||
|
boost_.detect(eval, img, scales, bboxes, confidences); |
||||||
|
|
||||||
|
if (confidences.rows > 0) { |
||||||
|
Mat1i indices; |
||||||
|
sortIdx(confidences, indices, |
||||||
|
CV_SORT_EVERY_COLUMN + CV_SORT_DESCENDING); |
||||||
|
|
||||||
|
int win_count = min(max_per_image, confidences.rows); |
||||||
|
win_count = min(win_count, stage_neg - bootstrap_count); |
||||||
|
Mat window; |
||||||
|
for (int k = 0; k < win_count; ++k) { |
||||||
|
resize(img(bboxes[indices(k, 0)]), window, Size(24, 24)); |
||||||
|
neg_imgs.push_back(window.clone()); |
||||||
|
bootstrap_count += 1; |
||||||
|
} |
||||||
|
if (bootstrap_count >= stage_neg) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
cerr << "bootstrapped " << bootstrap_count << " windows from " |
||||||
|
<< (img_i + 1) << " images" << endl; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void WBDetectorImpl::detect( |
||||||
|
const Mat& img, |
||||||
|
vector<Rect> &bboxes, |
||||||
|
vector<double> &confidences) |
||||||
|
{ |
||||||
|
Mat test_img = img.clone(); |
||||||
|
bboxes.clear(); |
||||||
|
confidences.clear(); |
||||||
|
vector<float> scales; |
||||||
|
for (float scale = 0.2f; scale < 1.2f; scale *= 1.1f) { |
||||||
|
scales.push_back(scale); |
||||||
|
} |
||||||
|
Ptr<CvFeatureParams> params = CvFeatureParams::create(); |
||||||
|
Ptr<CvFeatureEvaluator> eval = CvFeatureEvaluator::create(); |
||||||
|
eval->init(params, 1, Size(24, 24)); |
||||||
|
boost_.detect(eval, img, scales, bboxes, confidences); |
||||||
|
assert(confidences.size() == bboxes.size()); |
||||||
|
} |
||||||
|
|
||||||
|
Ptr<WBDetector> |
||||||
|
WBDetector::create() |
||||||
|
{ |
||||||
|
return Ptr<WBDetector>(new WBDetectorImpl()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
add_subdirectory(waldboost_detector) |
@ -1,4 +1,4 @@ |
|||||||
set(name fcw_train) |
set(name waldboost_detector) |
||||||
set(the_target opencv_${name}) |
set(the_target opencv_${name}) |
||||||
|
|
||||||
set(OPENCV_${the_target}_DEPS opencv_core opencv_imgcodecs opencv_videoio |
set(OPENCV_${the_target}_DEPS opencv_core opencv_imgcodecs opencv_videoio |
@ -0,0 +1,46 @@ |
|||||||
|
#include <opencv2/xobjdetect.hpp> |
||||||
|
#include <opencv2/imgcodecs/imgcodecs_c.h> |
||||||
|
#include <opencv2/imgproc.hpp> |
||||||
|
#include <iostream> |
||||||
|
#include <cstdio> |
||||||
|
using namespace std; |
||||||
|
using namespace cv; |
||||||
|
using namespace cv::xobjdetect; |
||||||
|
|
||||||
|
int main(int argc, char **argv) |
||||||
|
{ |
||||||
|
if (argc < 5) { |
||||||
|
cerr << "Usage: " << argv[0] << " train <model_filename> <pos_path> <neg_path>" << endl; |
||||||
|
cerr << " " << argv[0] << " detect <model_filename> <img_filename> <out_filename> <labelling_filename>" << endl; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
string mode = argv[1]; |
||||||
|
Ptr<WBDetector> detector = WBDetector::create(); |
||||||
|
if (mode == "train") { |
||||||
|
assert(argc == 5); |
||||||
|
detector->train(argv[3], argv[4]); |
||||||
|
FileStorage fs(argv[2], FileStorage::WRITE); |
||||||
|
fs << "waldboost"; |
||||||
|
detector->write(fs); |
||||||
|
} else if (mode == "detect") { |
||||||
|
assert(argc == 6); |
||||||
|
vector<Rect> bboxes; |
||||||
|
vector<double> confidences; |
||||||
|
Mat img = imread(argv[3], CV_LOAD_IMAGE_GRAYSCALE); |
||||||
|
FileStorage fs(argv[2], FileStorage::READ); |
||||||
|
detector->read(fs.getFirstTopLevelNode()); |
||||||
|
detector->detect(img, bboxes, confidences); |
||||||
|
|
||||||
|
FILE *fhandle = fopen(argv[5], "a"); |
||||||
|
for (size_t i = 0; i < bboxes.size(); ++i) { |
||||||
|
Rect o = bboxes[i]; |
||||||
|
fprintf(fhandle, "%s;%u;%u;%u;%u;%lf\n", |
||||||
|
argv[3], o.x, o.y, o.width, o.height, confidences[i]); |
||||||
|
} |
||||||
|
for (size_t i = 0; i < bboxes.size(); ++i) { |
||||||
|
rectangle(img, bboxes[i], Scalar(255, 0, 0)); |
||||||
|
} |
||||||
|
imwrite(argv[4], img); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue