Commit d06d7e29 authored by Vlad Shakhuro's avatar Vlad Shakhuro

Change of interface and multiple fixes

parent 3f1cce24
if(IOS)
ocv_module_disable(adas)
endif()
set(the_description "Automatic driver assistance algorithms")
ocv_define_module(adas opencv_xobjdetect)
add_subdirectory(tools)
ADAS: Advanced Driver Assistance Systems module with Forward Collision Warning
==============================================================================
\ No newline at end of file
add_subdirectory(fcw_train)
add_subdirectory(fcw_detect)
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)
#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));
}
#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(), &params.model_n_rows,
&params.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();
}
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)
......@@ -49,204 +49,28 @@ the use of this software, even if advised of the possibility of such damage.
/** @defgroup xobjdetect Extended object detection
*/
namespace cv
{
namespace xobjdetect
{
//! @addtogroup xobjdetect
//! @{
/** @brief Compute channels for integral channel features evaluation
@param image image for which channels should be computed
@param channels output array for computed channels
*/
CV_EXPORTS void computeChannels(InputArray image, std::vector<Mat>& channels);
/** @brief Feature evaluation interface
*/
class CV_EXPORTS FeatureEvaluator : public Algorithm
{
public:
/** @brief Set channels for feature evaluation
@param channels array of channels to be set
*/
virtual void setChannels(InputArrayOfArrays channels) = 0;
/** @brief Set window position to sample features with shift. By default position is (0, 0).
@param position position to be set
*/
virtual void setPosition(Size position) = 0;
/** @brief Evaluate feature value with given index for current channels and window position.
@param feature_ind index of feature to be evaluated
*/
virtual int evaluate(size_t feature_ind) const = 0;
/** @brief Evaluate all features for current channels and window position.
@param feature_values matrix-column of evaluated feature values
*/
virtual void evaluateAll(OutputArray feature_values) const = 0;
virtual void assertChannels() = 0;
};
/** @brief Construct feature evaluator.
@param features features for evaluation
@param type feature type. Can be "icf" or "acf"
*/
CV_EXPORTS Ptr<FeatureEvaluator>
createFeatureEvaluator(const std::vector<std::vector<int> >& features,
const std::string& type);
/** @brief Generate integral features. Returns vector of features.
@param window_size size of window in which features should be evaluated
@param type feature type. Can be "icf" or "acf"
@param count number of features to generate.
@param channel_count number of feature channels
*/
std::vector<std::vector<int> >
generateFeatures(Size window_size, const std::string& type,
int count = INT_MAX, int channel_count = 10);
//sort in-place of columns of the input matrix
void sort_columns_without_copy(Mat& m, Mat indices = Mat());
/** @brief Parameters for WaldBoost. weak_count — number of weak learners, alpha — cascade thresholding param.
*/
struct CV_EXPORTS WaldBoostParams
{
int weak_count;
float alpha;
WaldBoostParams(): weak_count(100), alpha(0.02f)
{}
};
/** @brief WaldBoost object detector from @cite Sochman05 .
*/
class CV_EXPORTS WaldBoost : public Algorithm
{
class CV_EXPORTS WBDetector {
public:
/** @brief Train WaldBoost cascade for given data.
Returns feature indices chosen for cascade. Feature enumeration starts from 0.
@param data matrix of feature values, size M x N, one feature per row
@param labels matrix of samples class labels, size 1 x N. Labels can be from {-1, +1}
@param use_fast_log
*/
virtual std::vector<int> train(Mat& data,
const Mat& labels, bool use_fast_log=false) = 0;
/** @brief Predict objects class given object that can compute object features.
Returns unnormed confidence value — measure of confidence that object is from class +1.
@param feature_evaluator object that can compute features by demand
*/
virtual float predict(
const Ptr<FeatureEvaluator>& feature_evaluator) const = 0;
};
WBDetector(const std::string& model_filename);
/** @brief Construct WaldBoost object.
*/
CV_EXPORTS Ptr<WaldBoost>
createWaldBoost(const WaldBoostParams& params = WaldBoostParams());
void train(
const std::string& pos_samples,
const std::string& neg_imgs);
/** @brief Params for ICFDetector training.
*/
struct CV_EXPORTS ICFDetectorParams
{
int feature_count;
int weak_count;
int model_n_rows;
int model_n_cols;
int bg_per_image;
std::string features_type;
float alpha;
bool is_grayscale;
bool use_fast_log;
ICFDetectorParams(): feature_count(UINT_MAX), weak_count(100),
model_n_rows(56), model_n_cols(56), bg_per_image(5), alpha(0.02f), is_grayscale(false), use_fast_log(false)
{}
};
/** @brief Integral Channel Features from @cite Dollar09 .
*/
class CV_EXPORTS ICFDetector
{
public:
ICFDetector(): waldboost_(), features_(), ftype_() {}
/** @brief Train detector.
@param pos_filenames path to folder with images of objects (wildcards like /my/path/\*.png are allowed)
@param bg_filenames path to folder with background images
@param params parameters for detector training
*/
void train(const std::vector<String>& pos_filenames,
const std::vector<String>& bg_filenames,
ICFDetectorParams params = ICFDetectorParams());
/** @brief Detect objects on image.
@param image image for detection
@param objects output array of bounding boxes
@param scaleFactor scale between layers in detection pyramid
@param minSize min size of objects in pixels
@param maxSize max size of objects in pixels
@param threshold
@param slidingStep sliding window step
@param values output vector with values of positive samples
*/
void detect(const Mat& image, std::vector<Rect>& objects,
float scaleFactor, Size minSize, Size maxSize, float threshold, int slidingStep, std::vector<float>& values);
/** @brief Detect objects on image.
@param img image for detection
@param objects output array of bounding boxes
@param minScaleFactor min factor by which the image will be resized
@param maxScaleFactor max factor by which the image will be resized
@param factorStep scaling factor is incremented each pyramid layer according to this parameter
@param threshold
@param slidingStep sliding window step
@param values output vector with values of positive samples
*/
void detect(const Mat& img, std::vector<Rect>& objects, float minScaleFactor, float maxScaleFactor, float factorStep, float threshold, int slidingStep, std::vector<float>& values);
/** @brief Write detector to FileStorage.
@param fs FileStorage for output
*/
void write(FileStorage &fs) const;
/** @brief Write ICFDetector to FileNode
@param node FileNode for reading
*/
void read(const FileNode &node);
void detect(
const Mat& img,
std::vector<Rect> &bboxes,
std::vector<double> &confidences);
private:
Ptr<WaldBoost> waldboost_;
std::vector<std::vector<int> > features_;
int model_n_rows_;
int model_n_cols_;
std::string ftype_;
std::string model_filename_;
};
CV_EXPORTS void write(FileStorage& fs, String&, const ICFDetector& detector);
CV_EXPORTS void read(const FileNode& node, ICFDetector& d,
const ICFDetector& default_value = ICFDetector());
//! @}
} /* namespace xobjdetect */
} /* namespace cv */
......
#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__
This diff is collapsed.
/*
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_
......
/*
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 {
WBDetector::WBDetector(const string& model_filename):
model_filename_(model_filename)
{}
static vector<Mat> sample_patches(
const string& path,
int n_rows,
int n_cols,
int n_patches)
{
vector<String> filenames;
glob(path, filenames);
vector<Mat> patches;
int 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 WBDetector::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());
assert(pos_imgs.size());
assert(neg_imgs.size());
int n_features;
Mat pos_data, neg_data;
Ptr<CvFeatureEvaluator> eval = CvFeatureEvaluator::create(CvFeatureParams::LBP);
eval->init(CvFeatureParams::create(CvFeatureParams::LBP), 1, Size(24, 24));
n_features = eval->getNumFeatures();
const int stages[] = {32, 64, 128, 256, 512, 1024, 2048, 4096};
const int stage_count = sizeof(stages) / sizeof(*stages);
const int stage_neg = 5000;
const int max_per_image = 25;
const float scales_arr[] = {.3, .4, .5, .6, .7, .8, .9, 1};
const vector<float> scales(scales_arr,
scales_arr + sizeof(scales_arr) / sizeof(*scales_arr));
WaldBoost boost;
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, pos_imgs.size());
neg_data = Mat1b(n_features, 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, k) = (*eval)(j, 0);
}
}
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, k) = (*eval)(j, 0);
}
}
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;
}
boost.save(model_filename_);
}
void WBDetector::detect(
const Mat& img,
vector<Rect> &bboxes,
vector<double> &confidences)
{
WaldBoost boost;
boost.load(model_filename_);
Mat test_img = img.clone();
bboxes.clear();
confidences.clear();
vector<float> scales;
for (float scale = 0.2f; scale < 1.2f; scale *= 1.1) {
scales.push_back(scale);
}
Ptr<CvFeatureParams> params = CvFeatureParams::create(CvFeatureParams::LBP);
Ptr<CvFeatureEvaluator> eval = CvFeatureEvaluator::create(CvFeatureParams::LBP);
eval->init(params, 1, Size(24, 24));
boost.detect(eval, img, scales, bboxes, confidences);
assert(confidences.size() == bboxes.size());
}
}
}
#include <opencv2/opencv.hpp>
/*
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.
#include "traincascade_features.h"
#include "cascadeclassifier.h"
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 namespace std;
using namespace cv;
......
This diff is collapsed.
#include <opencv2/opencv.hpp>
#include "lbpfeatures.h"
#include "cascadeclassifier.h"
/*
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.
#include <iostream>
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 namespace cv;
......
/*
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_
......
This diff is collapsed.
/*
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,
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.
......@@ -9,7 +8,12 @@ copy or use the software.
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
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,
......@@ -28,31 +32,48 @@ are permitted provided that the following conditions are met:
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
warranties of merchantability and fitness for a particular purpose are disclaimed.
In no event shall copyright holders or contributors be liable for any direct,
indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
*/
#ifndef __OPENCV_XOBJDETECT_PRECOMP_HPP__
#define __OPENCV_XOBJDETECT_PRECOMP_HPP__
#include <opencv2/xobjdetect.hpp>
#include <opencv2/xobjdetect/private.hpp>
#include <opencv2/core/utility.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgproc/types_c.h>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgcodecs/imgcodecs_c.h>
#include <opencv2/objdetect.hpp>
#include <algorithm>
#include <vector>
#include <string>
#include <cmath>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <cassert>
#include <cstdio>
#include "cascadeclassifier.h"
#include "traincascade_features.h"
#include "lbpfeatures.h"
#include "waldboost.hpp"
#endif /* __OPENCV_XOBJDETECT_PRECOMP_HPP__ */
/*
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 */
/*
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_
......
This diff is collapsed.
/*
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,
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.
......@@ -9,7 +8,12 @@ copy or use the software.
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
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,
......@@ -28,17 +32,57 @@ are permitted provided that the following conditions are met:
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
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.
*/
/** @defgroup adas Advanced Driver Assistance
*/
#ifndef __OPENCV_XOBJDETECT_WALDBOOST_HPP__
#define __OPENCV_XOBJDETECT_WALDBOOST_HPP__
#include "precomp.hpp"
namespace cv {
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 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
add_subdirectory(waldboost_detector)
set(name fcw_train)
set(name waldboost_detector)
set(the_target opencv_${name})
set(OPENCV_${the_target}_DEPS opencv_core opencv_imgcodecs opencv_videoio
......
#include <opencv2/xobjdetect.hpp>
#include <opencv2/imgcodecs/imgcodecs_c.h>
#include <opencv2/imgproc.hpp>
#include <iostream>
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>" << endl;
return 0;
}
string mode = argv[1];
WBDetector detector(argv[2]);
if (mode == "train") {
detector.train(argv[3], argv[4]);
} else if (mode == "detect") {
cerr << "detect" << endl;
vector<Rect> bboxes;
vector<double> confidences;
Mat img = imread(argv[3], CV_LOAD_IMAGE_GRAYSCALE);
detector.detect(img, bboxes, confidences);
for (size_t i = 0; i < bboxes.size(); ++i) {
rectangle(img, bboxes[i], Scalar(255, 0, 0));
}
imwrite(argv[4], img);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment