OZ++ Sample: HOGPeopleDetector |
/******************************************************************************
*
* Copyright (c) 2017 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer.
*
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
*
* HOGPeopleDetector.cpp
*
*****************************************************************************/
//
//2018/04/10
//On cv::HOGDescriptor Struct, see: https://docs.opencv.org/3.4.1/d5/d33/structcv_1_1HOGDescriptor.html
/*
//Constructor
cv::HOGDescriptor::HOGDescriptor ( Size _winSize, //Detection window size. Align to block size and block stride. Default value is Size(64,128).
Size _blockSize, //Block size in pixels. Align to cell size. Default value is Size(16,16).
Size _blockStride, //Block stride. It must be a multiple of cell size. Default value is Size(8,8).
Size _cellSize, //Cell size. Default value is Size(8,8).
int _nbins, //Number of bins used in the calculation of histogram of gradients. Default value is 9.
int _derivAperture = 1, //not documented ?
double _winSigma = -1,
int _histogramNormType = HOGDescriptor::L2Hys, //histogramNormType
double _L2HysThreshold = 0.2, //L2-Hys normalization method shrinkage.
bool _gammaCorrection = false, //Flag to specify whether the gamma correction preprocessing is required or not.
int _nlevels = HOGDescriptor::DEFAULT_NLEVELS, //Maximum number of detection window increases. Default value is 64.
bool _signedGradient = false //Indicates signed gradient will be used or not.
)
//////////////////////////////////////////////////////
Please note the following attributes.
Public Attributes
Size blockSize
Block size in pixels. Align to cell size. Default value is Size(16,16). More...
Size blockStride
Block stride. It must be a multiple of cell size. Default value is Size(8,8). More...
Size cellSize
Cell size. Default value is Size(8,8). More...
int derivAperture
not documented More...
float free_coef
not documented More...
bool gammaCorrection
Flag to specify whether the gamma correction preprocessing is required or not. More...
int histogramNormType
histogramNormType More...
double L2HysThreshold
L2-Hys normalization method shrinkage. More...
int nbins
Number of bins used in the calculation of histogram of gradients. Default value is 9. More...
int nlevels
Maximum number of detection window increases. Default value is 64. More...
UMat oclSvmDetector
coefficients for the linear SVM classifier used when OpenCL is enabled More...
bool signedGradient
Indicates signed gradient will be used or not. More...
std::vector< float > svmDetector
coefficients for the linear SVM classifier. More...
double winSigma
Gaussian smoothing window parameter. More...
Size winSize
Detection window size. Align to block size and block stri
*/
/*
train_HOG.cpp
See also: https://docs.opencv.org/3.4.1/d5/d77/train_HOG_8cpp-example.html#a34
*/
#include <es++/Pair.h>
#include <es++/gtkmm-3.0/Application.h>
#include <es++/gtkmm-3.0/Label.h>
#include <es++/gtkmm-3.0/LabeledTrackBar.h>
#include <es++/gtkmm-3.0/FileOpenDialog.h>
#include <es++/opencv-3.0/OpenCVMainView.h>
#include <es++/opencv-3.0/OpenCVScrolledImageView.h>
#include <es++/opencv-3.0/OpenCVScaleComboBox.h>
using namespace Gtk;
namespace Es {
class MainView :public Es::OpenCVMainView {
private:
typedef enum {
DEFAULT = 0,
DAIMLER = 1,
USER_DEFINED = 2
} HOG_TYPE;
private:
///////////////////////////////////////////////////////
//Inner classes start.
class OriginalImageView :public Es::OpenCVScrolledImageView {
public:
OriginalImageView()
{
}
void rescale(int scaling_ratio)
{
OpenCVScrolledImageView::scaleImage(scaling_ratio);
}
};
class DetectedImageView :public Es::OpenCVScrolledImageView {
private:
cv::Mat gray_image;
cv::Mat detected_image;
public:
DetectedImageView()
{
}
void loadImage(const std::string& filename,
int imageLoadingFlag= CV_LOAD_IMAGE_COLOR,
int scaling_ratio=100)
{
OpenCVScrolledImageView::loadImage(filename, imageLoadingFlag,
scaling_ratio);
cv::Mat& original_image = getOriginalImage();
//1 Convert it to a gray image.
cv::cvtColor(original_image, gray_image, COLOR_BGR2GRAY );
//2 Apply equalizeHist to the gray image.
cv::equalizeHist(gray_image, gray_image);
detected_image = original_image.clone();
scaleImage(detected_image, scaling_ratio);
}
void clear(int scalingRatio)
{
cv::Mat& original_image = getOriginalImage();
cv::Mat image = original_image.clone();
detected_image = image;
scaleImage(detected_image, scalingRatio);
refresh();
}
void detect(HOG_TYPE descriptor,int scaling_ratio)
{
cv::Mat& original_image = getOriginalImage();
detected_image = original_image.clone();
//Please refer the method size_t HOGDescriptor::getDescriptorSize() const in opencv-3.4.1/module/objdetect/src/hog.cpp
//Note the following restrictions on blockSize, winSize, blockStride and cellSize:
// (blockSize.width % cellSize.width == 0 &&
// blockSize.height % cellSize.height == 0);
//((winSize.width - blockSize.width) % blockStride.width == 0 &&
// (winSize.height - blockSize.height) % blockStride.height == 0)
cv::HOGDescriptor hog ;
switch(descriptor) {
case DEFAULT:
hog.winSize = cv::Size(64,128);
hog.blockSize = cv::Size(16, 16);
hog.blockStride = cv::Size( 8, 8);
hog.cellSize = cv::Size( 8, 8);
hog.nbins = 9;
hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector());
break;
case DAIMLER:
hog.winSize = cv::Size(48, 96);
hog.blockSize = cv::Size(16, 16);
hog.blockStride = cv::Size( 8, 8);
hog.cellSize = cv::Size( 8, 8);
hog.nbins = 9;
hog.setSVMDetector(cv::HOGDescriptor::getDaimlerPeopleDetector());
break;
case USER_DEFINED:
hog.winSize = cv::Size(32,64);
hog.blockSize = cv::Size( 8, 8);
hog.blockStride = cv::Size( 4, 4);
hog.cellSize = cv::Size( 4, 4);
hog.nbins = 9;
hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector());
break;
}
std::vector<cv::Rect> people;
hog.detectMultiScale(gray_image, people);
for (std::vector<cv::Rect>::const_iterator it = people.begin();
it != people.end(); ++it) {
cv::Rect r = *it;
cv::rectangle(detected_image, r.tl(), r.br(), CV_RGB(255, 0, 0), 3);
}
scaleImage(detected_image, scaling_ratio);
}
void rescale(int scaling_ratio)
{
OpenCVScrolledImageView::scaleImage(detected_image, scaling_ratio);
}
};
// Inner classes end.
///////////////////////////////////////////////////////
Es::Label filepath;
Es::HorizontalLayout horiz_layout;
Es::VerticalLayout control_pane;
OriginalImageView original_image;
DetectedImageView detected_image;
int loading_flag;
Es::OpenCVScaleComboBox scale_combobox;
int blockSize;
Es::LabeledTrackBar blockSize_trackbar;
int ksize;
Es::LabeledTrackBar ksize_trackbar;
HOG_TYPE descriptor_index;
Es::LabeledComboBox descriptor_combobox;
int scaling_ratio; //Percentage.
static const int CONTROLPANE_WIDTH = 200;
std::string filename;
Es::FileOpenDialog file_dialog;
public:
//////////////////////////////////////////////
//Constructor
//
MainView(Es::Application& applet,
std::string& name,
Es::Args& args)
:OpenCVMainView(applet, name, args)
,scaling_ratio(100) //100%
,file_dialog(*this, Es::FileOpenDialog::IMAGE_FILES)
{
int w = (int)args.get(XmNwidth);
int h = (int)args.get(XmNheight);
int ratio = (int)args.get(XmNscalingRatio);
scaling_ratio = OpenCVImageView::validateScale(ratio);
Es::MainLayout& main_layout = get_main_layout();
main_layout.pack_start(filepath, FALSE, FALSE, 0);
main_layout.pack_start(horiz_layout);
filename = "../../images/Pedestrian.png";
filepath.set_label(filename);
int ww = (w - CONTROLPANE_WIDTH)/2;
filepath.set_size_request(w, 30);
original_image.set_size_request(ww, h);
detected_image.set_size_request(ww, h);
control_pane.set_size_request( CONTROLPANE_WIDTH, h);
horiz_layout.pack_start(original_image);
horiz_layout.pack_start(detected_image);
horiz_layout.pack_start(control_pane, FALSE, FALSE, 0);
scale_combobox.set_selection(scaling_ratio);
scale_combobox.set_changed_callback(
sigc::mem_fun(*this, &MainView::scale_changed) );
descriptor_index = DEFAULT;
const char* types[] = {
"DEFAULT",
"DAIMLER",
"USER_DEFINED",
};
descriptor_combobox.append_items(types, CountOf(types));
descriptor_combobox.set_label("Descriptor");
descriptor_combobox.set_active_text(types[0]);
descriptor_combobox.set_changed_callback(
sigc::mem_fun(*this, &MainView::descriptor_changed) );
control_pane.set_spacing(20);
control_pane.pack_start(scale_combobox, Gtk::PACK_SHRINK);
control_pane.pack_start(descriptor_combobox, Gtk::PACK_SHRINK);
loading_flag = IMREAD_COLOR;
original_image.loadImage(filename, loading_flag, scaling_ratio);
detected_image.loadImage(filename, loading_flag, scaling_ratio);
detected_image.detect(DEFAULT,
scaling_ratio);
show_all();
}
void scale_changed()
{
std::string scale = scale_combobox.get_active_text();
printf("scale_changed %s\n", scale.c_str());
scaling_ratio = scale_combobox.get_selection();
original_image.rescale(scaling_ratio);
detected_image.rescale(scaling_ratio);
}
void descriptor_changed()
{
const Pair<const char*, HOG_TYPE> types[] = {
{"DEFAULT", DEFAULT},
{"DAIMLER", DAIMLER},
{"USER_DEFINED", USER_DEFINED},
};
std::string type = descriptor_combobox.get_active_text();
for (int i = 0; i<CountOf(types); i++) {
if (strcmp(type.c_str(), types[i].first) == 0) {
descriptor_index = types[i].second;
break;
}
}
detected_image.detect(descriptor_index,
scaling_ratio);
}
void file_open()
{
int rc = file_dialog.popup();
if (rc == Gtk::RESPONSE_OK) {
const std::string filename = file_dialog.get_filename();
filepath.set_label(filename);
original_image.loadImage(filename, loading_flag, scaling_ratio);
detected_image.loadImage(filename, loading_flag, scaling_ratio);
detected_image.detect(DEFAULT,
scaling_ratio);
}
}
};
}
int main(int argc, char** argv)
{
Es::Environment env;
try {
std::string name = argv[0];
Es::Application applet(argc, argv);
Es::Args args;
args.set(XmNx, 20);
args.set(XmNy, 40);
args.set(XmNwidth, 900);
args.set(XmNheight, 400);
args.set(XmNscalingRatio, 60); //60%
Es::MainView mainv(applet, name, args);
mainv.show();
applet.run(mainv);
} catch (Es::Exception& ex) {
caught(ex);
} catch (...) {
printf("Get exception \n");
}
return 0;
}