// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_OBJECT_DeTECTOR_H__
#define DLIB_OBJECT_DeTECTOR_H__
#include "object_detector_abstract.h"
#include "../geometry.h"
#include <vector>
#include "box_overlap_testing.h"
#include "full_object_detection.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename image_scanner_type
>
class object_detector
{
public:
typedef typename image_scanner_type::feature_vector_type feature_vector_type;
object_detector (
);
object_detector (
const object_detector& item
);
object_detector (
const image_scanner_type& scanner_,
const test_box_overlap& overlap_tester_,
const feature_vector_type& w_
);
const feature_vector_type& get_w (
) const { return w; }
const test_box_overlap& get_overlap_tester (
) const;
const image_scanner_type& get_scanner (
) const;
object_detector& operator= (
const object_detector& item
);
template <
typename image_type
>
std::vector<rectangle> operator() (
const image_type& img,
double adjust_threshold = 0
);
template <
typename image_type
>
void operator() (
const image_type& img,
std::vector<std::pair<double, rectangle> >& final_dets,
double adjust_threshold = 0
);
template <
typename image_type
>
void operator() (
const image_type& img,
std::vector<std::pair<double, full_object_detection> >& final_dets,
double adjust_threshold = 0
);
template <
typename image_type
>
void operator() (
const image_type& img,
std::vector<full_object_detection>& final_dets,
double adjust_threshold = 0
);
template <typename T>
friend void serialize (
const object_detector<T>& item,
std::ostream& out
);
template <typename T>
friend void deserialize (
object_detector<T>& item,
std::istream& in
);
private:
bool overlaps_any_box (
const std::vector<rectangle>& rects,
const dlib::rectangle& rect
) const
{
for (unsigned long i = 0; i < rects.size(); ++i)
{
if (boxes_overlap(rects[i], rect))
return true;
}
return false;
}
bool overlaps_any_box (
const std::vector<std::pair<double,rectangle> >& rects,
const dlib::rectangle& rect
) const
{
for (unsigned long i = 0; i < rects.size(); ++i)
{
if (boxes_overlap(rects[i].second, rect))
return true;
}
return false;
}
test_box_overlap boxes_overlap;
feature_vector_type w;
image_scanner_type scanner;
};
// ----------------------------------------------------------------------------------------
template <typename T>
void serialize (
const object_detector<T>& item,
std::ostream& out
)
{
int version = 1;
serialize(version, out);
T scanner;
scanner.copy_configuration(item.scanner);
serialize(scanner, out);
serialize(item.w, out);
serialize(item.boxes_overlap, out);
}
// ----------------------------------------------------------------------------------------
template <typename T>
void deserialize (
object_detector<T>& item,
std::istream& in
)
{
int version = 0;
deserialize(version, in);
if (version != 1)
throw serialization_error("Unexpected version encountered while deserializing a dlib::object_detector object.");
deserialize(item.scanner, in);
deserialize(item.w, in);
deserialize(item.boxes_overlap, in);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// object_detector member functions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename image_scanner_type
>
object_detector<image_scanner_type>::
object_detector (
)
{
}
// ----------------------------------------------------------------------------------------
template <
typename image_scanner_type
>
object_detector<image_scanner_type>::
object_detector (
const object_detector& item
)
{
boxes_overlap = item.boxes_overlap;
w = item.w;
scanner.copy_configuration(item.scanner);
}
// ----------------------------------------------------------------------------------------
template <
typename image_scanner_type
>
object_detector<image_scanner_type>::
object_detector (
const image_scanner_type& scanner_,
const test_box_overlap& overlap_tester,
const feature_vector_type& w_
) :
boxes_overlap(overlap_tester),
w(w_)
{
// make sure requires clause is not broken
DLIB_ASSERT(scanner_.get_num_detection_templates() > 0 &&
w_.size() == scanner_.get_num_dimensions() + 1,
"\t object_detector::object_detector(scanner_,overlap_tester,w_)"
<< "\n\t Invalid inputs were given to this function "
<< "\n\t scanner_.get_num_detection_templates(): " << scanner_.get_num_detection_templates()
<< "\n\t w_.size(): " << w_.size()
<< "\n\t scanner_.get_num_dimensions(): " << scanner_.get_num_dimensions()
<< "\n\t this: " << this
);
scanner.copy_configuration(scanner_);
}
// ----------------------------------------------------------------------------------------
template <
typename image_scanner_type
>
object_detector<image_scanner_type>& object_detector<image_scanner_type>::
operator= (
const object_detector& item
)
{
if (this == &item)
return *this;
boxes_overlap = item.boxes_overlap;
w = item.w;
scanner.copy_configuration(item.scanner);
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename image_scanner_type
>
template <
typename image_type
>
std::vector<rectangle> object_detector<image_scanner_type>::
operator() (
const image_type& img,
double adjust_threshold
)
{
std::vector<rectangle> final_dets;
if (w.size() != 0)
{
std::vector<std::pair<double, rectangle> > dets;
const double thresh = w(scanner.get_num_dimensions());
scanner.load(img);
scanner.detect(w, dets, thresh + adjust_threshold);
for (unsigned long i = 0; i < dets.size(); ++i)
{
if (overlaps_any_box(final_dets, dets[i].second))
continue;
final_dets.push_back(dets[i].second);
}
}
return final_dets;
}
// ----------------------------------------------------------------------------------------
template <
typename image_scanner_type
>
template <
typename image_type
>
void object_detector<image_scanner_type>::
operator() (
const image_type& img,
std::vector<std::pair<double, rectangle> >& final_dets,
double adjust_threshold
)
{
final_dets.clear();
if (w.size() != 0)
{
std::vector<std::pair<double, rectangle> > dets;
const double thresh = w(scanner.get_num_dimensions());
scanner.load(img);
scanner.detect(w, dets, thresh + adjust_threshold);
for (unsigned long i = 0; i < dets.size(); ++i)
{
if (overlaps_any_box(final_dets, dets[i].second))
continue;
dets[i].first -= thresh;
final_dets.push_back(dets[i]);
}
}
}
// ----------------------------------------------------------------------------------------
template <
typename image_scanner_type
>
template <
typename image_type
>
void object_detector<image_scanner_type>::
operator() (
const image_type& img,
std::vector<std::pair<double, full_object_detection> >& final_dets,
double adjust_threshold
)
{
std::vector<std::pair<double, rectangle> > temp_dets;
(*this)(img,temp_dets,adjust_threshold);
final_dets.clear();
final_dets.reserve(temp_dets.size());
// convert all the rectangle detections into full_object_detections.
for (unsigned long i = 0; i < temp_dets.size(); ++i)
{
final_dets.push_back(std::make_pair(temp_dets[i].first,
scanner.get_full_object_detection(temp_dets[i].second, w)));
}
}
// ----------------------------------------------------------------------------------------
template <
typename image_scanner_type
>
template <
typename image_type
>
void object_detector<image_scanner_type>::
operator() (
const image_type& img,
std::vector<full_object_detection>& final_dets,
double adjust_threshold
)
{
std::vector<std::pair<double, rectangle> > temp_dets;
(*this)(img,temp_dets,adjust_threshold);
final_dets.clear();
final_dets.reserve(temp_dets.size());
// convert all the rectangle detections into full_object_detections.
for (unsigned long i = 0; i < temp_dets.size(); ++i)
{
final_dets.push_back(scanner.get_full_object_detection(temp_dets[i].second, w));
}
}
// ----------------------------------------------------------------------------------------
template <
typename image_scanner_type
>
const test_box_overlap& object_detector<image_scanner_type>::
get_overlap_tester (
) const
{
return boxes_overlap;
}
// ----------------------------------------------------------------------------------------
template <
typename image_scanner_type
>
const image_scanner_type& object_detector<image_scanner_type>::
get_scanner (
) const
{
return scanner;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_OBJECT_DeTECTOR_H__