// 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__