Merge pull request #322 from cuda-geek:training
This commit is contained in:
commit
f52ce6529b
@ -1,2 +1,4 @@
|
||||
add_subdirectory(haartraining)
|
||||
add_subdirectory(traincascade)
|
||||
add_subdirectory(sft)
|
||||
|
||||
|
33
apps/sft/CMakeLists.txt
Normal file
33
apps/sft/CMakeLists.txt
Normal file
@ -0,0 +1,33 @@
|
||||
set(name sft)
|
||||
set(the_target opencv_${name})
|
||||
|
||||
set(OPENCV_${the_target}_DEPS opencv_core opencv_softcascade opencv_highgui opencv_imgproc opencv_ml)
|
||||
ocv_check_dependencies(${OPENCV_${the_target}_DEPS})
|
||||
|
||||
if(NOT OCV_DEPENDENCIES_FOUND)
|
||||
return()
|
||||
endif()
|
||||
|
||||
project(${the_target})
|
||||
|
||||
ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" "${OpenCV_SOURCE_DIR}/include/opencv")
|
||||
ocv_include_modules(${OPENCV_${the_target}_DEPS})
|
||||
|
||||
file(GLOB ${the_target}_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
|
||||
|
||||
add_executable(${the_target} ${${the_target}_SOURCES})
|
||||
|
||||
target_link_libraries(${the_target} ${OPENCV_${the_target}_DEPS})
|
||||
|
||||
set_target_properties(${the_target} PROPERTIES
|
||||
DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
|
||||
INSTALL_NAME_DIR lib
|
||||
OUTPUT_NAME "opencv_trainsoftcascade")
|
||||
|
||||
if(ENABLE_SOLUTION_FOLDERS)
|
||||
set_target_properties(${the_target} PROPERTIES FOLDER "applications")
|
||||
endif()
|
||||
|
||||
install(TARGETS ${the_target} RUNTIME DESTINATION bin COMPONENT main)
|
159
apps/sft/config.cpp
Normal file
159
apps/sft/config.cpp
Normal file
@ -0,0 +1,159 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2012, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include <sft/config.hpp>
|
||||
#include <iomanip>
|
||||
|
||||
sft::Config::Config(): seed(0) {}
|
||||
|
||||
void sft::Config::write(cv::FileStorage& fs) const
|
||||
{
|
||||
fs << "{"
|
||||
<< "trainPath" << trainPath
|
||||
<< "testPath" << testPath
|
||||
|
||||
<< "modelWinSize" << modelWinSize
|
||||
<< "offset" << offset
|
||||
<< "octaves" << octaves
|
||||
|
||||
<< "positives" << positives
|
||||
<< "negatives" << negatives
|
||||
<< "btpNegatives" << btpNegatives
|
||||
|
||||
<< "shrinkage" << shrinkage
|
||||
|
||||
<< "treeDepth" << treeDepth
|
||||
<< "weaks" << weaks
|
||||
<< "poolSize" << poolSize
|
||||
|
||||
<< "cascadeName" << cascadeName
|
||||
<< "outXmlPath" << outXmlPath
|
||||
|
||||
<< "seed" << seed
|
||||
<< "}";
|
||||
}
|
||||
|
||||
void sft::Config::read(const cv::FileNode& node)
|
||||
{
|
||||
trainPath = (string)node["trainPath"];
|
||||
testPath = (string)node["testPath"];
|
||||
|
||||
cv::FileNodeIterator nIt = node["modelWinSize"].end();
|
||||
modelWinSize = cv::Size((int)*(--nIt), (int)*(--nIt));
|
||||
|
||||
nIt = node["offset"].end();
|
||||
offset = cv::Point2i((int)*(--nIt), (int)*(--nIt));
|
||||
|
||||
node["octaves"] >> octaves;
|
||||
|
||||
positives = (int)node["positives"];
|
||||
negatives = (int)node["negatives"];
|
||||
btpNegatives = (int)node["btpNegatives"];
|
||||
|
||||
shrinkage = (int)node["shrinkage"];
|
||||
|
||||
treeDepth = (int)node["treeDepth"];
|
||||
weaks = (int)node["weaks"];
|
||||
poolSize = (int)node["poolSize"];
|
||||
|
||||
cascadeName = (std::string)node["cascadeName"];
|
||||
outXmlPath = (std::string)node["outXmlPath"];
|
||||
|
||||
seed = (int)node["seed"];
|
||||
}
|
||||
|
||||
void sft::write(cv::FileStorage& fs, const string&, const Config& x)
|
||||
{
|
||||
x.write(fs);
|
||||
}
|
||||
|
||||
void sft::read(const cv::FileNode& node, Config& x, const Config& default_value)
|
||||
{
|
||||
x = default_value;
|
||||
|
||||
if(!node.empty())
|
||||
x.read(node);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct Out
|
||||
{
|
||||
Out(std::ostream& _out): out(_out) {}
|
||||
template<typename T>
|
||||
void operator ()(const T a) const {out << a << " ";}
|
||||
|
||||
std::ostream& out;
|
||||
private:
|
||||
Out& operator=(Out const& other);
|
||||
};
|
||||
}
|
||||
|
||||
std::ostream& sft::operator<<(std::ostream& out, const Config& m)
|
||||
{
|
||||
out << std::setw(14) << std::left << "trainPath" << m.trainPath << std::endl
|
||||
<< std::setw(14) << std::left << "testPath" << m.testPath << std::endl
|
||||
|
||||
<< std::setw(14) << std::left << "modelWinSize" << m.modelWinSize << std::endl
|
||||
<< std::setw(14) << std::left << "offset" << m.offset << std::endl
|
||||
<< std::setw(14) << std::left << "octaves";
|
||||
|
||||
Out o(out);
|
||||
for_each(m.octaves.begin(), m.octaves.end(), o);
|
||||
|
||||
out << std::endl
|
||||
<< std::setw(14) << std::left << "positives" << m.positives << std::endl
|
||||
<< std::setw(14) << std::left << "negatives" << m.negatives << std::endl
|
||||
<< std::setw(14) << std::left << "btpNegatives" << m.btpNegatives << std::endl
|
||||
|
||||
<< std::setw(14) << std::left << "shrinkage" << m.shrinkage << std::endl
|
||||
|
||||
<< std::setw(14) << std::left << "treeDepth" << m.treeDepth << std::endl
|
||||
<< std::setw(14) << std::left << "weaks" << m.weaks << std::endl
|
||||
<< std::setw(14) << std::left << "poolSize" << m.poolSize << std::endl
|
||||
|
||||
<< std::setw(14) << std::left << "cascadeName" << m.cascadeName << std::endl
|
||||
<< std::setw(14) << std::left << "outXmlPath" << m.outXmlPath << std::endl
|
||||
<< std::setw(14) << std::left << "seed" << m.seed << std::endl;
|
||||
|
||||
return out;
|
||||
}
|
161
apps/sft/dataset.cpp
Normal file
161
apps/sft/dataset.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2012, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include <sft/dataset.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
|
||||
inline std::string itoa(long i) { return cv::format("%ld", i); }
|
||||
|
||||
#if !defined (_WIN32) && ! defined(__MINGW32__)
|
||||
# include <glob.h>
|
||||
|
||||
namespace {
|
||||
using namespace sft;
|
||||
void glob(const string& path, svector& ret)
|
||||
{
|
||||
glob_t glob_result;
|
||||
glob(path.c_str(), GLOB_TILDE, 0, &glob_result);
|
||||
|
||||
ret.clear();
|
||||
ret.reserve(glob_result.gl_pathc);
|
||||
|
||||
for(unsigned int i = 0; i < glob_result.gl_pathc; ++i)
|
||||
{
|
||||
ret.push_back(std::string(glob_result.gl_pathv[i]));
|
||||
dprintf("%s\n", ret[i].c_str());
|
||||
}
|
||||
|
||||
globfree(&glob_result);
|
||||
}
|
||||
|
||||
}
|
||||
#else
|
||||
|
||||
# include <windows.h>
|
||||
namespace {
|
||||
using namespace sft;
|
||||
void glob(const string& refRoot, const string& refExt, svector &refvecFiles)
|
||||
{
|
||||
std::string strFilePath; // File path
|
||||
std::string strExtension; // Extension
|
||||
|
||||
std::string strPattern = refRoot + "\\*.*";
|
||||
|
||||
WIN32_FIND_DATA FileInformation; // File information
|
||||
HANDLE hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);
|
||||
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
CV_Error(CV_StsBadArg, "Your dataset search path is incorrect");
|
||||
|
||||
do
|
||||
{
|
||||
if(FileInformation.cFileName[0] != '.')
|
||||
{
|
||||
strFilePath.erase();
|
||||
strFilePath = refRoot + "\\" + FileInformation.cFileName;
|
||||
|
||||
if( !(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
||||
{
|
||||
// Check extension
|
||||
strExtension = FileInformation.cFileName;
|
||||
strExtension = strExtension.substr(strExtension.rfind(".") + 1);
|
||||
|
||||
if(strExtension == refExt)
|
||||
// Save filename
|
||||
refvecFiles.push_back(strFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
while(::FindNextFile(hFile, &FileInformation) == TRUE);
|
||||
|
||||
// Close handle
|
||||
::FindClose(hFile);
|
||||
|
||||
DWORD dwError = ::GetLastError();
|
||||
if(dwError != ERROR_NO_MORE_FILES)
|
||||
CV_Error(CV_StsBadArg, "Your dataset search path is incorrect");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// in the default case data folders should be aligned as following:
|
||||
// 1. positives: <train or test path>/octave_<octave number>/pos/*.png
|
||||
// 2. negatives: <train or test path>/octave_<octave number>/neg/*.png
|
||||
ScaledDataset::ScaledDataset(const string& path, const int oct)
|
||||
{
|
||||
dprintf("%s\n", "get dataset file names...");
|
||||
dprintf("%s\n", "Positives globing...");
|
||||
|
||||
#if !defined (_WIN32) && ! defined(__MINGW32__)
|
||||
glob(path + "/pos/octave_" + itoa(oct) + "/*.png", pos);
|
||||
#else
|
||||
glob(path + "/pos/octave_" + itoa(oct), "png", pos);
|
||||
#endif
|
||||
|
||||
dprintf("%s\n", "Negatives globing...");
|
||||
#if !defined (_WIN32) && ! defined(__MINGW32__)
|
||||
glob(path + "/neg/octave_" + itoa(oct) + "/*.png", neg);
|
||||
#else
|
||||
glob(path + "/neg/octave_" + itoa(oct), "png", neg);
|
||||
#endif
|
||||
|
||||
// Check: files not empty
|
||||
CV_Assert(pos.size() != size_t(0));
|
||||
CV_Assert(neg.size() != size_t(0));
|
||||
}
|
||||
|
||||
cv::Mat ScaledDataset::get(SampleType type, int idx) const
|
||||
{
|
||||
const std::string& src = (type == POSITIVE)? pos[idx]: neg[idx];
|
||||
return cv::imread(src);
|
||||
}
|
||||
|
||||
int ScaledDataset::available(SampleType type) const
|
||||
{
|
||||
return (int)((type == POSITIVE)? pos.size():neg.size());
|
||||
}
|
||||
|
||||
ScaledDataset::~ScaledDataset(){}
|
@ -40,74 +40,34 @@
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#ifndef __SFT_COMMON_HPP__
|
||||
#define __SFT_COMMON_HPP__
|
||||
|
||||
cv::SCascade::Channels::Channels(int shr) : shrinkage(shr) {}
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/softcascade/softcascade.hpp>
|
||||
|
||||
void cv::SCascade::Channels::appendHogBins(const cv::Mat& gray, std::vector<cv::Mat>& integrals, int bins) const
|
||||
namespace cv {using namespace softcascade;}
|
||||
namespace sft
|
||||
{
|
||||
CV_Assert(gray.type() == CV_8UC1);
|
||||
int h = gray.rows;
|
||||
int w = gray.cols;
|
||||
CV_Assert(!(w % shrinkage) && !(h % shrinkage));
|
||||
|
||||
cv::Mat df_dx, df_dy, mag, angle;
|
||||
cv::Sobel(gray, df_dx, CV_32F, 1, 0);
|
||||
cv::Sobel(gray, df_dy, CV_32F, 0, 1);
|
||||
using cv::Mat;
|
||||
struct ICF;
|
||||
|
||||
cv::cartToPolar(df_dx, df_dy, mag, angle, true);
|
||||
mag *= (1.f / (8 * sqrt(2.f)));
|
||||
typedef std::string string;
|
||||
|
||||
cv::Mat nmag;
|
||||
mag.convertTo(nmag, CV_8UC1);
|
||||
|
||||
angle *= bins/360.f;
|
||||
|
||||
std::vector<cv::Mat> hist;
|
||||
for (int bin = 0; bin < bins; ++bin)
|
||||
hist.push_back(cv::Mat::zeros(h, w, CV_8UC1));
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
uchar* magnitude = nmag.ptr<uchar>(y);
|
||||
float* ang = angle.ptr<float>(y);
|
||||
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
hist[ (int)ang[x] ].ptr<uchar>(y)[x] = magnitude[x];
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < bins; ++i)
|
||||
{
|
||||
cv::Mat shrunk, sum;
|
||||
cv::resize(hist[i], shrunk, cv::Size(), 1.0 / shrinkage, 1.0 / shrinkage, CV_INTER_AREA);
|
||||
cv::integral(shrunk, sum, cv::noArray(), CV_32S);
|
||||
integrals.push_back(sum);
|
||||
}
|
||||
|
||||
cv::Mat shrMag;
|
||||
cv::resize(nmag, shrMag, cv::Size(), 1.0 / shrinkage, 1.0 / shrinkage, CV_INTER_AREA);
|
||||
cv::integral(shrMag, mag, cv::noArray(), CV_32S);
|
||||
integrals.push_back(mag);
|
||||
typedef std::vector<ICF> Icfvector;
|
||||
typedef std::vector<sft::string> svector;
|
||||
typedef std::vector<int> ivector;
|
||||
}
|
||||
|
||||
void cv::SCascade::Channels::appendLuvBins(const cv::Mat& frame, std::vector<cv::Mat>& integrals) const
|
||||
{
|
||||
CV_Assert(frame.type() == CV_8UC3);
|
||||
CV_Assert(!(frame.cols % shrinkage) && !(frame.rows % shrinkage));
|
||||
// used for noisy printfs
|
||||
//#define WITH_DEBUG_OUT
|
||||
|
||||
cv::Mat luv, shrunk;
|
||||
cv::cvtColor(frame, luv, CV_BGR2Luv);
|
||||
cv::resize(luv, shrunk, cv::Size(), 1.0 / shrinkage, 1.0 / shrinkage, CV_INTER_AREA);
|
||||
#if defined WITH_DEBUG_OUT
|
||||
# include <stdio.h>
|
||||
# define dprintf(format, ...) printf(format, ##__VA_ARGS__)
|
||||
#else
|
||||
# define dprintf(format, ...)
|
||||
#endif
|
||||
|
||||
std::vector<cv::Mat> splited;
|
||||
split(shrunk, splited);
|
||||
|
||||
for (size_t i = 0; i < splited.size(); ++i)
|
||||
{
|
||||
cv::Mat sum;
|
||||
cv::integral(splited[i], sum, cv::noArray(), CV_32S);
|
||||
integrals.push_back(sum);
|
||||
}
|
||||
}
|
||||
#endif
|
135
apps/sft/include/sft/config.hpp
Normal file
135
apps/sft/include/sft/config.hpp
Normal file
@ -0,0 +1,135 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2012, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __SFT_CONFIG_HPP__
|
||||
#define __SFT_CONFIG_HPP__
|
||||
|
||||
#include <sft/common.hpp>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace sft {
|
||||
|
||||
struct Config
|
||||
{
|
||||
Config();
|
||||
|
||||
void write(cv::FileStorage& fs) const;
|
||||
|
||||
void read(const cv::FileNode& node);
|
||||
|
||||
// Scaled and shrunk model size.
|
||||
cv::Size model(ivector::const_iterator it) const
|
||||
{
|
||||
float octave = powf(2.f, (float)(*it));
|
||||
return cv::Size( cvRound(modelWinSize.width * octave) / shrinkage,
|
||||
cvRound(modelWinSize.height * octave) / shrinkage );
|
||||
}
|
||||
|
||||
// Scaled but, not shrunk bounding box for object in sample image.
|
||||
cv::Rect bbox(ivector::const_iterator it) const
|
||||
{
|
||||
float octave = powf(2.f, (float)(*it));
|
||||
return cv::Rect( cvRound(offset.x * octave), cvRound(offset.y * octave),
|
||||
cvRound(modelWinSize.width * octave), cvRound(modelWinSize.height * octave));
|
||||
}
|
||||
|
||||
string resPath(ivector::const_iterator it) const
|
||||
{
|
||||
return cv::format("%s%d.xml",cascadeName.c_str(), *it);
|
||||
}
|
||||
|
||||
// Paths to a rescaled data
|
||||
string trainPath;
|
||||
string testPath;
|
||||
|
||||
// Original model size.
|
||||
cv::Size modelWinSize;
|
||||
|
||||
// example offset into positive image
|
||||
cv::Point2i offset;
|
||||
|
||||
// List of octaves for which have to be trained cascades (a list of powers of two)
|
||||
ivector octaves;
|
||||
|
||||
// Maximum number of positives that should be used during training
|
||||
int positives;
|
||||
|
||||
// Initial number of negatives used during training.
|
||||
int negatives;
|
||||
|
||||
// Number of weak negatives to add each bootstrapping step.
|
||||
int btpNegatives;
|
||||
|
||||
// Inverse of scale for feature resizing
|
||||
int shrinkage;
|
||||
|
||||
// Depth on weak classifier's decision tree
|
||||
int treeDepth;
|
||||
|
||||
// Weak classifiers number in resulted cascade
|
||||
int weaks;
|
||||
|
||||
// Feature random pool size
|
||||
int poolSize;
|
||||
|
||||
// file name to store cascade
|
||||
string cascadeName;
|
||||
|
||||
// path to resulting cascade
|
||||
string outXmlPath;
|
||||
|
||||
// seed for random generation
|
||||
int seed;
|
||||
|
||||
// // bounding rectangle for actual example into example window
|
||||
// cv::Rect exampleWindow;
|
||||
};
|
||||
|
||||
// required for cv::FileStorage serialization
|
||||
void write(cv::FileStorage& fs, const string&, const Config& x);
|
||||
void read(const cv::FileNode& node, Config& x, const Config& default_value);
|
||||
std::ostream& operator<<(std::ostream& out, const Config& m);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
67
apps/sft/include/sft/dataset.hpp
Normal file
67
apps/sft/include/sft/dataset.hpp
Normal file
@ -0,0 +1,67 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2012, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __SFT_OCTAVE_HPP__
|
||||
#define __SFT_OCTAVE_HPP__
|
||||
|
||||
#include <sft/common.hpp>
|
||||
namespace sft
|
||||
{
|
||||
|
||||
using cv::softcascade::Dataset;
|
||||
|
||||
class ScaledDataset : public Dataset
|
||||
{
|
||||
public:
|
||||
ScaledDataset(const sft::string& path, const int octave);
|
||||
|
||||
virtual cv::Mat get(SampleType type, int idx) const;
|
||||
virtual int available(SampleType type) const;
|
||||
virtual ~ScaledDataset();
|
||||
|
||||
private:
|
||||
svector pos;
|
||||
svector neg;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
161
apps/sft/sft.cpp
Normal file
161
apps/sft/sft.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2012, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
// Training application for Soft Cascades.
|
||||
|
||||
#include <sft/common.hpp>
|
||||
#include <iostream>
|
||||
#include <sft/dataset.hpp>
|
||||
#include <sft/config.hpp>
|
||||
|
||||
#include <opencv2/core/core_c.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
using namespace sft;
|
||||
|
||||
const string keys =
|
||||
"{help h usage ? | | print this message }"
|
||||
"{config c | | path to configuration xml }"
|
||||
;
|
||||
|
||||
cv::CommandLineParser parser(argc, argv, keys);
|
||||
parser.about("Soft cascade training application.");
|
||||
|
||||
if (parser.has("help"))
|
||||
{
|
||||
parser.printMessage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!parser.check())
|
||||
{
|
||||
parser.printErrors();
|
||||
return 1;
|
||||
}
|
||||
|
||||
string configPath = parser.get<string>("config");
|
||||
if (configPath.empty())
|
||||
{
|
||||
std::cout << "Configuration file is missing or empty. Could not start training." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::cout << "Read configuration from file " << configPath << std::endl;
|
||||
cv::FileStorage fs(configPath, cv::FileStorage::READ);
|
||||
if(!fs.isOpened())
|
||||
{
|
||||
std::cout << "Configuration file " << configPath << " can't be opened." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 1. load config
|
||||
sft::Config cfg;
|
||||
fs["config"] >> cfg;
|
||||
std::cout << std::endl << "Training will be executed for configuration:" << std::endl << cfg << std::endl;
|
||||
|
||||
// 2. check and open output file
|
||||
cv::FileStorage fso(cfg.outXmlPath, cv::FileStorage::WRITE);
|
||||
if(!fso.isOpened())
|
||||
{
|
||||
std::cout << "Training stopped. Output classifier Xml file " << cfg.outXmlPath << " can't be opened." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
fso << cfg.cascadeName
|
||||
<< "{"
|
||||
<< "stageType" << "BOOST"
|
||||
<< "featureType" << "ICF"
|
||||
<< "octavesNum" << (int)cfg.octaves.size()
|
||||
<< "width" << cfg.modelWinSize.width
|
||||
<< "height" << cfg.modelWinSize.height
|
||||
<< "shrinkage" << cfg.shrinkage
|
||||
<< "octaves" << "[";
|
||||
|
||||
// 3. Train all octaves
|
||||
for (ivector::const_iterator it = cfg.octaves.begin(); it != cfg.octaves.end(); ++it)
|
||||
{
|
||||
// a. create random feature pool
|
||||
int nfeatures = cfg.poolSize;
|
||||
cv::Size model = cfg.model(it);
|
||||
std::cout << "Model " << model << std::endl;
|
||||
cv::Ptr<cv::FeaturePool> pool = cv::FeaturePool::create(model, nfeatures);
|
||||
nfeatures = pool->size();
|
||||
|
||||
|
||||
int npositives = cfg.positives;
|
||||
int nnegatives = cfg.negatives;
|
||||
int shrinkage = cfg.shrinkage;
|
||||
cv::Rect boundingBox = cfg.bbox(it);
|
||||
std::cout << "Object bounding box" << boundingBox << std::endl;
|
||||
|
||||
typedef cv::Octave Octave;
|
||||
|
||||
cv::Ptr<Octave> boost = Octave::create(boundingBox, npositives, nnegatives, *it, shrinkage, nfeatures);
|
||||
|
||||
std::string path = cfg.trainPath;
|
||||
sft::ScaledDataset dataset(path, *it);
|
||||
|
||||
if (boost->train(&dataset, pool, cfg.weaks, cfg.treeDepth))
|
||||
{
|
||||
CvFileStorage* fout = cvOpenFileStorage(cfg.resPath(it).c_str(), 0, CV_STORAGE_WRITE);
|
||||
boost->write(fout, cfg.cascadeName);
|
||||
|
||||
cvReleaseFileStorage( &fout);
|
||||
|
||||
cv::Mat thresholds;
|
||||
boost->setRejectThresholds(thresholds);
|
||||
|
||||
boost->write(fso, pool, thresholds);
|
||||
|
||||
cv::FileStorage tfs(("thresholds." + cfg.resPath(it)).c_str(), cv::FileStorage::WRITE);
|
||||
tfs << "thresholds" << thresholds;
|
||||
|
||||
std::cout << "Octave " << *it << " was successfully trained..." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
fso << "]" << "}";
|
||||
fso.release();
|
||||
std::cout << "Training complete..." << std::endl;
|
||||
return 0;
|
||||
}
|
@ -1580,8 +1580,11 @@ bool CvCascadeBoost::isErrDesired()
|
||||
for( int i = 0; i < sCount; i++ )
|
||||
if( ((CvCascadeBoostTrainData*)data)->featureEvaluator->getCls( i ) == 1.0F )
|
||||
eval[numPos++] = predict( i, true );
|
||||
|
||||
icvSortFlt( &eval[0], numPos, 0 );
|
||||
|
||||
int thresholdIdx = (int)((1.0F - minHitRate) * numPos);
|
||||
|
||||
threshold = eval[ thresholdIdx ];
|
||||
numPosTrue = numPos - thresholdIdx;
|
||||
for( int i = thresholdIdx - 1; i >= 0; i--)
|
||||
|
61401
data/softcascade/inria_caltech-17.01.2013.xml
Normal file
61401
data/softcascade/inria_caltech-17.01.2013.xml
Normal file
File diff suppressed because it is too large
Load Diff
@ -1251,6 +1251,8 @@ protected:
|
||||
virtual void write_params( CvFileStorage* fs ) const;
|
||||
virtual void read_params( CvFileStorage* fs, CvFileNode* node );
|
||||
|
||||
virtual void initialize_weights(double (&p)[2]);
|
||||
|
||||
CvDTreeTrainData* data;
|
||||
CvBoostParams params;
|
||||
CvSeq* weak;
|
||||
@ -2129,7 +2131,6 @@ typedef CvGBTrees GradientBoostingTrees;
|
||||
template<> CV_EXPORTS void Ptr<CvDTreeSplit>::delete_obj();
|
||||
|
||||
CV_EXPORTS bool initModule_ml(void);
|
||||
|
||||
}
|
||||
|
||||
#endif // __cplusplus
|
||||
|
@ -879,7 +879,6 @@ void CvBoostTree::read( CvFileStorage* fs, CvFileNode* fnode, CvBoost* _ensemble
|
||||
ensemble = _ensemble;
|
||||
}
|
||||
|
||||
|
||||
void CvBoostTree::read( CvFileStorage*, CvFileNode* )
|
||||
{
|
||||
assert(0);
|
||||
@ -1116,6 +1115,12 @@ bool CvBoost::train( CvMLData* _data,
|
||||
return result;
|
||||
}
|
||||
|
||||
void CvBoost::initialize_weights(double (&p)[2])
|
||||
{
|
||||
p[0] = 1.;
|
||||
p[1] = 1.;
|
||||
}
|
||||
|
||||
void
|
||||
CvBoost::update_weights( CvBoostTree* tree )
|
||||
{
|
||||
@ -1159,8 +1164,9 @@ CvBoost::update_weights( CvBoostTree* tree )
|
||||
// in case of logitboost and gentle adaboost each weak tree is a regression tree,
|
||||
// so we need to convert class labels to floating-point values
|
||||
|
||||
double w0 = 1./n;
|
||||
double p[2] = { 1, 1 };
|
||||
double w0 = 1./ n;
|
||||
double p[2] = { 1., 1. };
|
||||
initialize_weights(p);
|
||||
|
||||
cvReleaseMat( &orig_response );
|
||||
cvReleaseMat( &sum_response );
|
||||
|
@ -8,5 +8,4 @@ objdetect. Object Detection
|
||||
:maxdepth: 2
|
||||
|
||||
cascade_classification
|
||||
soft_cascade
|
||||
latent_svm
|
||||
|
@ -488,95 +488,6 @@ protected:
|
||||
Ptr<MaskGenerator> maskGenerator;
|
||||
};
|
||||
|
||||
// Implementation of soft (stageless) cascaded detector.
|
||||
class CV_EXPORTS_W SCascade : public Algorithm
|
||||
{
|
||||
public:
|
||||
|
||||
// Representation of detectors result.
|
||||
struct CV_EXPORTS Detection
|
||||
{
|
||||
// Default object type.
|
||||
enum {PEDESTRIAN = 1};
|
||||
|
||||
// Creates Detection from an object bounding box and confidence.
|
||||
// Param b is a bounding box
|
||||
// Param c is a confidence that object belongs to class k
|
||||
// Paral k is an object class
|
||||
Detection(const cv::Rect& b, const float c, int k = PEDESTRIAN) : bb(b), confidence(c), kind(k) {}
|
||||
|
||||
cv::Rect bb;
|
||||
float confidence;
|
||||
int kind;
|
||||
};
|
||||
|
||||
// Create channel integrals for Soft Cascade detector.
|
||||
class CV_EXPORTS Channels
|
||||
{
|
||||
public:
|
||||
// constrictor form resizing factor.
|
||||
// Param shr is a resizing factor. Resize is applied before the computing integral sum
|
||||
Channels(const int shrinkage);
|
||||
|
||||
// Appends specified number of HOG first-order features integrals into given vector.
|
||||
// Param gray is an input 1-channel gray image.
|
||||
// Param integrals is a vector of integrals. Hog-channels will be appended to it.
|
||||
// Param bins is a number of hog-bins
|
||||
void appendHogBins(const cv::Mat& gray, std::vector<cv::Mat>& integrals, int bins) const;
|
||||
|
||||
// Converts 3-channel BGR input frame in Luv and appends each channel to the integrals.
|
||||
// Param frame is an input 3-channel BGR colored image.
|
||||
// Param integrals is a vector of integrals. Computed from the frame luv-channels will be appended to it.
|
||||
void appendLuvBins(const cv::Mat& frame, std::vector<cv::Mat>& integrals) const;
|
||||
|
||||
private:
|
||||
int shrinkage;
|
||||
};
|
||||
|
||||
enum { NO_REJECT = 1, DOLLAR = 2, /*PASCAL = 4,*/ DEFAULT = NO_REJECT};
|
||||
|
||||
// An empty cascade will be created.
|
||||
// Param minScale is a minimum scale relative to the original size of the image on which cascade will be applyed.
|
||||
// Param minScale is a maximum scale relative to the original size of the image on which cascade will be applyed.
|
||||
// Param scales is a number of scales from minScale to maxScale.
|
||||
// Param rejCriteria is used for NMS.
|
||||
CV_WRAP SCascade(const double minScale = 0.4, const double maxScale = 5., const int scales = 55, const int rejCriteria = 1);
|
||||
|
||||
CV_WRAP virtual ~SCascade();
|
||||
|
||||
cv::AlgorithmInfo* info() const;
|
||||
|
||||
// Load cascade from FileNode.
|
||||
// Param fn is a root node for cascade. Should be <cascade>.
|
||||
CV_WRAP virtual bool load(const FileNode& fn);
|
||||
|
||||
// Load cascade config.
|
||||
CV_WRAP virtual void read(const FileNode& fn);
|
||||
|
||||
// Return the vector of Decection objcts.
|
||||
// Param image is a frame on which detector will be applied.
|
||||
// Param rois is a vector of regions of interest. Only the objects that fall into one of the regions will be returned.
|
||||
// Param objects is an output array of Detections
|
||||
virtual void detect(InputArray image, InputArray rois, std::vector<Detection>& objects) const;
|
||||
// Param rects is an output array of bounding rectangles for detected objects.
|
||||
// Param confs is an output array of confidence for detected objects. i-th bounding rectangle corresponds i-th configence.
|
||||
CV_WRAP virtual void detect(InputArray image, InputArray rois, CV_OUT OutputArray rects, CV_OUT OutputArray confs) const;
|
||||
|
||||
private:
|
||||
void detectNoRoi(const Mat& image, std::vector<Detection>& objects) const;
|
||||
|
||||
struct Fields;
|
||||
Fields* fields;
|
||||
|
||||
double minScale;
|
||||
double maxScale;
|
||||
|
||||
int scales;
|
||||
int rejCriteria;
|
||||
};
|
||||
|
||||
CV_EXPORTS bool initModule_objdetect(void);
|
||||
|
||||
//////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector //////////////
|
||||
|
||||
// struct for detection region of interest (ROI)
|
||||
|
@ -47,47 +47,4 @@ PERF_TEST_P(ImageName_MinSize, CascadeClassifierLBPFrontalFace,
|
||||
|
||||
std::sort(faces.begin(), faces.end(), comparators::RectLess());
|
||||
SANITY_CHECK(faces, 3.001 * faces.size());
|
||||
}
|
||||
|
||||
typedef std::tr1::tuple<std::string, std::string> fixture;
|
||||
typedef perf::TestBaseWithParam<fixture> detect;
|
||||
|
||||
|
||||
namespace {
|
||||
typedef cv::SCascade::Detection detection_t;
|
||||
|
||||
void extractRacts(std::vector<detection_t> objectBoxes, vector<Rect>& rects)
|
||||
{
|
||||
rects.clear();
|
||||
for (int i = 0; i < (int)objectBoxes.size(); ++i)
|
||||
rects.push_back(objectBoxes[i].bb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PERF_TEST_P(detect, SCascade,
|
||||
testing::Combine(testing::Values(std::string("cv/cascadeandhog/cascades/inria_caltech-17.01.2013.xml")),
|
||||
testing::Values(std::string("cv/cascadeandhog/images/image_00000000_0.png"))))
|
||||
{
|
||||
typedef cv::SCascade::Detection Detection;
|
||||
cv::Mat colored = imread(getDataPath(get<1>(GetParam())));
|
||||
ASSERT_FALSE(colored.empty());
|
||||
|
||||
cv::SCascade cascade;
|
||||
cv::FileStorage fs(getDataPath(get<0>(GetParam())), cv::FileStorage::READ);
|
||||
ASSERT_TRUE(fs.isOpened());
|
||||
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
|
||||
|
||||
std::vector<detection_t> objectBoxes;
|
||||
cascade.detect(colored, cv::noArray(), objectBoxes);
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
cascade.detect(colored, cv::noArray(), objectBoxes);
|
||||
}
|
||||
|
||||
vector<Rect> rects;
|
||||
extractRacts(objectBoxes, rects);
|
||||
std::sort(rects.begin(), rects.end(), comparators::RectLess());
|
||||
SANITY_CHECK(rects);
|
||||
}
|
@ -10,7 +10,7 @@ if(ANDROID OR IOS OR NOT PYTHONLIBS_FOUND OR NOT PYTHON_USE_NUMPY)
|
||||
endif()
|
||||
|
||||
set(the_description "The python bindings")
|
||||
ocv_add_module(python BINDINGS opencv_core opencv_flann opencv_imgproc opencv_video opencv_ml opencv_features2d opencv_highgui opencv_calib3d opencv_photo opencv_objdetect opencv_contrib opencv_legacy OPTIONAL opencv_nonfree)
|
||||
ocv_add_module(python BINDINGS opencv_core opencv_flann opencv_imgproc opencv_video opencv_ml opencv_features2d opencv_highgui opencv_calib3d opencv_photo opencv_objdetect opencv_contrib opencv_legacy opencv_softcascade OPTIONAL opencv_nonfree)
|
||||
|
||||
add_definitions(-DPYTHON_USE_NUMPY=1)
|
||||
|
||||
@ -34,6 +34,7 @@ set(opencv_hdrs
|
||||
"${OPENCV_MODULE_opencv_features2d_LOCATION}/include/opencv2/features2d/features2d.hpp"
|
||||
"${OPENCV_MODULE_opencv_calib3d_LOCATION}/include/opencv2/calib3d/calib3d.hpp"
|
||||
"${OPENCV_MODULE_opencv_objdetect_LOCATION}/include/opencv2/objdetect/objdetect.hpp"
|
||||
"${OPENCV_MODULE_opencv_softcascade_LOCATION}/include/opencv2/softcascade/softcascade.hpp"
|
||||
"${OPENCV_MODULE_opencv_contrib_LOCATION}/include/opencv2/contrib/contrib.hpp")
|
||||
|
||||
if(HAVE_opencv_nonfree)
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "opencv2/ml/ml.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/objdetect/objdetect.hpp"
|
||||
#include "opencv2/softcascade/softcascade.hpp"
|
||||
#include "opencv2/video/tracking.hpp"
|
||||
#include "opencv2/video/background_segm.hpp"
|
||||
#include "opencv2/photo/photo.hpp"
|
||||
@ -96,6 +97,7 @@ catch (const cv::Exception &e) \
|
||||
}
|
||||
|
||||
using namespace cv;
|
||||
typedef cv::softcascade::ChannelFeatureBuilder softcascade_ChannelFeatureBuilder;
|
||||
|
||||
typedef vector<uchar> vector_uchar;
|
||||
typedef vector<int> vector_int;
|
||||
@ -124,6 +126,8 @@ typedef Ptr<DescriptorExtractor> Ptr_DescriptorExtractor;
|
||||
typedef Ptr<Feature2D> Ptr_Feature2D;
|
||||
typedef Ptr<DescriptorMatcher> Ptr_DescriptorMatcher;
|
||||
|
||||
typedef Ptr<cv::softcascade::ChannelFeatureBuilder> Ptr_ChannelFeatureBuilder;
|
||||
|
||||
typedef SimpleBlobDetector::Params SimpleBlobDetector_Params;
|
||||
|
||||
typedef cvflann::flann_distance_t cvflann_flann_distance_t;
|
||||
|
2
modules/softcascade/CMakeLists.txt
Normal file
2
modules/softcascade/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
set(the_description "Soft Cascade detection and training")
|
||||
ocv_define_module(softcascade opencv_core opencv_imgproc opencv_ml)
|
11
modules/softcascade/doc/softcascade.rst
Normal file
11
modules/softcascade/doc/softcascade.rst
Normal file
@ -0,0 +1,11 @@
|
||||
********************************************************
|
||||
softcascade. Soft Cascade object detection and training.
|
||||
********************************************************
|
||||
|
||||
.. highlight:: cpp
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
softcascade_detector
|
||||
softcascade_training
|
@ -1,10 +1,10 @@
|
||||
Soft Cascade Classifier
|
||||
======================
|
||||
=======================
|
||||
|
||||
.. highlight:: cpp
|
||||
|
||||
Soft Cascade Classifier for Object Detection
|
||||
----------------------------------------------------------
|
||||
--------------------------------------------
|
||||
|
||||
Cascade detectors have been shown to operate extremely rapidly, with high accuracy, and have important applications in different spheres. The initial goal for this cascade implementation was the fast and accurate pedestrian detector but it also useful in general. Soft cascade is trained with AdaBoost. But instead of training sequence of stages, the soft cascade is trained as a one long stage of T weak classifiers. Soft cascade is formulated as follows:
|
||||
|
||||
@ -16,7 +16,7 @@ where :math:`\texttt{s}_t(x) = \alpha_t\texttt{h}_t(x)` are the set of threshold
|
||||
.. math::
|
||||
\texttt{H}_t(x) = \sum _{\texttt{i}=1..\texttt{t}} {\texttt{s}_i(x)}
|
||||
|
||||
be the partial sum of sample responses before :math:`t`-the weak classifier will be applied. The funtcion :math:`\texttt{H}_t(x)` of :math:`t` for sample :math:`x` named *sample trace*.
|
||||
be the partial sum of sample responses before :math:`t`-the weak classifier will be applied. The function :math:`\texttt{H}_t(x)` of :math:`t` for sample :math:`x` named *sample trace*.
|
||||
After each weak classifier evaluation, the sample trace at the point :math:`t` is compared with the rejection threshold :math:`r_t`. The sequence of :math:`r_t` named *rejection trace*.
|
||||
|
||||
The sample has been rejected if it fall rejection threshold. So stageless cascade allows to reject not-object sample as soon as possible. Another meaning of the sample trace is a confidence with that sample recognized as desired object. At each :math:`t` that confidence depend on all previous weak classifier. This feature of soft cascade is resulted in more accurate detection. The original formulation of soft cascade can be found in [BJ05]_.
|
||||
@ -25,65 +25,77 @@ The sample has been rejected if it fall rejection threshold. So stageless cascad
|
||||
.. [BMTG12] Rodrigo Benenson, Markus Mathias, Radu Timofte and Luc Van Gool. Pedestrian detection at 100 frames per second. IEEE CVPR, 2012.
|
||||
|
||||
|
||||
SCascade
|
||||
----------------
|
||||
.. ocv:class:: SCascade
|
||||
Detector
|
||||
-------------------
|
||||
.. ocv:class:: Detector
|
||||
|
||||
Implementation of soft (stageless) cascaded detector. ::
|
||||
|
||||
class CV_EXPORTS SCascade : public Algorithm
|
||||
class CV_EXPORTS_W Detector : public Algorithm
|
||||
{
|
||||
public:
|
||||
SCascade(const float minScale = 0.4f, const float maxScale = 5.f, const int scales = 55, const int rejfactor = 1);
|
||||
virtual ~SCascade();
|
||||
|
||||
enum { NO_REJECT = 1, DOLLAR = 2, /*PASCAL = 4,*/ DEFAULT = NO_REJECT};
|
||||
|
||||
CV_WRAP Detector(double minScale = 0.4, double maxScale = 5., int scales = 55, int rejCriteria = 1);
|
||||
CV_WRAP virtual ~Detector();
|
||||
cv::AlgorithmInfo* info() const;
|
||||
virtual bool load(const FileNode& fn);
|
||||
CV_WRAP virtual bool load(const FileNode& fileNode);
|
||||
CV_WRAP virtual void read(const FileNode& fileNode);
|
||||
virtual void detect(InputArray image, InputArray rois, std::vector<Detection>& objects) const;
|
||||
virtual void detect(InputArray image, InputArray rois, OutputArray rects, OutputArray confs) const;
|
||||
};
|
||||
CV_WRAP virtual void detect(InputArray image, InputArray rois, CV_OUT OutputArray rects, CV_OUT OutputArray confs) const;
|
||||
|
||||
}
|
||||
|
||||
|
||||
SCascade::SCascade
|
||||
--------------------------
|
||||
|
||||
Detector::Detector
|
||||
----------------------------------------
|
||||
An empty cascade will be created.
|
||||
|
||||
.. ocv:function:: bool SCascade::SCascade(const float minScale = 0.4f, const float maxScale = 5.f, const int scales = 55, const int rejfactor = 1)
|
||||
.. ocv:function:: Detector::Detector(float minScale = 0.4f, float maxScale = 5.f, int scales = 55, int rejCriteria = 1)
|
||||
|
||||
:param minScale: a minimum scale relative to the original size of the image on which cascade will be applyed.
|
||||
.. ocv:pyfunction:: cv2.Detector.Detector(minScale[, maxScale[, scales[, rejCriteria]]]) -> cascade
|
||||
|
||||
:param maxScale: a maximum scale relative to the original size of the image on which cascade will be applyed.
|
||||
:param minScale: a minimum scale relative to the original size of the image on which cascade will be applied.
|
||||
|
||||
:param maxScale: a maximum scale relative to the original size of the image on which cascade will be applied.
|
||||
|
||||
:param scales: a number of scales from minScale to maxScale.
|
||||
|
||||
:param rejfactor: used for non maximum suppression.
|
||||
:param rejCriteria: algorithm used for non maximum suppression.
|
||||
|
||||
|
||||
|
||||
SCascade::~SCascade
|
||||
---------------------------
|
||||
Destructor for SCascade.
|
||||
Detector::~Detector
|
||||
-----------------------------------------
|
||||
Destructor for Detector.
|
||||
|
||||
.. ocv:function:: SCascade::~SCascade()
|
||||
.. ocv:function:: Detector::~Detector()
|
||||
|
||||
|
||||
|
||||
SCascade::load
|
||||
Detector::load
|
||||
--------------------------
|
||||
Load cascade from FileNode.
|
||||
|
||||
.. ocv:function:: bool SCascade::load(const FileNode& fn)
|
||||
.. ocv:function:: bool Detector::load(const FileNode& fileNode)
|
||||
|
||||
:param fn: File node from which the soft cascade are read.
|
||||
.. ocv:pyfunction:: cv2.Detector.load(fileNode)
|
||||
|
||||
:param fileNode: File node from which the soft cascade are read.
|
||||
|
||||
|
||||
|
||||
SCascade::detect
|
||||
--------------------------
|
||||
Apply cascade to an input frame and return the vector of Decection objcts.
|
||||
Detector::detect
|
||||
---------------------------
|
||||
Apply cascade to an input frame and return the vector of Detection objects.
|
||||
|
||||
.. ocv:function:: void SCascade::detect(InputArray image, InputArray rois, std::vector<Detection>& objects) const
|
||||
.. ocv:function:: void Detector::detect(InputArray image, InputArray rois, std::vector<Detection>& objects) const
|
||||
|
||||
.. ocv:function:: void SCascade::detect(InputArray image, InputArray rois, OutputArray rects, OutputArray confs) const
|
||||
.. ocv:function:: void Detector::detect(InputArray image, InputArray rois, OutputArray rects, OutputArray confs) const
|
||||
|
||||
.. ocv:pyfunction:: cv2.Detector.detect(image, rois) -> (rects, confs)
|
||||
|
||||
:param image: a frame on which detector will be applied.
|
||||
|
||||
@ -93,4 +105,41 @@ Apply cascade to an input frame and return the vector of Decection objcts.
|
||||
|
||||
:param rects: an output array of bounding rectangles for detected objects.
|
||||
|
||||
:param confs: an output array of confidence for detected objects. i-th bounding rectangle corresponds i-th configence.
|
||||
:param confs: an output array of confidence for detected objects. i-th bounding rectangle corresponds i-th confidence.
|
||||
|
||||
|
||||
ChannelFeatureBuilder
|
||||
---------------------
|
||||
.. ocv:class:: ChannelFeatureBuilder
|
||||
|
||||
Public interface for of soft (stageless) cascaded detector. ::
|
||||
|
||||
class CV_EXPORTS_W ChannelFeatureBuilder : public Algorithm
|
||||
{
|
||||
public:
|
||||
virtual ~ChannelFeatureBuilder();
|
||||
|
||||
CV_WRAP_AS(compute) virtual void operator()(InputArray src, CV_OUT OutputArray channels) const = 0;
|
||||
|
||||
CV_WRAP static cv::Ptr<ChannelFeatureBuilder> create();
|
||||
};
|
||||
|
||||
|
||||
ChannelFeatureBuilder:~ChannelFeatureBuilder
|
||||
--------------------------------------------
|
||||
Destructor for ChannelFeatureBuilder.
|
||||
|
||||
.. ocv:function:: ChannelFeatureBuilder::~ChannelFeatureBuilder()
|
||||
|
||||
|
||||
ChannelFeatureBuilder::operator()
|
||||
---------------------------------
|
||||
Create channel feature integrals for input image.
|
||||
|
||||
.. ocv:function:: void ChannelFeatureBuilder::operator()(InputArray src, OutputArray channels) const
|
||||
|
||||
.. ocv:pyfunction:: cv2.ChannelFeatureBuilder.compute(src, channels) -> None
|
||||
|
||||
:param src source frame
|
||||
|
||||
:param channels in OutputArray of computed channels
|
143
modules/softcascade/doc/softcascade_training.rst
Normal file
143
modules/softcascade/doc/softcascade_training.rst
Normal file
@ -0,0 +1,143 @@
|
||||
Soft Cascade Training
|
||||
=======================
|
||||
|
||||
.. highlight:: cpp
|
||||
|
||||
Soft Cascade Detector Training
|
||||
--------------------------------------------
|
||||
|
||||
|
||||
Octave
|
||||
-----------------
|
||||
.. ocv:class:: Octave
|
||||
|
||||
Public interface for soft cascade training algorithm. ::
|
||||
|
||||
class CV_EXPORTS Octave : public Algorithm
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
// Direct backward pruning. (Cha Zhang and Paul Viola)
|
||||
DBP = 1,
|
||||
// Multiple instance pruning. (Cha Zhang and Paul Viola)
|
||||
MIP = 2,
|
||||
// Originally proposed by L. Bourdev and J. Brandt
|
||||
HEURISTIC = 4 };
|
||||
|
||||
virtual ~Octave();
|
||||
static cv::Ptr<Octave> create(cv::Rect boundingBox, int npositives, int nnegatives, int logScale, int shrinkage);
|
||||
|
||||
virtual bool train(const Dataset* dataset, const FeaturePool* pool, int weaks, int treeDepth) = 0;
|
||||
virtual void setRejectThresholds(OutputArray thresholds) = 0;
|
||||
virtual void write( cv::FileStorage &fs, const FeaturePool* pool, InputArray thresholds) const = 0;
|
||||
virtual void write( CvFileStorage* fs, string name) const = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
Octave::~Octave
|
||||
---------------------------------------
|
||||
Destructor for Octave.
|
||||
|
||||
.. ocv:function:: Octave::~Octave()
|
||||
|
||||
|
||||
Octave::train
|
||||
------------------------
|
||||
|
||||
.. ocv:function:: bool Octave::train(const Dataset* dataset, const FeaturePool* pool, int weaks, int treeDepth)
|
||||
|
||||
:param dataset an object that allows communicate for training set.
|
||||
|
||||
:param pool an object that presents feature pool.
|
||||
|
||||
:param weaks a number of weak trees should be trained.
|
||||
|
||||
:param treeDepth a depth of resulting weak trees.
|
||||
|
||||
|
||||
|
||||
Octave::setRejectThresholds
|
||||
--------------------------------------
|
||||
|
||||
.. ocv:function:: void Octave::setRejectThresholds(OutputArray thresholds)
|
||||
|
||||
:param thresholds an output array of resulted rejection vector. Have same size as number of trained stages.
|
||||
|
||||
|
||||
Octave::write
|
||||
------------------------
|
||||
|
||||
.. ocv:function:: void Octave::train(cv::FileStorage &fs, const FeaturePool* pool, InputArray thresholds) const
|
||||
.. ocv:function:: void Octave::train( CvFileStorage* fs, string name) const
|
||||
|
||||
:param fs an output file storage to store trained detector.
|
||||
|
||||
:param pool an object that presents feature pool.
|
||||
|
||||
:param dataset a rejection vector that should be included in detector xml file.
|
||||
|
||||
:param name a name of root node for trained detector.
|
||||
|
||||
|
||||
FeaturePool
|
||||
-----------
|
||||
.. ocv:class:: FeaturePool
|
||||
|
||||
Public interface for feature pool. This is a hight level abstraction for training random feature pool. ::
|
||||
|
||||
class CV_EXPORTS FeaturePool
|
||||
{
|
||||
public:
|
||||
|
||||
virtual int size() const = 0;
|
||||
virtual float apply(int fi, int si, const Mat& channels) const = 0;
|
||||
virtual void write( cv::FileStorage& fs, int index) const = 0;
|
||||
virtual ~FeaturePool();
|
||||
|
||||
};
|
||||
|
||||
FeaturePool::size
|
||||
-----------------
|
||||
|
||||
Returns size of feature pool.
|
||||
|
||||
.. ocv:function:: int FeaturePool::size() const
|
||||
|
||||
|
||||
|
||||
FeaturePool::~FeaturePool
|
||||
-------------------------
|
||||
|
||||
FeaturePool destructor.
|
||||
|
||||
.. ocv:function:: int FeaturePool::~FeaturePool()
|
||||
|
||||
|
||||
|
||||
FeaturePool::write
|
||||
------------------
|
||||
|
||||
Write specified feature from feature pool to file storage.
|
||||
|
||||
.. ocv:function:: void FeaturePool::write( cv::FileStorage& fs, int index) const
|
||||
|
||||
:param fs an output file storage to store feature.
|
||||
|
||||
:param index an index of feature that should be stored.
|
||||
|
||||
|
||||
FeaturePool::apply
|
||||
------------------
|
||||
|
||||
Compute feature on integral channel image.
|
||||
|
||||
.. ocv:function:: float FeaturePool::apply(int fi, int si, const Mat& channels) const
|
||||
|
||||
:param fi an index of feature that should be computed.
|
||||
|
||||
:param si an index of sample.
|
||||
|
||||
:param fs a channel matrix.
|
214
modules/softcascade/include/opencv2/softcascade/softcascade.hpp
Normal file
214
modules/softcascade/include/opencv2/softcascade/softcascade.hpp
Normal file
@ -0,0 +1,214 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_SOFTCASCADE_HPP__
|
||||
#define __OPENCV_SOFTCASCADE_HPP__
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
|
||||
namespace cv { namespace softcascade {
|
||||
|
||||
// Representation of detectors result.
|
||||
struct CV_EXPORTS Detection
|
||||
{
|
||||
// Default object type.
|
||||
enum {PEDESTRIAN = 1};
|
||||
|
||||
// Creates Detection from an object bounding box and confidence.
|
||||
// Param b is a bounding box
|
||||
// Param c is a confidence that object belongs to class k
|
||||
// Param k is an object class
|
||||
Detection(const cv::Rect& b, const float c, int k = PEDESTRIAN) : bb(b), confidence(c), kind(k) {}
|
||||
|
||||
cv::Rect bb;
|
||||
float confidence;
|
||||
int kind;
|
||||
};
|
||||
|
||||
class CV_EXPORTS Dataset
|
||||
{
|
||||
public:
|
||||
typedef enum {POSITIVE = 1, NEGATIVE = 2} SampleType;
|
||||
|
||||
virtual cv::Mat get(SampleType type, int idx) const = 0;
|
||||
virtual int available(SampleType type) const = 0;
|
||||
virtual ~Dataset();
|
||||
};
|
||||
|
||||
// ========================================================================== //
|
||||
// Public interface feature pool.
|
||||
// ========================================================================== //
|
||||
|
||||
class CV_EXPORTS FeaturePool
|
||||
{
|
||||
public:
|
||||
|
||||
virtual int size() const = 0;
|
||||
virtual float apply(int fi, int si, const Mat& channels) const = 0;
|
||||
virtual void write( cv::FileStorage& fs, int index) const = 0;
|
||||
virtual ~FeaturePool();
|
||||
|
||||
static cv::Ptr<FeaturePool> create(const cv::Size& model, int nfeatures);
|
||||
};
|
||||
|
||||
// ========================================================================== //
|
||||
// First order channel feature.
|
||||
// ========================================================================== //
|
||||
|
||||
class CV_EXPORTS ChannelFeature
|
||||
{
|
||||
public:
|
||||
ChannelFeature(int x, int y, int w, int h, int ch);
|
||||
~ChannelFeature();
|
||||
|
||||
bool operator ==(ChannelFeature b);
|
||||
bool operator !=(ChannelFeature b);
|
||||
|
||||
float operator() (const cv::Mat& integrals, const cv::Size& model) const;
|
||||
|
||||
friend void write(cv::FileStorage& fs, const std::string&, const ChannelFeature& f);
|
||||
friend std::ostream& operator<<(std::ostream& out, const ChannelFeature& f);
|
||||
|
||||
private:
|
||||
cv::Rect bb;
|
||||
int channel;
|
||||
};
|
||||
|
||||
void write(cv::FileStorage& fs, const std::string&, const ChannelFeature& f);
|
||||
std::ostream& operator<<(std::ostream& out, const ChannelFeature& m);
|
||||
|
||||
// ========================================================================== //
|
||||
// Public Interface for Integral Channel Feature.
|
||||
// ========================================================================== //
|
||||
|
||||
class CV_EXPORTS_W ChannelFeatureBuilder : public cv::Algorithm
|
||||
{
|
||||
public:
|
||||
virtual ~ChannelFeatureBuilder();
|
||||
|
||||
// apply channels to source frame
|
||||
CV_WRAP_AS(compute) virtual void operator()(InputArray src, CV_OUT OutputArray channels) const = 0;
|
||||
|
||||
CV_WRAP static cv::Ptr<ChannelFeatureBuilder> create();
|
||||
};
|
||||
|
||||
// ========================================================================== //
|
||||
// Implementation of soft (stageless) cascaded detector.
|
||||
// ========================================================================== //
|
||||
class CV_EXPORTS_W Detector : public cv::Algorithm
|
||||
{
|
||||
public:
|
||||
|
||||
enum { NO_REJECT = 1, DOLLAR = 2, /*PASCAL = 4,*/ DEFAULT = NO_REJECT};
|
||||
|
||||
// An empty cascade will be created.
|
||||
// Param minScale is a minimum scale relative to the original size of the image on which cascade will be applied.
|
||||
// Param minScale is a maximum scale relative to the original size of the image on which cascade will be applied.
|
||||
// Param scales is a number of scales from minScale to maxScale.
|
||||
// Param rejCriteria is used for NMS.
|
||||
CV_WRAP Detector(double minScale = 0.4, double maxScale = 5., int scales = 55, int rejCriteria = 1);
|
||||
|
||||
CV_WRAP virtual ~Detector();
|
||||
|
||||
cv::AlgorithmInfo* info() const;
|
||||
|
||||
// Load soft cascade from FileNode.
|
||||
// Param fileNode is a root node for cascade.
|
||||
CV_WRAP virtual bool load(const FileNode& fileNode);
|
||||
|
||||
// Load soft cascade config.
|
||||
CV_WRAP virtual void read(const FileNode& fileNode);
|
||||
|
||||
// Return the vector of Detection objects.
|
||||
// Param image is a frame on which detector will be applied.
|
||||
// Param rois is a vector of regions of interest. Only the objects that fall into one of the regions will be returned.
|
||||
// Param objects is an output array of Detections
|
||||
virtual void detect(InputArray image, InputArray rois, std::vector<Detection>& objects) const;
|
||||
|
||||
// Param rects is an output array of bounding rectangles for detected objects.
|
||||
// Param confs is an output array of confidence for detected objects. i-th bounding rectangle corresponds i-th confidence.
|
||||
CV_WRAP virtual void detect(InputArray image, InputArray rois, CV_OUT OutputArray rects, CV_OUT OutputArray confs) const;
|
||||
|
||||
private:
|
||||
void detectNoRoi(const Mat& image, std::vector<Detection>& objects) const;
|
||||
|
||||
struct Fields;
|
||||
Fields* fields;
|
||||
|
||||
double minScale;
|
||||
double maxScale;
|
||||
|
||||
int scales;
|
||||
int rejCriteria;
|
||||
};
|
||||
|
||||
// ========================================================================== //
|
||||
// Public Interface for singe soft (stageless) cascade octave training.
|
||||
// ========================================================================== //
|
||||
class CV_EXPORTS Octave : public cv::Algorithm
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
// Direct backward pruning. (Cha Zhang and Paul Viola)
|
||||
DBP = 1,
|
||||
// Multiple instance pruning. (Cha Zhang and Paul Viola)
|
||||
MIP = 2,
|
||||
// Originally proposed by L. Bourdev and J. Brandt
|
||||
HEURISTIC = 4
|
||||
};
|
||||
|
||||
virtual ~Octave();
|
||||
static cv::Ptr<Octave> create(cv::Rect boundingBox, int npositives, int nnegatives,
|
||||
int logScale, int shrinkage, int poolSize);
|
||||
|
||||
virtual bool train(const Dataset* dataset, const FeaturePool* pool, int weaks, int treeDepth) = 0;
|
||||
virtual void setRejectThresholds(OutputArray thresholds) = 0;
|
||||
virtual void write( cv::FileStorage &fs, const FeaturePool* pool, InputArray thresholds) const = 0;
|
||||
virtual void write( CvFileStorage* fs, string name) const = 0;
|
||||
};
|
||||
|
||||
CV_EXPORTS bool initModule_softcascade(void);
|
||||
|
||||
}} // namespace cv { namespace softcascade {
|
||||
|
||||
#endif
|
81
modules/softcascade/misc/detections2negatives.py
Executable file
81
modules/softcascade/misc/detections2negatives.py
Executable file
@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys, os, os.path, glob, math, cv2, string, random
|
||||
from datetime import datetime
|
||||
from optparse import OptionParser
|
||||
import re
|
||||
import numpy as np
|
||||
from xml.dom import minidom
|
||||
|
||||
def resize(image, d_w, d_h):
|
||||
if (d_h < image.shape[0]) or (d_w < image.shape[1]):
|
||||
ratio = min(d_h / float(image.shape[0]), d_w / float(image.shape[1]))
|
||||
|
||||
kernel_size = int( 5 / (2 * ratio))
|
||||
sigma = 0.5 / ratio
|
||||
image_to_resize = cv2.filter2D(image, cv2.CV_8UC3, cv2.getGaussianKernel(kernel_size, sigma))
|
||||
interpolation_type = cv2.INTER_AREA
|
||||
else:
|
||||
image_to_resize = image
|
||||
interpolation_type = cv2.INTER_CUBIC
|
||||
|
||||
return cv2.resize(image_to_resize,(d_w, d_h), None, 0, 0, interpolation_type)
|
||||
|
||||
def det2negative(xmldoc, opath):
|
||||
samples = xmldoc.getElementsByTagName('sample')
|
||||
for sample in samples:
|
||||
detections = sample.getElementsByTagName('detections')
|
||||
detections = minidom.parseString(detections[0].toxml())
|
||||
detections = detections.getElementsByTagName("_")
|
||||
if len(detections) is not 0:
|
||||
path = sample.getElementsByTagName("path")
|
||||
path = path[0].firstChild.nodeValue
|
||||
mat = cv2.imread(path)
|
||||
mat_h, mat_w, _ = mat.shape
|
||||
|
||||
for detection in detections:
|
||||
detection = detection.childNodes
|
||||
for each in detection:
|
||||
rect = eval(re.sub( r"\b\s\b", ",", re.sub(r"\n", "[", each.nodeValue )) + "]")
|
||||
print rect
|
||||
|
||||
ratio = 64.0 / rect[3]
|
||||
|
||||
print rect, ratio
|
||||
mat = resize(mat, int(round(mat_w * ratio)), int(round(mat_h * ratio)))
|
||||
|
||||
rect[0] = int(round(ratio * rect[0])) - 10
|
||||
rect[1] = int(round(ratio * rect[1])) - 10
|
||||
rect[2] = rect[0] + 32 + 20
|
||||
rect[3] = rect[1] + 64 + 20
|
||||
try:
|
||||
cropped = mat[rect[1]:(rect[3]), rect[0]:(rect[2]), :]
|
||||
img = os.path.join(opath, ''.join(random.choice(string.lowercase) for i in range(8)) + ".png")
|
||||
cr_h, cr_w, _ = cropped.shape
|
||||
if cr_h is 84 and cr_w is 52:
|
||||
cv2.imwrite(img, cropped)
|
||||
except:
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
parser = OptionParser()
|
||||
parser.add_option("-i", "--input", dest="input", metavar="DIRECTORY", type="string",
|
||||
help="Path to the xml collection folder.")
|
||||
|
||||
parser.add_option("-d", "--output-dir", dest="output", metavar="DIRECTORY", type="string",
|
||||
help="Path to store data", default=".")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if not options.input:
|
||||
parser.error("Input folder is required.")
|
||||
|
||||
opath = os.path.join(options.output, datetime.now().strftime("negatives" + "-%Y-%m-%d-%H-%M-%S"))
|
||||
os.mkdir(opath)
|
||||
|
||||
gl = glob.iglob( os.path.join(options.input, "set[0][0]_V0[0][5].seq.xml"))
|
||||
for f in gl:
|
||||
print f
|
||||
xmldoc = minidom.parse(f)
|
||||
det2negative(xmldoc, opath)
|
17
modules/softcascade/misc/roc_caltech.py
Executable file
17
modules/softcascade/misc/roc_caltech.py
Executable file
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
import sft
|
||||
|
||||
import sys, os, os.path, glob, math, cv2, re
|
||||
from datetime import datetime
|
||||
import numpy
|
||||
|
||||
if __name__ == "__main__":
|
||||
path = "/home/kellan/datasets/caltech/set00/V000.txt"
|
||||
# open annotation file
|
||||
f = open(path)
|
||||
annotations = sft.parse_caltech(f)
|
||||
|
||||
for each in annotations:
|
||||
print each
|
103
modules/softcascade/misc/roc_test.py
Executable file
103
modules/softcascade/misc/roc_test.py
Executable file
@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
import sft
|
||||
|
||||
import sys, os, os.path, glob, math, cv2
|
||||
from datetime import datetime
|
||||
import numpy
|
||||
|
||||
plot_colors = ['b', 'c', 'r', 'g', 'm']
|
||||
|
||||
# "key" : ( b, g, r)
|
||||
bgr = { "red" : ( 0, 0, 255),
|
||||
"green" : ( 0, 255, 0),
|
||||
"blue" : (255, 0 , 0)}
|
||||
|
||||
def range(s):
|
||||
try:
|
||||
lb, rb = map(int, s.split(','))
|
||||
return lb, rb
|
||||
except:
|
||||
raise argparse.ArgumentTypeError("Must be lb, rb")
|
||||
|
||||
def call_parser(f, a):
|
||||
return eval( "sft.parse_" + f + "('" + a + "')")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description = 'Plot ROC curve using Caltech method of per image detection performance estimation.')
|
||||
|
||||
# positional
|
||||
parser.add_argument("cascade", help = "Path to the tested detector.", nargs='+')
|
||||
parser.add_argument("input", help = "Image sequence pattern.")
|
||||
parser.add_argument("annotations", help = "Path to the annotations.")
|
||||
|
||||
# optional
|
||||
parser.add_argument("-m", "--min_scale", dest = "min_scale", type = float, metavar= "fl", help = "Minimum scale to be tested.", default = 0.4)
|
||||
parser.add_argument("-M", "--max_scale", dest = "max_scale", type = float, metavar= "fl", help = "Maximum scale to be tested.", default = 5.0)
|
||||
parser.add_argument("-o", "--output", dest = "output", type = str, metavar= "path", help = "Path to store resulting image.", default = "./roc.png")
|
||||
parser.add_argument("-n", "--nscales", dest = "nscales", type = int, metavar= "n", help = "Preferred count of scales from min to max.", default = 55)
|
||||
|
||||
parser.add_argument("-r", "--scale-range", dest = "scale_range", type = range, default = (128 * 0.4, 128 * 2.4))
|
||||
parser.add_argument("-e", "--extended-range-ratio", dest = "ext_ratio", type = float, default = 1.25)
|
||||
parser.add_argument("-t", "--title", dest = "title", type = str, default = "ROC curve Bahnhof")
|
||||
|
||||
# required
|
||||
parser.add_argument("-f", "--anttn-format", dest = "anttn_format", choices = ['inria', 'caltech', "idl"], help = "Annotation file for test sequence.", required = True)
|
||||
parser.add_argument("-l", "--labels", dest = "labels" ,required=True, help = "Plot labels for legend.", nargs='+')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
print args.scale_range
|
||||
|
||||
print args.cascade
|
||||
# parse annotations
|
||||
sft.initPlot(args.title)
|
||||
samples = call_parser(args.anttn_format, args.annotations)
|
||||
for idx, each in enumerate(args.cascade):
|
||||
print each
|
||||
cascade = sft.cascade(args.min_scale, args.max_scale, args.nscales, each)
|
||||
pattern = args.input
|
||||
camera = cv2.VideoCapture(pattern)
|
||||
|
||||
# for plotting over dataset
|
||||
nannotated = 0
|
||||
nframes = 0
|
||||
|
||||
confidenses = []
|
||||
tp = []
|
||||
ignored = []
|
||||
|
||||
while True:
|
||||
ret, img = camera.read()
|
||||
if not ret:
|
||||
break;
|
||||
|
||||
name = pattern % (nframes,)
|
||||
_, tail = os.path.split(name)
|
||||
|
||||
boxes = sft.filter_for_range(samples[tail], args.scale_range, args.ext_ratio)
|
||||
|
||||
nannotated = nannotated + len(boxes)
|
||||
nframes = nframes + 1
|
||||
rects, confs = cascade.detect(img, rois = None)
|
||||
|
||||
if confs is None:
|
||||
continue
|
||||
|
||||
dts = sft.convert2detections(rects, confs)
|
||||
|
||||
confs = confs.tolist()[0]
|
||||
confs.sort(lambda x, y : -1 if (x - y) > 0 else 1)
|
||||
confidenses = confidenses + confs
|
||||
|
||||
matched, skip_list = sft.match(boxes, dts)
|
||||
tp = tp + matched
|
||||
ignored = ignored + skip_list
|
||||
|
||||
print nframes, nannotated
|
||||
|
||||
fppi, miss_rate = sft.computeROC(confidenses, tp, nannotated, nframes, ignored)
|
||||
sft.plotLogLog(fppi, miss_rate, plot_colors[idx])
|
||||
|
||||
sft.showPlot(args.output, args.labels)
|
142
modules/softcascade/misc/scale_caltech.py
Executable file
142
modules/softcascade/misc/scale_caltech.py
Executable file
@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys, os, os.path, glob, math, cv2
|
||||
from datetime import datetime
|
||||
from optparse import OptionParser
|
||||
import re
|
||||
import numpy as np
|
||||
|
||||
def extractPositive(f, path, opath, octave, min_possible):
|
||||
newobj = re.compile("^lbl=\'(\w+)\'\s+str=(\d+)\s+end=(\d+)\s+hide=0$")
|
||||
pos = re.compile("^pos\s=(\[[((\d+\.+\d*)|\s+|\;)]*\])$")
|
||||
occl = re.compile("^occl\s*=(\[[0-1|\s]*\])$")
|
||||
|
||||
whole_mod_w = int(64 * octave) + 2 * int(20 * octave)
|
||||
whole_mod_h = int(128 * octave) + 2 * int(20 * octave)
|
||||
|
||||
goNext = 0
|
||||
start = 0
|
||||
end = 0
|
||||
|
||||
person_id = -1;
|
||||
|
||||
boxes = []
|
||||
occls = []
|
||||
|
||||
for l in f:
|
||||
m = newobj.match(l)
|
||||
if m is not None:
|
||||
if m.group(1) == "person":
|
||||
goNext = 1
|
||||
start = int(m.group(2))
|
||||
end = int(m.group(3))
|
||||
person_id = person_id + 1
|
||||
print m.group(1), person_id, start, end
|
||||
else:
|
||||
goNext = 0
|
||||
else:
|
||||
m = pos.match(l)
|
||||
if m is not None:
|
||||
if not goNext:
|
||||
continue
|
||||
strarr = re.sub(r"\s", ", ", re.sub(r"\;\s+(?=\])", "]", re.sub(r"\;\s+(?!\])", "],[", re.sub(r"(\[)(\d)", "\\1[\\2", m.group(1)))))
|
||||
boxes = eval(strarr)
|
||||
else:
|
||||
m = occl.match(l)
|
||||
if m is not None:
|
||||
occls = eval(re.sub(r"\s+(?!\])", ",", m.group(1)))
|
||||
|
||||
if len(boxes) > 0 and len(boxes) == len(occls):
|
||||
for idx, box in enumerate(boxes):
|
||||
if occls[idx] == 1:
|
||||
continue
|
||||
|
||||
x = box[0]
|
||||
y = box[1]
|
||||
w = box[2]
|
||||
h = box[3]
|
||||
|
||||
id = int(start) - 1 + idx
|
||||
file = os.path.join(path, "I0%04d.jpg" % id)
|
||||
|
||||
if (start + id) >= end or w < 10 or h < min_possible:
|
||||
continue
|
||||
|
||||
mat = cv2.imread(file)
|
||||
mat_h, mat_w, _ = mat.shape
|
||||
|
||||
# let default height of person be 96.
|
||||
scale = h / float(96)
|
||||
rel_scale = scale / octave
|
||||
|
||||
d_w = whole_mod_w * rel_scale
|
||||
d_h = whole_mod_h * rel_scale
|
||||
|
||||
tb = (d_h - h) / 2.0
|
||||
lr = (d_w - w) / 2.0
|
||||
|
||||
x = int(round(x - lr))
|
||||
y = int(round(y - tb))
|
||||
|
||||
w = int(round(w + lr * 2.0))
|
||||
h = int(round(h + tb * 2.0))
|
||||
|
||||
inner = [max(5, x), max(5, y), min(mat_w - 5, x + w), min(mat_h - 5, y + h) ]
|
||||
cropped = mat[inner[1]:inner[3], inner[0]:inner[2], :]
|
||||
|
||||
top = int(max(0, 0 - y))
|
||||
bottom = int(max(0, y + h - mat_h))
|
||||
left = int(max(0, 0 - x))
|
||||
right = int(max(0, x + w - mat_w))
|
||||
|
||||
if top < -d_h / 4.0 or bottom > d_h / 4.0 or left < -d_w / 4.0 or right > d_w / 4.0:
|
||||
continue
|
||||
|
||||
cropped = cv2.copyMakeBorder(cropped, top, bottom, left, right, cv2.BORDER_REPLICATE)
|
||||
resized = sft.resize_sample(cropped, whole_mod_w, whole_mod_h)
|
||||
flipped = cv2.flip(resized, 1)
|
||||
|
||||
cv2.imshow("resized", resized)
|
||||
|
||||
c = cv2.waitKey(20)
|
||||
if c == 27:
|
||||
exit(0)
|
||||
|
||||
fname = re.sub(r"^.*\/(set[0-1]\d)\/(V0\d\d)\.(seq)/(I\d+).jpg$", "\\1_\\2_\\4", file)
|
||||
fname = os.path.join(opath, fname + "_%04d." % person_id + "png")
|
||||
fname_fl = os.path.join(opath, fname + "_mirror_%04d." % person_id + "png")
|
||||
try:
|
||||
cv2.imwrite(fname, resized)
|
||||
cv2.imwrite(fname_fl, flipped)
|
||||
except:
|
||||
print "something wrong... go next."
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = OptionParser()
|
||||
parser.add_option("-i", "--input", dest="input", metavar="DIRECTORY", type="string",
|
||||
help="Path to the Caltech dataset folder.")
|
||||
|
||||
parser.add_option("-d", "--output-dir", dest="output", metavar="DIRECTORY", type="string",
|
||||
help="Path to store data", default=".")
|
||||
|
||||
parser.add_option("-o", "--octave", dest="octave", type="float",
|
||||
help="Octave for a dataset to be scaled", default="0.5")
|
||||
|
||||
parser.add_option("-m", "--min-possible", dest="min_possible", type="int",
|
||||
help="Minimum possible height for positive.", default="64")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if not options.input:
|
||||
parser.error("Caltech dataset folder is required.")
|
||||
|
||||
opath = os.path.join(options.output, datetime.now().strftime("raw_ge64_cr_mirr_ts" + "-%Y-%m-%d-%H-%M-%S"))
|
||||
os.mkdir(opath)
|
||||
|
||||
gl = glob.iglob( os.path.join(options.input, "set[0][0]/V0[0-9][0-9].txt"))
|
||||
for each in gl:
|
||||
path, ext = os.path.splitext(each)
|
||||
path = path + ".seq"
|
||||
print path
|
||||
extractPositive(open(each), path, opath, options.octave, options.min_possible)
|
139
modules/softcascade/misc/scale_inria.py
Executable file
139
modules/softcascade/misc/scale_inria.py
Executable file
@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys, os, os.path, glob, math, cv2
|
||||
from datetime import datetime
|
||||
from optparse import OptionParser
|
||||
|
||||
def parse(ipath, f):
|
||||
bbs = []
|
||||
path = None
|
||||
for l in f:
|
||||
box = None
|
||||
if l.startswith("Bounding box"):
|
||||
b = [x.strip() for x in l.split(":")[1].split("-")]
|
||||
c = [x[1:-1].split(",") for x in b]
|
||||
d = [int(x) for x in sum(c, [])]
|
||||
bbs.append(d)
|
||||
|
||||
if l.startswith("Image filename"):
|
||||
path = os.path.join(os.path.join(ipath, ".."), l.split('"')[-2])
|
||||
|
||||
return (path, bbs)
|
||||
|
||||
def adjust(box, tb, lr):
|
||||
|
||||
mix = int(round(box[0] - lr))
|
||||
miy = int(round(box[1] - tb))
|
||||
|
||||
max = int(round(box[2] + lr))
|
||||
may = int(round(box[3] + tb))
|
||||
|
||||
return [mix, miy, max, may]
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = OptionParser()
|
||||
parser.add_option("-i", "--input", dest="input", metavar="DIRECTORY", type="string",
|
||||
help="path to Inria train data folder")
|
||||
|
||||
parser.add_option("-o", "--output", dest="output", metavar="DIRECTORY", type="string",
|
||||
help="path to store data", default=".")
|
||||
|
||||
parser.add_option("-t", "--target", dest="target", type="string", help="should be train or test", default="train")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
if not options.input:
|
||||
parser.error("Inria data folder required")
|
||||
|
||||
if options.target not in ["train", "test"]:
|
||||
parser.error("dataset should contain train or test data")
|
||||
|
||||
octaves = [-1, 0, 1, 2]
|
||||
|
||||
path = os.path.join(options.output, datetime.now().strftime("rescaled-" + options.target + "-%Y-%m-%d-%H-%M-%S"))
|
||||
os.mkdir(path)
|
||||
|
||||
neg_path = os.path.join(path, "neg")
|
||||
os.mkdir(neg_path)
|
||||
|
||||
pos_path = os.path.join(path, "pos")
|
||||
os.mkdir(pos_path)
|
||||
|
||||
print "rescaled Inria training data stored into", path, "\nprocessing",
|
||||
for each in octaves:
|
||||
octave = 2**each
|
||||
|
||||
whole_mod_w = int(64 * octave) + 2 * int(20 * octave)
|
||||
whole_mod_h = int(128 * octave) + 2 * int(20 * octave)
|
||||
|
||||
cpos_path = os.path.join(pos_path, "octave_%d" % each)
|
||||
os.mkdir(cpos_path)
|
||||
idx = 0
|
||||
|
||||
gl = glob.iglob(os.path.join(options.input, "annotations/*.txt"))
|
||||
for image, boxes in [parse(options.input, open(__p)) for __p in gl]:
|
||||
for box in boxes:
|
||||
height = box[3] - box[1]
|
||||
scale = height / float(96)
|
||||
|
||||
mat = cv2.imread(image)
|
||||
mat_h, mat_w, _ = mat.shape
|
||||
|
||||
rel_scale = scale / octave
|
||||
|
||||
d_w = whole_mod_w * rel_scale
|
||||
d_h = whole_mod_h * rel_scale
|
||||
|
||||
top_bottom_border = (d_h - (box[3] - box[1])) / 2.0
|
||||
left_right_border = (d_w - (box[2] - box[0])) / 2.0
|
||||
|
||||
box = adjust(box, top_bottom_border, left_right_border)
|
||||
inner = [max(0, box[0]), max(0, box[1]), min(mat_w, box[2]), min(mat_h, box[3]) ]
|
||||
|
||||
cropped = mat[inner[1]:inner[3], inner[0]:inner[2], :]
|
||||
|
||||
top = int(max(0, 0 - box[1]))
|
||||
bottom = int(max(0, box[3] - mat_h))
|
||||
left = int(max(0, 0 - box[0]))
|
||||
right = int(max(0, box[2] - mat_w))
|
||||
cropped = cv2.copyMakeBorder(cropped, top, bottom, left, right, cv2.BORDER_REPLICATE)
|
||||
resized = sft.resize_sample(cropped, whole_mod_w, whole_mod_h)
|
||||
|
||||
out_name = ".png"
|
||||
if round(math.log(scale)/math.log(2)) < each:
|
||||
out_name = "_upscaled" + out_name
|
||||
|
||||
cv2.imwrite(os.path.join(cpos_path, "sample_%d" % idx + out_name), resized)
|
||||
|
||||
flipped = cv2.flip(resized, 1)
|
||||
cv2.imwrite(os.path.join(cpos_path, "sample_%d" % idx + "_mirror" + out_name), flipped)
|
||||
idx = idx + 1
|
||||
print "." ,
|
||||
sys.stdout.flush()
|
||||
|
||||
idx = 0
|
||||
cneg_path = os.path.join(neg_path, "octave_%d" % each)
|
||||
os.mkdir(cneg_path)
|
||||
|
||||
for each in [__n for __n in glob.iglob(os.path.join(options.input, "neg/*.*"))]:
|
||||
img = cv2.imread(each)
|
||||
min_shape = (1.5 * whole_mod_h, 1.5 * whole_mod_w)
|
||||
|
||||
if (img.shape[1] <= min_shape[1]) or (img.shape[0] <= min_shape[0]):
|
||||
out_name = "negative_sample_%i_resized.png" % idx
|
||||
|
||||
ratio = float(img.shape[1]) / img.shape[0]
|
||||
|
||||
if (img.shape[1] <= min_shape[1]):
|
||||
resized_size = (int(min_shape[1]), int(min_shape[1] / ratio))
|
||||
|
||||
if (img.shape[0] <= min_shape[0]):
|
||||
resized_size = (int(min_shape[0] * ratio), int(min_shape[0]))
|
||||
|
||||
img = sft.resize_sample(img, resized_size[0], resized_size[1])
|
||||
else:
|
||||
out_name = "negative_sample_%i.png" % idx
|
||||
|
||||
cv2.imwrite(os.path.join(cneg_path, out_name), img)
|
||||
idx = idx + 1
|
||||
print "." ,
|
||||
sys.stdout.flush()
|
281
modules/softcascade/misc/sft.py
Normal file
281
modules/softcascade/misc/sft.py
Normal file
@ -0,0 +1,281 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import cv2, re, glob
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from itertools import izip
|
||||
|
||||
""" Convert numPy matrices with rectangles and confidences to sorted list of detections."""
|
||||
def convert2detections(rects, confs, crop_factor = 0.125):
|
||||
if rects is None:
|
||||
return []
|
||||
|
||||
dts = zip(*[rects.tolist(), confs.tolist()])
|
||||
dts = zip(dts[0][0], dts[0][1])
|
||||
dts = [Detection(r,c) for r, c in dts]
|
||||
|
||||
dts.sort(lambda x, y : -1 if (x.conf - y.conf) > 0 else 1)
|
||||
|
||||
for dt in dts:
|
||||
dt.crop(crop_factor)
|
||||
|
||||
return dts
|
||||
|
||||
""" Create new instance of soft cascade."""
|
||||
def cascade(min_scale, max_scale, nscales, f):
|
||||
# where we use nms cv::SoftCascadeDetector::DOLLAR == 2
|
||||
c = cv2.softcascade_Detector(min_scale, max_scale, nscales, 2)
|
||||
xml = cv2.FileStorage(f, 0)
|
||||
dom = xml.getFirstTopLevelNode()
|
||||
assert c.load(dom)
|
||||
return c
|
||||
|
||||
""" Compute prefix sum for en array."""
|
||||
def cumsum(n):
|
||||
cum = []
|
||||
y = 0
|
||||
for i in n:
|
||||
y += i
|
||||
cum.append(y)
|
||||
return cum
|
||||
|
||||
""" Compute x and y arrays for ROC plot."""
|
||||
def computeROC(confidenses, tp, nannotated, nframes, ignored):
|
||||
confidenses, tp, ignored = zip(*sorted(zip(confidenses, tp, ignored), reverse = True))
|
||||
|
||||
fp = [(1 - x) for x in tp]
|
||||
fp = [(x - y) for x, y in izip(fp, ignored)]
|
||||
|
||||
fp = cumsum(fp)
|
||||
tp = cumsum(tp)
|
||||
miss_rate = [(1 - x / (nannotated + 0.000001)) for x in tp]
|
||||
fppi = [x / float(nframes) for x in fp]
|
||||
|
||||
return fppi, miss_rate
|
||||
|
||||
""" Crop rectangle by factor."""
|
||||
def crop_rect(rect, factor):
|
||||
val_x = factor * float(rect[2])
|
||||
val_y = factor * float(rect[3])
|
||||
x = [int(rect[0] + val_x), int(rect[1] + val_y), int(rect[2] - 2.0 * val_x), int(rect[3] - 2.0 * val_y)]
|
||||
return x
|
||||
|
||||
""" Initialize plot axises."""
|
||||
def initPlot(name):
|
||||
plt.xlabel("fppi")
|
||||
plt.ylabel("miss rate")
|
||||
plt.title(name)
|
||||
plt.grid(True)
|
||||
plt.xscale('log')
|
||||
plt.yscale('log')
|
||||
|
||||
""" Draw plot."""
|
||||
def plotLogLog(fppi, miss_rate, c):
|
||||
plt.loglog(fppi, miss_rate, color = c, linewidth = 2)
|
||||
|
||||
""" Show resulted plot."""
|
||||
def showPlot(file_name, labels):
|
||||
plt.axis((pow(10, -3), pow(10, 1), .035, 1))
|
||||
plt.yticks( [0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.64, 0.8, 1], ['.05', '.10', '.20', '.30', '.40', '.50', '.64', '.80', '1'] )
|
||||
plt.legend(labels, loc = "lower left")
|
||||
plt.savefig(file_name)
|
||||
plt.show()
|
||||
|
||||
""" Filter true positives and ignored detections for cascade detector output."""
|
||||
def match(gts, dts):
|
||||
matches_gt = [0]*len(gts)
|
||||
matches_dt = [0]*len(dts)
|
||||
matches_ignore = [0]*len(dts)
|
||||
|
||||
if len(gts) == 0:
|
||||
return matches_dt, matches_ignore
|
||||
|
||||
# Cartesian product for each detection BB_dt with each BB_gt
|
||||
overlaps = [[dt.overlap(gt) for gt in gts]for dt in dts]
|
||||
|
||||
for idx, row in enumerate(overlaps):
|
||||
imax = row.index(max(row))
|
||||
|
||||
# try to match ground truth
|
||||
if (matches_gt[imax] == 0 and row[imax] > 0.5):
|
||||
matches_gt[imax] = 1
|
||||
matches_dt[idx] = 1
|
||||
|
||||
for idx, dt in enumerate(dts):
|
||||
# try to math ignored
|
||||
if matches_dt[idx] == 0:
|
||||
row = gts
|
||||
row = [i for i in row if (i[3] - i[1]) < 53 or (i[3] - i[1]) > 256]
|
||||
for each in row:
|
||||
if dts[idx].overlapIgnored(each) > 0.5:
|
||||
matches_ignore[idx] = 1
|
||||
return matches_dt, matches_ignore
|
||||
|
||||
|
||||
""" Draw detections or ground truth on image."""
|
||||
def draw_rects(img, rects, color, l = lambda x, y : x + y):
|
||||
if rects is not None:
|
||||
for x1, y1, x2, y2 in rects:
|
||||
cv2.rectangle(img, (x1, y1), (l(x1, x2), l(y1, y2)), color, 2)
|
||||
|
||||
|
||||
def draw_dt(img, dts, color, l = lambda x, y : x + y):
|
||||
if dts is not None:
|
||||
for dt in dts:
|
||||
bb = dt.bb
|
||||
x1, y1, x2, y2 = dt.bb[0], dt.bb[1], dt.bb[2], dt.bb[3]
|
||||
|
||||
cv2.rectangle(img, (x1, y1), (l(x1, x2), l(y1, y2)), color, 2)
|
||||
|
||||
class Detection:
|
||||
def __init__(self, bb, conf):
|
||||
self.bb = bb
|
||||
self.conf = conf
|
||||
self.matched = False
|
||||
|
||||
def crop(self, factor):
|
||||
self.bb = crop_rect(self.bb, factor)
|
||||
|
||||
# we use rect-style for dt and box style for gt. ToDo: fix it
|
||||
def overlap(self, b):
|
||||
|
||||
a = self.bb
|
||||
w = min( a[0] + a[2], b[2]) - max(a[0], b[0]);
|
||||
h = min( a[1] + a[3], b[3]) - max(a[1], b[1]);
|
||||
|
||||
cross_area = 0.0 if (w < 0 or h < 0) else float(w * h)
|
||||
union_area = (a[2] * a[3]) + ((b[2] - b[0]) * (b[3] - b[1])) - cross_area;
|
||||
|
||||
return cross_area / union_area
|
||||
|
||||
# we use rect-style for dt and box style for gt. ToDo: fix it
|
||||
def overlapIgnored(self, b):
|
||||
|
||||
a = self.bb
|
||||
w = min( a[0] + a[2], b[2]) - max(a[0], b[0]);
|
||||
h = min( a[1] + a[3], b[3]) - max(a[1], b[1]);
|
||||
|
||||
cross_area = 0.0 if (w < 0 or h < 0) else float(w * h)
|
||||
self_area = (a[2] * a[3]);
|
||||
|
||||
return cross_area / self_area
|
||||
|
||||
def mark_matched(self):
|
||||
self.matched = True
|
||||
|
||||
"""Parse INPIA annotation format"""
|
||||
def parse_inria(ipath, f):
|
||||
bbs = []
|
||||
path = None
|
||||
for l in f:
|
||||
box = None
|
||||
if l.startswith("Bounding box"):
|
||||
b = [x.strip() for x in l.split(":")[1].split("-")]
|
||||
c = [x[1:-1].split(",") for x in b]
|
||||
d = [int(x) for x in sum(c, [])]
|
||||
bbs.append(d)
|
||||
|
||||
if l.startswith("Image filename"):
|
||||
path = l.split('"')[-2]
|
||||
|
||||
return Sample(path, bbs)
|
||||
|
||||
|
||||
def glob_set(pattern):
|
||||
return [__n for __n in glob.iglob(pattern)]
|
||||
|
||||
""" Parse ETH idl file. """
|
||||
def parse_idl(f):
|
||||
map = {}
|
||||
for l in open(f):
|
||||
l = re.sub(r"^\"left\/", "{\"", l)
|
||||
l = re.sub(r"\:", ":[", l)
|
||||
l = re.sub(r"(\;|\.)$", "]}", l)
|
||||
map.update(eval(l))
|
||||
return map
|
||||
|
||||
""" Normalize detection box to unified aspect ration."""
|
||||
def norm_box(box, ratio):
|
||||
middle = float(box[0] + box[2]) / 2.0
|
||||
new_half_width = float(box[3] - box[1]) * ratio / 2.0
|
||||
return (int(round(middle - new_half_width)), box[1], int(round(middle + new_half_width)), box[3])
|
||||
|
||||
""" Process array of boxes."""
|
||||
def norm_acpect_ratio(boxes, ratio):
|
||||
return [ norm_box(box, ratio) for box in boxes]
|
||||
|
||||
""" Filter detections out of extended range. """
|
||||
def filter_for_range(boxes, scale_range, ext_ratio):
|
||||
boxes = norm_acpect_ratio(boxes, 0.5)
|
||||
boxes = [b for b in boxes if (b[3] - b[1]) > scale_range[0] / ext_ratio]
|
||||
boxes = [b for b in boxes if (b[3] - b[1]) < scale_range[1] * ext_ratio]
|
||||
return boxes
|
||||
|
||||
""" Resize sample for training."""
|
||||
def resize_sample(image, d_w, d_h):
|
||||
h, w, _ = image.shape
|
||||
if (d_h < h) or (d_w < w):
|
||||
ratio = min(d_h / float(h), d_w / float(w))
|
||||
|
||||
kernel_size = int( 5 / (2 * ratio))
|
||||
sigma = 0.5 / ratio
|
||||
image_to_resize = cv2.filter2D(image, cv2.CV_8UC3, cv2.getGaussianKernel(kernel_size, sigma))
|
||||
interpolation_type = cv2.INTER_AREA
|
||||
else:
|
||||
image_to_resize = image
|
||||
interpolation_type = cv2.INTER_CUBIC
|
||||
|
||||
return cv2.resize(image_to_resize,(d_w, d_h), None, 0, 0, interpolation_type)
|
||||
|
||||
newobj = re.compile("^lbl=\'(\w+)\'\s+str=(\d+)\s+end=(\d+)\s+hide=0$")
|
||||
|
||||
class caltech:
|
||||
@staticmethod
|
||||
def extract_objects(f):
|
||||
objects = []
|
||||
tmp = []
|
||||
for l in f:
|
||||
if newobj.match(l) is not None:
|
||||
objects.append(tmp)
|
||||
tmp = []
|
||||
tmp.append(l)
|
||||
return objects[1:]
|
||||
|
||||
@staticmethod
|
||||
def parse_header(f):
|
||||
_ = f.readline() # skip first line (version string)
|
||||
head = f.readline()
|
||||
(nFrame, nSample) = re.search(r'nFrame=(\d+) n=(\d+)', head).groups()
|
||||
return (int(nFrame), int(nSample))
|
||||
|
||||
@staticmethod
|
||||
def parse_pos(l):
|
||||
pos = re.match(r'^posv?\s*=(\[[\d\s\.\;]+\])$', l).group(1)
|
||||
pos = re.sub(r"(\[)(\d)", "\\1[\\2", pos)
|
||||
pos = re.sub(r"\s", ", ", re.sub(r"\;\s+(?=\])", "]", re.sub(r"\;\s+(?!\])", "],[", pos)))
|
||||
return eval(pos)
|
||||
|
||||
@staticmethod
|
||||
def parse_occl(l):
|
||||
occl = re.match(r'^occl\s*=(\[[\d\s\.\;]+\])$', l).group(1)
|
||||
occl = re.sub(r"\s(?!\])", ",", occl)
|
||||
return eval(occl)
|
||||
|
||||
def parse_caltech(f):
|
||||
(nFrame, nSample) = caltech.parse_header(f)
|
||||
objects = caltech.extract_objects(f)
|
||||
|
||||
annotations = [[] for i in range(nFrame)]
|
||||
for obj in objects:
|
||||
(type, start, end) = re.search(r'^lbl=\'(\w+)\'\s+str=(\d+)\s+end=(\d+)\s+hide=0$', obj[0]).groups()
|
||||
print type, start, end
|
||||
start = int(start) -1
|
||||
end = int(end)
|
||||
pos = caltech.parse_pos(obj[1])
|
||||
posv = caltech.parse_pos(obj[2])
|
||||
occl = caltech.parse_occl(obj[3])
|
||||
|
||||
for idx, (p, pv, oc) in enumerate(zip(*[pos, posv, occl])):
|
||||
annotations[start + idx].append((type, p, oc, pv))
|
||||
|
||||
return annotations
|
45
modules/softcascade/perf/perf_main.cpp
Normal file
45
modules/softcascade/perf/perf_main.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
CV_PERF_TEST_MAIN(softcascade)
|
0
modules/softcascade/perf/perf_precomp.
Normal file
0
modules/softcascade/perf/perf_precomp.
Normal file
43
modules/softcascade/perf/perf_precomp.cpp
Normal file
43
modules/softcascade/perf/perf_precomp.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
62
modules/softcascade/perf/perf_precomp.hpp
Normal file
62
modules/softcascade/perf/perf_precomp.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wmissing-declarations"
|
||||
# if defined __clang__ || defined __APPLE__
|
||||
# pragma GCC diagnostic ignored "-Wmissing-prototypes"
|
||||
# pragma GCC diagnostic ignored "-Wextra"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef __OPENCV_PERF_PRECOMP_HPP__
|
||||
#define __OPENCV_PERF_PRECOMP_HPP__
|
||||
|
||||
# include "opencv2/ts/ts.hpp"
|
||||
# include "opencv2/softcascade/softcascade.hpp"
|
||||
# include "opencv2/highgui/highgui.hpp"
|
||||
|
||||
#ifdef GTEST_CREATE_SHARED_LIBRARY
|
||||
# error no modules except ts should have GTEST_CREATE_SHARED_LIBRARY defined
|
||||
#endif
|
||||
|
||||
#endif
|
47
modules/softcascade/perf/perf_softcascade.cpp
Normal file
47
modules/softcascade/perf/perf_softcascade.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "perf_precomp.hpp"
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
|
||||
using cv::Rect;
|
||||
using std::tr1::get;
|
||||
|
||||
|
||||
using namespace cv::softcascade;
|
||||
|
||||
typedef std::tr1::tuple<std::string, std::string> fixture;
|
||||
typedef perf::TestBaseWithParam<fixture> detect;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void extractRacts(std::vector<Detection> objectBoxes, std::vector<Rect>& rects)
|
||||
{
|
||||
rects.clear();
|
||||
for (int i = 0; i < (int)objectBoxes.size(); ++i)
|
||||
rects.push_back(objectBoxes[i].bb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PERF_TEST_P(detect, SoftCascadeDetector,
|
||||
testing::Combine(testing::Values(std::string("cv/cascadeandhog/cascades/inria_caltech-17.01.2013.xml")),
|
||||
testing::Values(std::string("cv/cascadeandhog/images/image_00000000_0.png"))))
|
||||
{
|
||||
cv::Mat colored = cv::imread(getDataPath(get<1>(GetParam())));
|
||||
ASSERT_FALSE(colored.empty());
|
||||
|
||||
Detector cascade;
|
||||
cv::FileStorage fs(getDataPath(get<0>(GetParam())), cv::FileStorage::READ);
|
||||
ASSERT_TRUE(fs.isOpened());
|
||||
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
|
||||
|
||||
std::vector<Detection> objectBoxes;
|
||||
TEST_CYCLE()
|
||||
{
|
||||
cascade.detect(colored, cv::noArray(), objectBoxes);
|
||||
}
|
||||
|
||||
std::vector<Rect> rects;
|
||||
extractRacts(objectBoxes, rects);
|
||||
std::sort(rects.begin(), rects.end(), perf::comparators::RectLess());
|
||||
SANITY_CHECK(rects);
|
||||
}
|
152
modules/softcascade/src/_random.hpp
Normal file
152
modules/softcascade/src/_random.hpp
Normal file
@ -0,0 +1,152 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2012, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __SFT_RANDOM_HPP__
|
||||
#define __SFT_RANDOM_HPP__
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1600
|
||||
# include <random>
|
||||
|
||||
namespace cv { namespace softcascade { namespace internal
|
||||
{
|
||||
|
||||
struct Random
|
||||
{
|
||||
typedef std::mt19937 engine;
|
||||
typedef std::uniform_int<int> uniform;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#elif (__GNUC__) && __GNUC__ > 3 && __GNUC_MINOR__ > 1 && !defined(__ANDROID__)
|
||||
# if defined (__cplusplus) && __cplusplus > 201100L
|
||||
# include <random>
|
||||
|
||||
namespace cv { namespace softcascade { namespace internal
|
||||
{
|
||||
|
||||
struct Random
|
||||
{
|
||||
typedef std::mt19937 engine;
|
||||
typedef std::uniform_int<int> uniform;
|
||||
};
|
||||
}}}
|
||||
|
||||
# else
|
||||
# include <tr1/random>
|
||||
|
||||
namespace cv { namespace softcascade { namespace internal
|
||||
{
|
||||
|
||||
struct Random
|
||||
{
|
||||
typedef std::tr1::mt19937 engine;
|
||||
typedef std::tr1::uniform_int<int> uniform;
|
||||
};
|
||||
|
||||
}}}
|
||||
# endif
|
||||
|
||||
#else
|
||||
# include <opencv2/core/core.hpp>
|
||||
|
||||
namespace cv { namespace softcascade { namespace internal
|
||||
{
|
||||
namespace rnd {
|
||||
|
||||
typedef cv::RNG engine;
|
||||
|
||||
template<typename T>
|
||||
struct uniform_int
|
||||
{
|
||||
uniform_int(const int _min, const int _max) : min(_min), max(_max) {}
|
||||
T operator() (engine& eng, const int bound) const
|
||||
{
|
||||
return (T)eng.uniform(min, bound);
|
||||
}
|
||||
|
||||
T operator() (engine& eng) const
|
||||
{
|
||||
return (T)eng.uniform(min, max);
|
||||
}
|
||||
|
||||
private:
|
||||
int min;
|
||||
int max;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
struct Random
|
||||
{
|
||||
typedef rnd::engine engine;
|
||||
typedef rnd::uniform_int<int> uniform;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined _WIN32 && (_WIN32 || _WIN64)
|
||||
# if _WIN64
|
||||
# define USE_LONG_SEEDS
|
||||
# endif
|
||||
#endif
|
||||
#if defined (__GNUC__) &&__GNUC__
|
||||
# if defined(__x86_64__) || defined(__ppc64__)
|
||||
# define USE_LONG_SEEDS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined USE_LONG_SEEDS
|
||||
# define FEATURE_RECT_SEED 8854342234LU
|
||||
# define INDEX_ENGINE_SEED 764224349868LU
|
||||
#else
|
||||
# define FEATURE_RECT_SEED 88543422LU
|
||||
# define INDEX_ENGINE_SEED 76422434LU
|
||||
#endif
|
||||
#undef USE_LONG_SEEDS
|
||||
|
||||
#define DCHANNELS_SEED 314152314LU
|
||||
#define DX_DY_SEED 65633343LU
|
||||
|
||||
#endif
|
262
modules/softcascade/src/integral_channel_builder.cpp
Normal file
262
modules/softcascade/src/integral_channel_builder.cpp
Normal file
@ -0,0 +1,262 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace cv::softcascade;
|
||||
|
||||
class ICFBuilder : public ChannelFeatureBuilder
|
||||
{
|
||||
virtual ~ICFBuilder() {}
|
||||
virtual cv::AlgorithmInfo* info() const;
|
||||
|
||||
virtual void operator()(cv::InputArray _frame, CV_OUT cv::OutputArray _integrals) const
|
||||
{
|
||||
CV_Assert(_frame.type() == CV_8UC3);
|
||||
|
||||
cv::Mat frame = _frame.getMat();
|
||||
int h = frame.rows;
|
||||
int w = frame.cols;
|
||||
_integrals.create(h / 4 * 10 + 1, w / 4 + 1, CV_32SC1);
|
||||
cv::Mat& integrals = _integrals.getMatRef();
|
||||
|
||||
cv::Mat channels, gray;
|
||||
|
||||
channels.create(h * 10, w, CV_8UC1);
|
||||
channels.setTo(0);
|
||||
|
||||
cvtColor(frame, gray, CV_BGR2GRAY);
|
||||
|
||||
cv::Mat df_dx, df_dy, mag, angle;
|
||||
cv::Sobel(gray, df_dx, CV_32F, 1, 0);
|
||||
cv::Sobel(gray, df_dy, CV_32F, 0, 1);
|
||||
|
||||
cv::cartToPolar(df_dx, df_dy, mag, angle, true);
|
||||
mag *= (1.f / (8 * sqrt(2.f)));
|
||||
|
||||
cv::Mat nmag;
|
||||
mag.convertTo(nmag, CV_8UC1);
|
||||
|
||||
angle *= 6 / 360.f;
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
uchar* magnitude = nmag.ptr<uchar>(y);
|
||||
float* ang = angle.ptr<float>(y);
|
||||
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
channels.ptr<uchar>(y + (h * (int)ang[x]))[x] = magnitude[x];
|
||||
}
|
||||
}
|
||||
|
||||
cv::Mat luv, shrunk;
|
||||
cv::cvtColor(frame, luv, CV_BGR2Luv);
|
||||
|
||||
std::vector<cv::Mat> splited;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
splited.push_back(channels(cv::Rect(0, h * (7 + i), w, h)));
|
||||
split(luv, splited);
|
||||
|
||||
float shrinkage = static_cast<float>(integrals.cols - 1) / channels.cols;
|
||||
|
||||
CV_Assert(shrinkage == 0.25);
|
||||
|
||||
cv::resize(channels, shrunk, cv::Size(), shrinkage, shrinkage, CV_INTER_AREA);
|
||||
cv::integral(shrunk, integrals, cv::noArray(), CV_32S);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using cv::softcascade::ChannelFeatureBuilder;
|
||||
using cv::softcascade::ChannelFeature;
|
||||
|
||||
CV_INIT_ALGORITHM(ICFBuilder, "ChannelFeatureBuilder.ICFBuilder", );
|
||||
|
||||
ChannelFeatureBuilder::~ChannelFeatureBuilder() {}
|
||||
|
||||
cv::Ptr<ChannelFeatureBuilder> ChannelFeatureBuilder::create()
|
||||
{
|
||||
cv::Ptr<ChannelFeatureBuilder> builder(new ICFBuilder());
|
||||
return builder;
|
||||
}
|
||||
|
||||
ChannelFeature::ChannelFeature(int x, int y, int w, int h, int ch)
|
||||
: bb(cv::Rect(x, y, w, h)), channel(ch) {}
|
||||
|
||||
bool ChannelFeature::operator ==(ChannelFeature b)
|
||||
{
|
||||
return bb == b.bb && channel == b.channel;
|
||||
}
|
||||
|
||||
bool ChannelFeature::operator !=(ChannelFeature b)
|
||||
{
|
||||
return bb != b.bb || channel != b.channel;
|
||||
}
|
||||
|
||||
|
||||
float ChannelFeature::operator() (const cv::Mat& integrals, const cv::Size& model) const
|
||||
{
|
||||
int step = model.width + 1;
|
||||
|
||||
const int* ptr = integrals.ptr<int>(0) + (model.height * channel + bb.y) * step + bb.x;
|
||||
|
||||
int a = ptr[0];
|
||||
int b = ptr[bb.width];
|
||||
|
||||
ptr += bb.height * step;
|
||||
|
||||
int c = ptr[bb.width];
|
||||
int d = ptr[0];
|
||||
|
||||
return (float)(a - b + c - d);
|
||||
}
|
||||
|
||||
void cv::softcascade::write(cv::FileStorage& fs, const string&, const ChannelFeature& f)
|
||||
{
|
||||
fs << "{" << "channel" << f.channel << "rect" << f.bb << "}";
|
||||
}
|
||||
|
||||
std::ostream& cv::softcascade::operator<<(std::ostream& out, const ChannelFeature& m)
|
||||
{
|
||||
out << m.channel << " " << m.bb;
|
||||
return out;
|
||||
}
|
||||
|
||||
ChannelFeature::~ChannelFeature(){}
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace cv::softcascade;
|
||||
|
||||
class ChannelFeaturePool : public FeaturePool
|
||||
{
|
||||
public:
|
||||
ChannelFeaturePool(cv::Size m, int n) : FeaturePool(), model(m)
|
||||
{
|
||||
CV_Assert(m != cv::Size() && n > 0);
|
||||
fill(n);
|
||||
}
|
||||
|
||||
virtual int size() const { return (int)pool.size(); }
|
||||
virtual float apply(int fi, int si, const cv::Mat& integrals) const;
|
||||
virtual void write( cv::FileStorage& fs, int index) const;
|
||||
|
||||
virtual ~ChannelFeaturePool() {}
|
||||
|
||||
private:
|
||||
|
||||
void fill(int desired);
|
||||
|
||||
cv::Size model;
|
||||
std::vector<ChannelFeature> pool;
|
||||
enum { N_CHANNELS = 10 };
|
||||
};
|
||||
|
||||
float ChannelFeaturePool::apply(int fi, int si, const cv::Mat& integrals) const
|
||||
{
|
||||
return pool[fi](integrals.row(si), model);
|
||||
}
|
||||
|
||||
void ChannelFeaturePool::write( cv::FileStorage& fs, int index) const
|
||||
{
|
||||
CV_Assert((index > 0) && (index < (int)pool.size()));
|
||||
fs << pool[index];
|
||||
}
|
||||
|
||||
void ChannelFeaturePool::fill(int desired)
|
||||
{
|
||||
using namespace cv::softcascade::internal;
|
||||
int mw = model.width;
|
||||
int mh = model.height;
|
||||
|
||||
int maxPoolSize = (mw -1) * mw / 2 * (mh - 1) * mh / 2 * N_CHANNELS;
|
||||
|
||||
int nfeatures = std::min(desired, maxPoolSize);
|
||||
pool.reserve(nfeatures);
|
||||
|
||||
Random::engine eng(FEATURE_RECT_SEED);
|
||||
Random::engine eng_ch(DCHANNELS_SEED);
|
||||
|
||||
Random::uniform chRand(0, N_CHANNELS - 1);
|
||||
|
||||
Random::uniform xRand(0, model.width - 2);
|
||||
Random::uniform yRand(0, model.height - 2);
|
||||
|
||||
Random::uniform wRand(1, model.width - 1);
|
||||
Random::uniform hRand(1, model.height - 1);
|
||||
|
||||
while (pool.size() < size_t(nfeatures))
|
||||
{
|
||||
int x = xRand(eng);
|
||||
int y = yRand(eng);
|
||||
|
||||
int w = 1 + wRand(eng, model.width - x - 1);
|
||||
int h = 1 + hRand(eng, model.height - y - 1);
|
||||
|
||||
CV_Assert(w > 0);
|
||||
CV_Assert(h > 0);
|
||||
|
||||
CV_Assert(w + x < model.width);
|
||||
CV_Assert(h + y < model.height);
|
||||
|
||||
int ch = chRand(eng_ch);
|
||||
|
||||
ChannelFeature f(x, y, w, h, ch);
|
||||
|
||||
if (std::find(pool.begin(), pool.end(),f) == pool.end())
|
||||
{
|
||||
pool.push_back(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cv::Ptr<FeaturePool> FeaturePool::create(const cv::Size& model, int nfeatures)
|
||||
{
|
||||
cv::Ptr<FeaturePool> pool(new ChannelFeaturePool(model, nfeatures));
|
||||
return pool;
|
||||
}
|
43
modules/softcascade/src/precomp.cpp
Normal file
43
modules/softcascade/src/precomp.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
58
modules/softcascade/src/precomp.hpp
Normal file
58
modules/softcascade/src/precomp.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_PRECOMP_H__
|
||||
#define __OPENCV_PRECOMP_H__
|
||||
|
||||
#ifdef HAVE_CVCONFIG_H
|
||||
#include "cvconfig.h"
|
||||
#endif
|
||||
|
||||
#include "opencv2/softcascade/softcascade.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/imgproc/imgproc_c.h"
|
||||
#include "opencv2/core/core_c.h"
|
||||
#include "opencv2/core/internal.hpp"
|
||||
#include "opencv2/ml/ml.hpp"
|
||||
#include "_random.hpp"
|
||||
|
||||
#endif
|
455
modules/softcascade/src/soft_cascade_octave.cpp
Normal file
455
modules/softcascade/src/soft_cascade_octave.cpp
Normal file
@ -0,0 +1,455 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
using cv::InputArray;
|
||||
using cv::OutputArray;
|
||||
using cv::Mat;
|
||||
|
||||
using cv::softcascade::Octave;
|
||||
using cv::softcascade::FeaturePool;
|
||||
using cv::softcascade::Dataset;
|
||||
using cv::softcascade::ChannelFeatureBuilder;
|
||||
|
||||
FeaturePool::~FeaturePool(){}
|
||||
Dataset::~Dataset(){}
|
||||
|
||||
namespace {
|
||||
|
||||
class BoostedSoftCascadeOctave : public cv::Boost, public Octave
|
||||
{
|
||||
public:
|
||||
|
||||
BoostedSoftCascadeOctave(cv::Rect boundingBox = cv::Rect(), int npositives = 0, int nnegatives = 0, int logScale = 0,
|
||||
int shrinkage = 1, int poolSize = 0);
|
||||
virtual ~BoostedSoftCascadeOctave();
|
||||
virtual cv::AlgorithmInfo* info() const;
|
||||
virtual bool train(const Dataset* dataset, const FeaturePool* pool, int weaks, int treeDepth);
|
||||
virtual void setRejectThresholds(OutputArray thresholds);
|
||||
virtual void write( cv::FileStorage &fs, const FeaturePool* pool, InputArray thresholds) const;
|
||||
virtual void write( CvFileStorage* fs, std::string name) const;
|
||||
protected:
|
||||
virtual float predict( InputArray _sample, InputArray _votes, bool raw_mode, bool return_sum ) const;
|
||||
virtual bool train( const cv::Mat& trainData, const cv::Mat& responses, const cv::Mat& varIdx=cv::Mat(),
|
||||
const cv::Mat& sampleIdx=cv::Mat(), const cv::Mat& varType=cv::Mat(), const cv::Mat& missingDataMask=cv::Mat());
|
||||
|
||||
void processPositives(const Dataset* dataset);
|
||||
void generateNegatives(const Dataset* dataset);
|
||||
|
||||
float predict( const Mat& _sample, const cv::Range range) const;
|
||||
private:
|
||||
void traverse(const CvBoostTree* tree, cv::FileStorage& fs, int& nfeatures, int* used, const double* th) const;
|
||||
virtual void initialize_weights(double (&p)[2]);
|
||||
|
||||
int logScale;
|
||||
cv::Rect boundingBox;
|
||||
|
||||
int npositives;
|
||||
int nnegatives;
|
||||
|
||||
int shrinkage;
|
||||
|
||||
Mat integrals;
|
||||
Mat responses;
|
||||
|
||||
CvBoostParams params;
|
||||
|
||||
Mat trainData;
|
||||
|
||||
cv::Ptr<ChannelFeatureBuilder> builder;
|
||||
};
|
||||
|
||||
BoostedSoftCascadeOctave::BoostedSoftCascadeOctave(cv::Rect bb, int np, int nn, int ls, int shr, int poolSize)
|
||||
: logScale(ls), boundingBox(bb), npositives(np), nnegatives(nn), shrinkage(shr)
|
||||
{
|
||||
int maxSample = npositives + nnegatives;
|
||||
responses.create(maxSample, 1, CV_32FC1);
|
||||
|
||||
CvBoostParams _params;
|
||||
{
|
||||
// tree params
|
||||
_params.max_categories = 10;
|
||||
_params.max_depth = 2;
|
||||
_params.cv_folds = 0;
|
||||
_params.truncate_pruned_tree = false;
|
||||
_params.use_surrogates = false;
|
||||
_params.use_1se_rule = false;
|
||||
_params.regression_accuracy = 1.0e-6;
|
||||
|
||||
// boost params
|
||||
_params.boost_type = CvBoost::GENTLE;
|
||||
_params.split_criteria = CvBoost::SQERR;
|
||||
_params.weight_trim_rate = 0.95;
|
||||
|
||||
// simple defaults
|
||||
_params.min_sample_count = 2;
|
||||
_params.weak_count = 1;
|
||||
}
|
||||
|
||||
params = _params;
|
||||
|
||||
builder = ChannelFeatureBuilder::create();
|
||||
|
||||
int w = boundingBox.width;
|
||||
int h = boundingBox.height;
|
||||
|
||||
integrals.create(poolSize, (w / shrinkage + 1) * (h / shrinkage * 10 + 1), CV_32SC1);
|
||||
}
|
||||
|
||||
BoostedSoftCascadeOctave::~BoostedSoftCascadeOctave(){}
|
||||
|
||||
bool BoostedSoftCascadeOctave::train( const cv::Mat& _trainData, const cv::Mat& _responses, const cv::Mat& varIdx,
|
||||
const cv::Mat& sampleIdx, const cv::Mat& varType, const cv::Mat& missingDataMask)
|
||||
{
|
||||
bool update = false;
|
||||
return cv::Boost::train(_trainData, CV_COL_SAMPLE, _responses, varIdx, sampleIdx, varType, missingDataMask, params,
|
||||
update);
|
||||
}
|
||||
|
||||
void BoostedSoftCascadeOctave::setRejectThresholds(cv::OutputArray _thresholds)
|
||||
{
|
||||
// labels decided by classifier
|
||||
cv::Mat desisions(responses.cols, responses.rows, responses.type());
|
||||
float* dptr = desisions.ptr<float>(0);
|
||||
|
||||
// mask of samples satisfying the condition
|
||||
cv::Mat ppmask(responses.cols, responses.rows, CV_8UC1);
|
||||
uchar* mptr = ppmask.ptr<uchar>(0);
|
||||
|
||||
int nsamples = npositives + nnegatives;
|
||||
|
||||
cv::Mat stab;
|
||||
|
||||
for (int si = 0; si < nsamples; ++si)
|
||||
{
|
||||
float decision = dptr[si] = predict(trainData.col(si), stab, false, false);
|
||||
mptr[si] = cv::saturate_cast<uchar>((unsigned int)( (responses.ptr<float>(si)[0] == 1.f) && (decision == 1.f)));
|
||||
}
|
||||
|
||||
int weaks = weak->total;
|
||||
_thresholds.create(1, weaks, CV_64FC1);
|
||||
cv::Mat& thresholds = _thresholds.getMatRef();
|
||||
double* thptr = thresholds.ptr<double>(0);
|
||||
|
||||
cv::Mat traces(weaks, nsamples, CV_64FC1, cv::Scalar::all(FLT_MAX));
|
||||
|
||||
for (int w = 0; w < weaks; ++w)
|
||||
{
|
||||
double* rptr = traces.ptr<double>(w);
|
||||
for (int si = 0; si < nsamples; ++si)
|
||||
{
|
||||
cv::Range curr(0, w + 1);
|
||||
if (mptr[si])
|
||||
{
|
||||
float trace = predict(trainData.col(si), curr);
|
||||
rptr[si] = trace;
|
||||
}
|
||||
}
|
||||
double mintrace = 0.;
|
||||
cv::minMaxLoc(traces.row(w), &mintrace);
|
||||
thptr[w] = mintrace;
|
||||
}
|
||||
}
|
||||
|
||||
void BoostedSoftCascadeOctave::processPositives(const Dataset* dataset)
|
||||
{
|
||||
int h = boundingBox.height;
|
||||
|
||||
ChannelFeatureBuilder& _builder = *builder;
|
||||
|
||||
int total = 0;
|
||||
for (int curr = 0; curr < dataset->available( Dataset::POSITIVE); ++curr)
|
||||
{
|
||||
cv::Mat sample = dataset->get( Dataset::POSITIVE, curr);
|
||||
|
||||
cv::Mat channels = integrals.row(total).reshape(0, h / shrinkage * 10 + 1);
|
||||
sample = sample(boundingBox);
|
||||
|
||||
_builder(sample, channels);
|
||||
responses.ptr<float>(total)[0] = 1.f;
|
||||
|
||||
if (++total >= npositives) break;
|
||||
}
|
||||
npositives = total;
|
||||
nnegatives = cvRound(nnegatives * total / (double)npositives);
|
||||
}
|
||||
|
||||
void BoostedSoftCascadeOctave::generateNegatives(const Dataset* dataset)
|
||||
{
|
||||
using namespace cv::softcascade::internal;
|
||||
// ToDo: set seed, use offsets
|
||||
Random::engine eng(DX_DY_SEED);
|
||||
Random::engine idxEng(INDEX_ENGINE_SEED);
|
||||
|
||||
int h = boundingBox.height;
|
||||
|
||||
int nimages = dataset->available(Dataset::NEGATIVE);
|
||||
Random::uniform iRand(0, nimages - 1);
|
||||
|
||||
int total = 0;
|
||||
Mat sum;
|
||||
|
||||
ChannelFeatureBuilder& _builder = *builder;
|
||||
for (int i = npositives; i < nnegatives + npositives; ++total)
|
||||
{
|
||||
int curr = iRand(idxEng);
|
||||
|
||||
Mat frame = dataset->get(Dataset::NEGATIVE, curr);
|
||||
|
||||
int maxW = frame.cols - 2 * boundingBox.x - boundingBox.width;
|
||||
int maxH = frame.rows - 2 * boundingBox.y - boundingBox.height;
|
||||
|
||||
Random::uniform wRand(0, maxW -1);
|
||||
Random::uniform hRand(0, maxH -1);
|
||||
|
||||
int dx = wRand(eng);
|
||||
int dy = hRand(eng);
|
||||
|
||||
frame = frame(cv::Rect(dx, dy, boundingBox.width, boundingBox.height));
|
||||
|
||||
cv::Mat channels = integrals.row(i).reshape(0, h / shrinkage * 10 + 1);
|
||||
_builder(frame, channels);
|
||||
|
||||
// // if (predict(sum))
|
||||
{
|
||||
responses.ptr<float>(i)[0] = 0.f;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T> int sgn(T val) {
|
||||
return (T(0) < val) - (val < T(0));
|
||||
}
|
||||
|
||||
void BoostedSoftCascadeOctave::traverse(const CvBoostTree* tree, cv::FileStorage& fs, int& nfeatures, int* used, const double* th) const
|
||||
{
|
||||
std::queue<const CvDTreeNode*> nodes;
|
||||
nodes.push( tree->get_root());
|
||||
const CvDTreeNode* tempNode;
|
||||
int leafValIdx = 0;
|
||||
int internalNodeIdx = 1;
|
||||
float* leafs = new float[(int)pow(2.f, get_params().max_depth)];
|
||||
|
||||
fs << "{";
|
||||
fs << "treeThreshold" << *th;
|
||||
fs << "internalNodes" << "[";
|
||||
while (!nodes.empty())
|
||||
{
|
||||
tempNode = nodes.front();
|
||||
CV_Assert( tempNode->left );
|
||||
if ( !tempNode->left->left && !tempNode->left->right)
|
||||
{
|
||||
leafs[-leafValIdx] = (float)tempNode->left->value;
|
||||
fs << leafValIdx-- ;
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes.push( tempNode->left );
|
||||
fs << internalNodeIdx++;
|
||||
}
|
||||
CV_Assert( tempNode->right );
|
||||
if ( !tempNode->right->left && !tempNode->right->right)
|
||||
{
|
||||
leafs[-leafValIdx] = (float)tempNode->right->value;
|
||||
fs << leafValIdx--;
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes.push( tempNode->right );
|
||||
fs << internalNodeIdx++;
|
||||
}
|
||||
|
||||
int fidx = tempNode->split->var_idx;
|
||||
fs << nfeatures;
|
||||
used[nfeatures++] = fidx;
|
||||
|
||||
fs << tempNode->split->ord.c;
|
||||
|
||||
nodes.pop();
|
||||
}
|
||||
fs << "]";
|
||||
|
||||
fs << "leafValues" << "[";
|
||||
for (int ni = 0; ni < -leafValIdx; ni++)
|
||||
fs << leafs[ni];
|
||||
fs << "]";
|
||||
|
||||
|
||||
fs << "}";
|
||||
}
|
||||
|
||||
void BoostedSoftCascadeOctave::write( cv::FileStorage &fso, const FeaturePool* pool, InputArray _thresholds) const
|
||||
{
|
||||
CV_Assert(!_thresholds.empty());
|
||||
cv::Mat used( 1, weak->total * ( (int)pow(2.f, params.max_depth) - 1), CV_32SC1);
|
||||
int* usedPtr = used.ptr<int>(0);
|
||||
int nfeatures = 0;
|
||||
cv::Mat thresholds = _thresholds.getMat();
|
||||
fso << "{"
|
||||
<< "scale" << logScale
|
||||
<< "weaks" << weak->total
|
||||
<< "trees" << "[";
|
||||
// should be replaced with the H.L. one
|
||||
CvSeqReader reader;
|
||||
cvStartReadSeq( weak, &reader);
|
||||
|
||||
for(int i = 0; i < weak->total; i++ )
|
||||
{
|
||||
CvBoostTree* tree;
|
||||
CV_READ_SEQ_ELEM( tree, reader );
|
||||
|
||||
traverse(tree, fso, nfeatures, usedPtr, thresholds.ptr<double>(0) + i);
|
||||
}
|
||||
fso << "]";
|
||||
// features
|
||||
|
||||
fso << "features" << "[";
|
||||
for (int i = 0; i < nfeatures; ++i)
|
||||
pool->write(fso, usedPtr[i]);
|
||||
fso << "]"
|
||||
<< "}";
|
||||
}
|
||||
|
||||
void BoostedSoftCascadeOctave::initialize_weights(double (&p)[2])
|
||||
{
|
||||
double n = data->sample_count;
|
||||
p[0] = n / (2. * (double)(nnegatives));
|
||||
p[1] = n / (2. * (double)(npositives));
|
||||
}
|
||||
|
||||
bool BoostedSoftCascadeOctave::train(const Dataset* dataset, const FeaturePool* pool, int weaks, int treeDepth)
|
||||
{
|
||||
CV_Assert(treeDepth == 2);
|
||||
CV_Assert(weaks > 0);
|
||||
|
||||
params.max_depth = treeDepth;
|
||||
params.weak_count = weaks;
|
||||
|
||||
// 1. fill integrals and classes
|
||||
processPositives(dataset);
|
||||
generateNegatives(dataset);
|
||||
|
||||
// 2. only simple case (all features used)
|
||||
int nfeatures = pool->size();
|
||||
cv::Mat varIdx(1, nfeatures, CV_32SC1);
|
||||
int* ptr = varIdx.ptr<int>(0);
|
||||
|
||||
for (int x = 0; x < nfeatures; ++x)
|
||||
ptr[x] = x;
|
||||
|
||||
// 3. only simple case (all samples used)
|
||||
int nsamples = npositives + nnegatives;
|
||||
cv::Mat sampleIdx(1, nsamples, CV_32SC1);
|
||||
ptr = sampleIdx.ptr<int>(0);
|
||||
|
||||
for (int x = 0; x < nsamples; ++x)
|
||||
ptr[x] = x;
|
||||
|
||||
// 4. ICF has an ordered response.
|
||||
cv::Mat varType(1, nfeatures + 1, CV_8UC1);
|
||||
uchar* uptr = varType.ptr<uchar>(0);
|
||||
for (int x = 0; x < nfeatures; ++x)
|
||||
uptr[x] = CV_VAR_ORDERED;
|
||||
uptr[nfeatures] = CV_VAR_CATEGORICAL;
|
||||
|
||||
trainData.create(nfeatures, nsamples, CV_32FC1);
|
||||
for (int fi = 0; fi < nfeatures; ++fi)
|
||||
{
|
||||
float* dptr = trainData.ptr<float>(fi);
|
||||
for (int si = 0; si < nsamples; ++si)
|
||||
{
|
||||
dptr[si] = pool->apply(fi, si, integrals);
|
||||
}
|
||||
}
|
||||
|
||||
cv::Mat missingMask;
|
||||
|
||||
bool ok = train(trainData, responses, varIdx, sampleIdx, varType, missingMask);
|
||||
if (!ok)
|
||||
CV_Error(CV_StsInternal, "ERROR: tree can not be trained");
|
||||
return ok;
|
||||
|
||||
}
|
||||
|
||||
float BoostedSoftCascadeOctave::predict( cv::InputArray _sample, cv::InputArray _votes, bool raw_mode, bool return_sum ) const
|
||||
{
|
||||
cv::Mat sample = _sample.getMat();
|
||||
CvMat csample = sample;
|
||||
if (_votes.empty())
|
||||
return CvBoost::predict(&csample, 0, 0, CV_WHOLE_SEQ, raw_mode, return_sum);
|
||||
else
|
||||
{
|
||||
cv::Mat votes = _votes.getMat();
|
||||
CvMat cvotes = votes;
|
||||
return CvBoost::predict(&csample, 0, &cvotes, CV_WHOLE_SEQ, raw_mode, return_sum);
|
||||
}
|
||||
}
|
||||
|
||||
float BoostedSoftCascadeOctave::predict( const Mat& _sample, const cv::Range range) const
|
||||
{
|
||||
CvMat sample = _sample;
|
||||
return CvBoost::predict(&sample, 0, 0, range, false, true);
|
||||
}
|
||||
|
||||
void BoostedSoftCascadeOctave::write( CvFileStorage* fs, std::string _name) const
|
||||
{
|
||||
CvBoost::write(fs, _name.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CV_INIT_ALGORITHM(BoostedSoftCascadeOctave, "SoftCascadeOctave.BoostedSoftCascadeOctave", );
|
||||
|
||||
Octave::~Octave(){}
|
||||
|
||||
cv::Ptr<Octave> Octave::create(cv::Rect boundingBox, int npositives, int nnegatives,
|
||||
int logScale, int shrinkage, int poolSize)
|
||||
{
|
||||
cv::Ptr<Octave> octave(
|
||||
new BoostedSoftCascadeOctave(boundingBox, npositives, nnegatives, logScale, shrinkage, poolSize));
|
||||
return octave;
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2012, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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,
|
||||
@ -22,7 +22,7 @@
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
// and / or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
@ -42,11 +42,17 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
using cv::softcascade::Detection;
|
||||
using cv::softcascade::Detector;
|
||||
using cv::softcascade::ChannelFeatureBuilder;
|
||||
|
||||
using namespace cv;
|
||||
|
||||
namespace {
|
||||
|
||||
struct Octave
|
||||
struct SOctave
|
||||
{
|
||||
Octave(const int i, const cv::Size& origObjSize, const cv::FileNode& fn)
|
||||
SOctave(const int i, const cv::Size& origObjSize, const cv::FileNode& fn)
|
||||
: index(i), weaks((int)fn[SC_OCT_WEAKS]), scale(pow(2,(float)fn[SC_OCT_SCALE])),
|
||||
size(cvRound(origObjSize.width * scale), cvRound(origObjSize.height * scale)) {}
|
||||
|
||||
@ -115,16 +121,16 @@ struct Feature
|
||||
static const char *const SC_F_RECT;
|
||||
};
|
||||
|
||||
const char *const Octave::SC_OCT_SCALE = "scale";
|
||||
const char *const Octave::SC_OCT_WEAKS = "weaks";
|
||||
const char *const Octave::SC_OCT_SHRINKAGE = "shrinkingFactor";
|
||||
const char *const SOctave::SC_OCT_SCALE = "scale";
|
||||
const char *const SOctave::SC_OCT_WEAKS = "weaks";
|
||||
const char *const SOctave::SC_OCT_SHRINKAGE = "shrinkingFactor";
|
||||
const char *const Weak::SC_WEAK_THRESHOLD = "treeThreshold";
|
||||
const char *const Feature::SC_F_CHANNEL = "channel";
|
||||
const char *const Feature::SC_F_RECT = "rect";
|
||||
|
||||
struct Level
|
||||
{
|
||||
const Octave* octave;
|
||||
const SOctave* octave;
|
||||
|
||||
float origScale;
|
||||
float relScale;
|
||||
@ -134,9 +140,8 @@ struct Level
|
||||
cv::Size objSize;
|
||||
|
||||
float scaling[2]; // 0-th for channels <= 6, 1-st otherwise
|
||||
typedef cv::SCascade::Detection Detection;
|
||||
|
||||
Level(const Octave& oct, const float scale, const int shrinkage, const int w, const int h)
|
||||
Level(const SOctave& oct, const float scale, const int shrinkage, const int w, const int h)
|
||||
: octave(&oct), origScale(scale), relScale(scale / oct.scale),
|
||||
workRect(cv::Size(cvRound(w / (float)shrinkage),cvRound(h / (float)shrinkage))),
|
||||
objSize(cv::Size(cvRound(oct.size.width * relScale), cvRound(oct.size.height * relScale)))
|
||||
@ -170,37 +175,30 @@ struct Level
|
||||
return (sarea == 0.0f)? threshold : (threshold * scaling[idx] * sarea);
|
||||
}
|
||||
};
|
||||
|
||||
struct ChannelStorage
|
||||
{
|
||||
std::vector<cv::Mat> hog;
|
||||
cv::Mat hog;
|
||||
int shrinkage;
|
||||
int offset;
|
||||
int step;
|
||||
int model_height;
|
||||
|
||||
cv::Ptr<ChannelFeatureBuilder> builder;
|
||||
|
||||
enum {HOG_BINS = 6, HOG_LUV_BINS = 10};
|
||||
|
||||
ChannelStorage(const cv::Mat& colored, int shr) : shrinkage(shr)
|
||||
{
|
||||
hog.clear();
|
||||
hog.reserve(10);
|
||||
cv::SCascade::Channels ints(shr);
|
||||
builder = ChannelFeatureBuilder::create();
|
||||
(*builder)(colored, hog);
|
||||
|
||||
// convert to grey
|
||||
cv::Mat grey;
|
||||
cv::cvtColor(colored, grey, CV_BGR2GRAY);
|
||||
|
||||
ints.appendHogBins(grey, hog, 6);
|
||||
ints.appendLuvBins(colored, hog);
|
||||
|
||||
step = hog[0].cols;
|
||||
step = hog.step1();
|
||||
model_height = colored.rows / shrinkage;
|
||||
}
|
||||
|
||||
float get(const int channel, const cv::Rect& area) const
|
||||
{
|
||||
// CV_Assert(channel < HOG_LUV_BINS);
|
||||
const cv::Mat& m = hog[channel];
|
||||
int *ptr = ((int*)(m.data)) + offset;
|
||||
const int *ptr = hog.ptr<const int>(0) + model_height * channel * step + offset;
|
||||
|
||||
int a = ptr[area.y * step + area.x];
|
||||
int b = ptr[area.y * step + area.width];
|
||||
@ -213,7 +211,8 @@ struct ChannelStorage
|
||||
|
||||
}
|
||||
|
||||
struct cv::SCascade::Fields
|
||||
|
||||
struct Detector::Fields
|
||||
{
|
||||
float minScale;
|
||||
float maxScale;
|
||||
@ -224,7 +223,7 @@ struct cv::SCascade::Fields
|
||||
|
||||
int shrinkage;
|
||||
|
||||
std::vector<Octave> octaves;
|
||||
std::vector<SOctave> octaves;
|
||||
std::vector<Weak> weaks;
|
||||
std::vector<Node> nodes;
|
||||
std::vector<float> leaves;
|
||||
@ -234,14 +233,14 @@ struct cv::SCascade::Fields
|
||||
|
||||
cv::Size frameSize;
|
||||
|
||||
typedef std::vector<Octave>::iterator octIt_t;
|
||||
typedef std::vector<SOctave>::iterator octIt_t;
|
||||
typedef std::vector<Detection> dvector;
|
||||
|
||||
void detectAt(const int dx, const int dy, const Level& level, const ChannelStorage& storage, dvector& detections) const
|
||||
{
|
||||
float detectionScore = 0.f;
|
||||
|
||||
const Octave& octave = *(level.octave);
|
||||
const SOctave& octave = *(level.octave);
|
||||
|
||||
int stBegin = octave.index * octave.weaks, stEnd = stBegin + octave.weaks;
|
||||
|
||||
@ -287,7 +286,7 @@ struct cv::SCascade::Fields
|
||||
octIt_t res = octaves.begin();
|
||||
for (octIt_t oct = octaves.begin(); oct < octaves.end(); ++oct)
|
||||
{
|
||||
const Octave& octave =*oct;
|
||||
const SOctave& octave =*oct;
|
||||
float logOctave = log(octave.scale);
|
||||
float logAbsScale = fabs(logFactor - logOctave);
|
||||
|
||||
@ -381,7 +380,7 @@ struct cv::SCascade::Fields
|
||||
for (int octIndex = 0; it != it_end; ++it, ++octIndex)
|
||||
{
|
||||
FileNode fns = *it;
|
||||
Octave octave(octIndex, cv::Size(origObjWidth, origObjHeight), fns);
|
||||
SOctave octave(octIndex, cv::Size(origObjWidth, origObjHeight), fns);
|
||||
CV_Assert(octave.weaks > 0);
|
||||
octaves.push_back(octave);
|
||||
|
||||
@ -417,17 +416,17 @@ struct cv::SCascade::Fields
|
||||
}
|
||||
};
|
||||
|
||||
cv::SCascade::SCascade(const double mins, const double maxs, const int nsc, const int rej)
|
||||
Detector::Detector(const double mins, const double maxs, const int nsc, const int rej)
|
||||
: fields(0), minScale(mins), maxScale(maxs), scales(nsc), rejCriteria(rej) {}
|
||||
|
||||
cv::SCascade::~SCascade() { delete fields;}
|
||||
Detector::~Detector() { delete fields;}
|
||||
|
||||
void cv::SCascade::read(const FileNode& fn)
|
||||
void Detector::read(const cv::FileNode& fn)
|
||||
{
|
||||
Algorithm::read(fn);
|
||||
}
|
||||
|
||||
bool cv::SCascade::load(const FileNode& fn)
|
||||
bool Detector::load(const cv::FileNode& fn)
|
||||
{
|
||||
if (fields) delete fields;
|
||||
|
||||
@ -436,7 +435,8 @@ bool cv::SCascade::load(const FileNode& fn)
|
||||
}
|
||||
|
||||
namespace {
|
||||
typedef cv::SCascade::Detection Detection;
|
||||
|
||||
using cv::softcascade::Detection;
|
||||
typedef std::vector<Detection> dvector;
|
||||
|
||||
|
||||
@ -480,13 +480,13 @@ void DollarNMS(dvector& objects)
|
||||
|
||||
static void suppress(int type, std::vector<Detection>& objects)
|
||||
{
|
||||
CV_Assert(type == cv::SCascade::DOLLAR);
|
||||
CV_Assert(type == Detector::DOLLAR);
|
||||
DollarNMS(objects);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cv::SCascade::detectNoRoi(const cv::Mat& image, std::vector<Detection>& objects) const
|
||||
void Detector::detectNoRoi(const cv::Mat& image, std::vector<Detection>& objects) const
|
||||
{
|
||||
Fields& fld = *fields;
|
||||
// create integrals
|
||||
@ -513,9 +513,9 @@ void cv::SCascade::detectNoRoi(const cv::Mat& image, std::vector<Detection>& obj
|
||||
if (rejCriteria != NO_REJECT) suppress(rejCriteria, objects);
|
||||
}
|
||||
|
||||
void cv::SCascade::detect(cv::InputArray _image, cv::InputArray _rois, std::vector<Detection>& objects) const
|
||||
void Detector::detect(cv::InputArray _image, cv::InputArray _rois, std::vector<Detection>& objects) const
|
||||
{
|
||||
// only color images are supperted
|
||||
// only color images are suppered
|
||||
cv::Mat image = _image.getMat();
|
||||
CV_Assert(image.type() == CV_8UC3);
|
||||
|
||||
@ -565,7 +565,7 @@ void cv::SCascade::detect(cv::InputArray _image, cv::InputArray _rois, std::vect
|
||||
if (rejCriteria != NO_REJECT) suppress(rejCriteria, objects);
|
||||
}
|
||||
|
||||
void cv::SCascade::detect(InputArray _image, InputArray _rois, OutputArray _rects, OutputArray _confs) const
|
||||
void Detector::detect(InputArray _image, InputArray _rois, OutputArray _rects, OutputArray _confs) const
|
||||
{
|
||||
std::vector<Detection> objects;
|
||||
detect( _image, _rois, objects);
|
@ -11,7 +11,7 @@
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2012, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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,
|
||||
@ -22,7 +22,7 @@
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
// and / or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
@ -42,19 +42,20 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv
|
||||
namespace cv { namespace softcascade
|
||||
{
|
||||
|
||||
CV_INIT_ALGORITHM(SCascade, "CascadeDetector.SCascade",
|
||||
CV_INIT_ALGORITHM(Detector, "SoftCascade.Detector",
|
||||
obj.info()->addParam(obj, "minScale", obj.minScale);
|
||||
obj.info()->addParam(obj, "maxScale", obj.maxScale);
|
||||
obj.info()->addParam(obj, "scales", obj.scales);
|
||||
obj.info()->addParam(obj, "rejCriteria", obj.rejCriteria));
|
||||
|
||||
bool initModule_objdetect(void)
|
||||
|
||||
bool initModule_softcascade(void)
|
||||
{
|
||||
Ptr<Algorithm> sc = createSCascade();
|
||||
return sc->info() != 0;
|
||||
Ptr<Algorithm> sc1 = createDetector();
|
||||
return (sc1->info() != 0);
|
||||
}
|
||||
|
||||
}
|
||||
} }
|
62
modules/softcascade/test/test_channel_features.cpp
Normal file
62
modules/softcascade/test/test_channel_features.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
using namespace cv::softcascade;
|
||||
|
||||
TEST(ChannelFeatureBuilderTest, info)
|
||||
{
|
||||
cv::Ptr<ChannelFeatureBuilder> builder = ChannelFeatureBuilder::create();
|
||||
ASSERT_TRUE(builder->info() != 0);
|
||||
}
|
||||
|
||||
TEST(ChannelFeatureBuilderTest, compute)
|
||||
{
|
||||
cv::Ptr<ChannelFeatureBuilder> builder = ChannelFeatureBuilder::create();
|
||||
|
||||
cv::Mat colored = cv::imread(cvtest::TS::ptr()->get_data_path() + "cascadeandhog/images/image_00000000_0.png");
|
||||
cv::Mat ints;
|
||||
(*builder)(colored, ints);
|
||||
|
||||
ASSERT_FALSE(ints.empty());
|
||||
}
|
45
modules/softcascade/test/test_main.cpp
Normal file
45
modules/softcascade/test/test_main.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
CV_TEST_MAIN("cv")
|
43
modules/softcascade/test/test_precomp.cpp
Normal file
43
modules/softcascade/test/test_precomp.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
59
modules/softcascade/test/test_precomp.hpp
Normal file
59
modules/softcascade/test/test_precomp.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wmissing-declarations"
|
||||
# if defined __clang__ || defined __APPLE__
|
||||
# pragma GCC diagnostic ignored "-Wmissing-prototypes"
|
||||
# pragma GCC diagnostic ignored "-Wextra"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
# include "opencv2/ts/ts.hpp"
|
||||
# include "opencv2/softcascade/softcascade.hpp"
|
||||
# include "opencv2/imgproc/imgproc.hpp"
|
||||
# include "opencv2/highgui/highgui.hpp"
|
||||
|
||||
#endif
|
@ -11,7 +11,7 @@
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2012, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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,
|
||||
@ -22,7 +22,7 @@
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
// and / or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
@ -45,20 +45,21 @@
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
TEST(SCascade, readCascade)
|
||||
using namespace cv::softcascade;
|
||||
|
||||
TEST(SoftCascadeDetector, readCascade)
|
||||
{
|
||||
std::string xml = cvtest::TS::ptr()->get_data_path() + "cascadeandhog/cascades/inria_caltech-17.01.2013.xml";
|
||||
cv::SCascade cascade;
|
||||
Detector cascade;
|
||||
cv::FileStorage fs(xml, cv::FileStorage::READ);
|
||||
ASSERT_TRUE(fs.isOpened());
|
||||
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
|
||||
}
|
||||
|
||||
TEST(SCascade, detect)
|
||||
TEST(SoftCascadeDetector, detect)
|
||||
{
|
||||
typedef cv::SCascade::Detection Detection;
|
||||
std::string xml = cvtest::TS::ptr()->get_data_path()+ "cascadeandhog/cascades/inria_caltech-17.01.2013.xml";
|
||||
cv::SCascade cascade;
|
||||
Detector cascade;
|
||||
cv::FileStorage fs(xml, cv::FileStorage::READ);
|
||||
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
|
||||
|
||||
@ -71,11 +72,10 @@ TEST(SCascade, detect)
|
||||
ASSERT_EQ(719, (int)objects.size());
|
||||
}
|
||||
|
||||
TEST(SCascade, detectSeparate)
|
||||
TEST(SoftCascadeDetector, detectSeparate)
|
||||
{
|
||||
typedef cv::SCascade::Detection Detection;
|
||||
std::string xml = cvtest::TS::ptr()->get_data_path() + "cascadeandhog/cascades/inria_caltech-17.01.2013.xml";
|
||||
cv::SCascade cascade;
|
||||
Detector cascade;
|
||||
cv::FileStorage fs(xml, cv::FileStorage::READ);
|
||||
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
|
||||
|
||||
@ -88,11 +88,10 @@ TEST(SCascade, detectSeparate)
|
||||
ASSERT_EQ(719, confs.cols);
|
||||
}
|
||||
|
||||
TEST(SCascade, detectRoi)
|
||||
TEST(SoftCascadeDetector, detectRoi)
|
||||
{
|
||||
typedef cv::SCascade::Detection Detection;
|
||||
std::string xml = cvtest::TS::ptr()->get_data_path() + "cascadeandhog/cascades/inria_caltech-17.01.2013.xml";
|
||||
cv::SCascade cascade;
|
||||
Detector cascade;
|
||||
cv::FileStorage fs(xml, cv::FileStorage::READ);
|
||||
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
|
||||
|
||||
@ -107,11 +106,10 @@ TEST(SCascade, detectRoi)
|
||||
ASSERT_EQ(719, (int)objects.size());
|
||||
}
|
||||
|
||||
TEST(SCascade, detectNoRoi)
|
||||
TEST(SoftCascadeDetector, detectNoRoi)
|
||||
{
|
||||
typedef cv::SCascade::Detection Detection;
|
||||
std::string xml = cvtest::TS::ptr()->get_data_path() + "cascadeandhog/cascades/inria_caltech-17.01.2013.xml";
|
||||
cv::SCascade cascade;
|
||||
Detector cascade;
|
||||
cv::FileStorage fs(xml, cv::FileStorage::READ);
|
||||
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
|
||||
|
||||
@ -126,11 +124,10 @@ TEST(SCascade, detectNoRoi)
|
||||
ASSERT_EQ(719, (int)objects.size());
|
||||
}
|
||||
|
||||
TEST(SCascade, detectEmptyRoi)
|
||||
TEST(SoftCascadeDetector, detectEmptyRoi)
|
||||
{
|
||||
typedef cv::SCascade::Detection Detection;
|
||||
std::string xml = cvtest::TS::ptr()->get_data_path() + "cascadeandhog/cascades/inria_caltech-17.01.2013.xml";
|
||||
cv::SCascade cascade;
|
||||
Detector cascade;
|
||||
cv::FileStorage fs(xml, cv::FileStorage::READ);
|
||||
ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode()));
|
||||
|
247
modules/softcascade/test/test_training.cpp
Normal file
247
modules/softcascade/test/test_training.cpp
Normal file
@ -0,0 +1,247 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 the Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#if !defined(ANDROID)
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#if !defined (_WIN32) && ! defined(__MINGW32__)
|
||||
# include <glob.h>
|
||||
#else
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace cv::softcascade;
|
||||
|
||||
typedef vector<string> svector;
|
||||
class ScaledDataset : public Dataset
|
||||
{
|
||||
public:
|
||||
ScaledDataset(const string& path, const int octave);
|
||||
|
||||
virtual cv::Mat get(SampleType type, int idx) const;
|
||||
virtual int available(SampleType type) const;
|
||||
virtual ~ScaledDataset();
|
||||
|
||||
private:
|
||||
svector pos;
|
||||
svector neg;
|
||||
};
|
||||
|
||||
string itoa(long i)
|
||||
{
|
||||
char s[65];
|
||||
sprintf(s, "%ld", i);
|
||||
return std::string(s);
|
||||
}
|
||||
|
||||
|
||||
#if !defined (_WIN32) && ! defined(__MINGW32__)
|
||||
|
||||
void glob(const string& path, svector& ret)
|
||||
{
|
||||
glob_t glob_result;
|
||||
glob(path.c_str(), GLOB_TILDE, 0, &glob_result);
|
||||
|
||||
ret.clear();
|
||||
ret.reserve(glob_result.gl_pathc);
|
||||
|
||||
for(unsigned int i = 0; i < glob_result.gl_pathc; ++i)
|
||||
{
|
||||
ret.push_back(std::string(glob_result.gl_pathv[i]));
|
||||
}
|
||||
|
||||
globfree(&glob_result);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void glob(const string& refRoot, const string& refExt, svector &refvecFiles)
|
||||
{
|
||||
std::string strFilePath; // File path
|
||||
std::string strExtension; // Extension
|
||||
|
||||
std::string strPattern = refRoot + "\\*.*";
|
||||
|
||||
WIN32_FIND_DATA FileInformation; // File information
|
||||
HANDLE hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);
|
||||
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
CV_Error(CV_StsBadArg, "Your dataset search path is incorrect");
|
||||
|
||||
do
|
||||
{
|
||||
if(FileInformation.cFileName[0] != '.')
|
||||
{
|
||||
strFilePath.erase();
|
||||
strFilePath = refRoot + "\\" + FileInformation.cFileName;
|
||||
|
||||
if( !(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
||||
{
|
||||
// Check extension
|
||||
strExtension = FileInformation.cFileName;
|
||||
strExtension = strExtension.substr(strExtension.rfind(".") + 1);
|
||||
|
||||
if(strExtension == refExt)
|
||||
// Save filename
|
||||
refvecFiles.push_back(strFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
while(::FindNextFile(hFile, &FileInformation) == TRUE);
|
||||
|
||||
// Close handle
|
||||
::FindClose(hFile);
|
||||
|
||||
DWORD dwError = ::GetLastError();
|
||||
if(dwError != ERROR_NO_MORE_FILES)
|
||||
CV_Error(CV_StsBadArg, "Your dataset search path is incorrect");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ScaledDataset::ScaledDataset(const string& path, const int oct)
|
||||
{
|
||||
|
||||
#if !defined (_WIN32) && ! defined(__MINGW32__)
|
||||
glob(path + "/pos/octave_" + itoa(oct) + "/*.png", pos);
|
||||
#else
|
||||
glob(path + "/pos/octave_" + itoa(oct), "png", pos);
|
||||
#endif
|
||||
|
||||
#if !defined (_WIN32) && ! defined(__MINGW32__)
|
||||
glob(path + "/neg/octave_" + itoa(oct) + "/*.png", neg);
|
||||
#else
|
||||
glob(path + "/neg/octave_" + itoa(oct), "png", neg);
|
||||
#endif
|
||||
|
||||
// Check: files not empty
|
||||
CV_Assert(pos.size() != size_t(0));
|
||||
CV_Assert(neg.size() != size_t(0));
|
||||
}
|
||||
|
||||
cv::Mat ScaledDataset::get(SampleType type, int idx) const
|
||||
{
|
||||
const std::string& src = (type == POSITIVE)? pos[idx]: neg[idx];
|
||||
return cv::imread(src);
|
||||
}
|
||||
|
||||
int ScaledDataset::available(SampleType type) const
|
||||
{
|
||||
return (int)((type == POSITIVE)? pos.size():neg.size());
|
||||
}
|
||||
|
||||
ScaledDataset::~ScaledDataset(){}
|
||||
|
||||
}
|
||||
|
||||
TEST(DISABLED_SoftCascade, training)
|
||||
{
|
||||
// // 2. check and open output file
|
||||
string outXmlPath = cv::tempfile(".xml");
|
||||
cv::FileStorage fso(outXmlPath, cv::FileStorage::WRITE);
|
||||
|
||||
ASSERT_TRUE(fso.isOpened());
|
||||
|
||||
std::vector<int> octaves;
|
||||
{
|
||||
octaves.push_back(-1);
|
||||
octaves.push_back(0);
|
||||
}
|
||||
|
||||
fso << "regression-cascade"
|
||||
<< "{"
|
||||
<< "stageType" << "BOOST"
|
||||
<< "featureType" << "ICF"
|
||||
<< "octavesNum" << 2
|
||||
<< "width" << 64
|
||||
<< "height" << 128
|
||||
<< "shrinkage" << 4
|
||||
<< "octaves" << "[";
|
||||
|
||||
for (std::vector<int>::const_iterator it = octaves.begin(); it != octaves.end(); ++it)
|
||||
{
|
||||
int nfeatures = 100;
|
||||
int shrinkage = 4;
|
||||
float octave = powf(2.f, (float)(*it));
|
||||
cv::Size model = cv::Size( cvRound(64 * octave) / shrinkage, cvRound(128 * octave) / shrinkage );
|
||||
|
||||
cv::Ptr<FeaturePool> pool = FeaturePool::create(model, nfeatures);
|
||||
nfeatures = pool->size();
|
||||
int npositives = 20;
|
||||
int nnegatives = 40;
|
||||
|
||||
cv::Rect boundingBox = cv::Rect( cvRound(20 * octave), cvRound(20 * octave),
|
||||
cvRound(64 * octave), cvRound(128 * octave));
|
||||
|
||||
cv::Ptr<Octave> boost = Octave::create(boundingBox, npositives, nnegatives, *it, shrinkage, nfeatures);
|
||||
|
||||
std::string path = cvtest::TS::ptr()->get_data_path() + "softcascade/sample_training_set";
|
||||
ScaledDataset dataset(path, *it);
|
||||
|
||||
if (boost->train(&dataset, pool, 3, 2))
|
||||
{
|
||||
cv::Mat thresholds;
|
||||
boost->setRejectThresholds(thresholds);
|
||||
boost->write(fso, pool, thresholds);
|
||||
}
|
||||
}
|
||||
|
||||
fso << "]" << "}";
|
||||
fso.release();
|
||||
|
||||
|
||||
cv::FileStorage actual(outXmlPath, cv::FileStorage::READ);
|
||||
cv::FileNode root = actual.getFirstTopLevelNode();
|
||||
|
||||
cv::FileNode fn = root["octaves"];
|
||||
ASSERT_FALSE(fn.empty());
|
||||
}
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user