mirror of https://github.com/davisking/dlib.git
Moved the responsibility for automatically filling out a test_box_overlap
object from the structural_object_detection_trainer to the structural_svm_object_detection_problem. This allows us to use image scanners which require an image be loaded before get_best_matching_rect() can be called. I also made it so that the scanner loading (and therefore feature extraction) is threaded. Previously, it only used a single core.
This commit is contained in:
parent
d81641cd8e
commit
b638145fb6
|
@ -275,29 +275,8 @@ namespace dlib
|
|||
}
|
||||
#endif
|
||||
|
||||
test_box_overlap local_overlap_tester;
|
||||
|
||||
if (auto_overlap_tester)
|
||||
{
|
||||
std::vector<std::vector<rectangle> > mapped_rects(truth_object_detections.size());
|
||||
for (unsigned long i = 0; i < truth_object_detections.size(); ++i)
|
||||
{
|
||||
mapped_rects[i].resize(truth_object_detections[i].size());
|
||||
for (unsigned long j = 0; j < truth_object_detections[i].size(); ++j)
|
||||
{
|
||||
mapped_rects[i][j] = scanner.get_best_matching_rect(truth_object_detections[i][j].get_rect());
|
||||
}
|
||||
}
|
||||
|
||||
local_overlap_tester = find_tight_overlap_tester(mapped_rects);
|
||||
}
|
||||
else
|
||||
{
|
||||
local_overlap_tester = overlap_tester;
|
||||
}
|
||||
|
||||
structural_svm_object_detection_problem<image_scanner_type,image_array_type >
|
||||
svm_prob(scanner, local_overlap_tester, images, truth_object_detections, num_threads);
|
||||
svm_prob(scanner, overlap_tester, auto_overlap_tester, images, truth_object_detections, num_threads);
|
||||
|
||||
if (verbose)
|
||||
svm_prob.be_verbose();
|
||||
|
@ -314,7 +293,7 @@ namespace dlib
|
|||
solver(svm_prob,w);
|
||||
|
||||
// report the results of the training.
|
||||
return object_detector<image_scanner_type>(scanner, local_overlap_tester, w);
|
||||
return object_detector<image_scanner_type>(scanner, svm_prob.get_overlap_tester(), w);
|
||||
}
|
||||
|
||||
template <
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace dlib
|
|||
structural_svm_object_detection_problem(
|
||||
const image_scanner_type& scanner,
|
||||
const test_box_overlap& overlap_tester,
|
||||
const bool auto_overlap_tester,
|
||||
const image_array_type& images_,
|
||||
const std::vector<std::vector<full_object_detection> >& truth_object_detections_,
|
||||
unsigned long num_threads = 2
|
||||
|
@ -75,19 +76,34 @@ namespace dlib
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
scanners.set_max_size(images.size());
|
||||
scanners.set_size(images.size());
|
||||
|
||||
// The purpose of the max_num_dets member variable is to give us a reasonable
|
||||
// upper limit on the number of detections we can expect from a single image.
|
||||
// This is used in the separation_oracle to put a hard limit on the number of
|
||||
// detections we will consider. We do this purely for computational reasons
|
||||
// since otherwise we can end up wasting large amounts of time on certain
|
||||
// pathological cases during optimization which ultimately do not influence the
|
||||
// result. Therefore, we for the separation oracle to only consider the
|
||||
// max_num_dets strongest detections.
|
||||
max_num_dets = 0;
|
||||
for (unsigned long i = 0; i < truth_object_detections.size(); ++i)
|
||||
{
|
||||
if (truth_object_detections[i].size() > max_num_dets)
|
||||
max_num_dets = truth_object_detections[i].size();
|
||||
|
||||
scanners[i].copy_configuration(scanner);
|
||||
}
|
||||
max_num_dets = max_num_dets*3 + 10;
|
||||
|
||||
initialize_scanners(scanner, num_threads);
|
||||
|
||||
if (auto_overlap_tester)
|
||||
{
|
||||
auto_configure_overlap_tester();
|
||||
}
|
||||
}
|
||||
|
||||
test_box_overlap get_overlap_tester (
|
||||
) const
|
||||
{
|
||||
return boxes_overlap;
|
||||
}
|
||||
|
||||
void set_match_eps (
|
||||
|
@ -154,6 +170,24 @@ namespace dlib
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
void auto_configure_overlap_tester(
|
||||
)
|
||||
{
|
||||
std::vector<std::vector<rectangle> > mapped_rects(truth_object_detections.size());
|
||||
for (unsigned long i = 0; i < truth_object_detections.size(); ++i)
|
||||
{
|
||||
mapped_rects[i].resize(truth_object_detections[i].size());
|
||||
for (unsigned long j = 0; j < truth_object_detections[i].size(); ++j)
|
||||
{
|
||||
mapped_rects[i][j] = scanners[i].get_best_matching_rect(truth_object_detections[i][j].get_rect());
|
||||
}
|
||||
}
|
||||
|
||||
boxes_overlap = find_tight_overlap_tester(mapped_rects);
|
||||
}
|
||||
|
||||
|
||||
virtual long get_num_dimensions (
|
||||
) const
|
||||
{
|
||||
|
@ -172,7 +206,7 @@ namespace dlib
|
|||
feature_vector_type& psi
|
||||
) const
|
||||
{
|
||||
const image_scanner_type& scanner = get_scanner(idx);
|
||||
const image_scanner_type& scanner = scanners[idx];
|
||||
|
||||
psi.set_size(get_num_dimensions());
|
||||
std::vector<rectangle> mapped_rects;
|
||||
|
@ -268,7 +302,7 @@ namespace dlib
|
|||
feature_vector_type& psi
|
||||
) const
|
||||
{
|
||||
const image_scanner_type& scanner = get_scanner(idx);
|
||||
const image_scanner_type& scanner = scanners[idx];
|
||||
|
||||
std::vector<std::pair<double, rectangle> > dets;
|
||||
const double thresh = current_solution(scanner.get_num_dimensions());
|
||||
|
@ -437,13 +471,38 @@ namespace dlib
|
|||
return std::make_pair(match,best_idx);
|
||||
}
|
||||
|
||||
|
||||
const image_scanner_type& get_scanner (long idx) const
|
||||
struct init_scanners_helper
|
||||
{
|
||||
if (scanners[idx].is_loaded_with_image() == false)
|
||||
scanners[idx].load(images[idx]);
|
||||
init_scanners_helper (
|
||||
array<image_scanner_type>& scanners_,
|
||||
const image_array_type& images_
|
||||
) :
|
||||
scanners(scanners_),
|
||||
images(images_)
|
||||
{}
|
||||
|
||||
return scanners[idx];
|
||||
array<image_scanner_type>& scanners;
|
||||
const image_array_type& images;
|
||||
|
||||
void operator() (long i ) const
|
||||
{
|
||||
scanners[i].load(images[i]);
|
||||
}
|
||||
};
|
||||
|
||||
void initialize_scanners (
|
||||
const image_scanner_type& scanner,
|
||||
unsigned long num_threads
|
||||
)
|
||||
{
|
||||
scanners.set_max_size(images.size());
|
||||
scanners.set_size(images.size());
|
||||
|
||||
for (unsigned long i = 0; i < scanners.size(); ++i)
|
||||
scanners[i].copy_configuration(scanner);
|
||||
|
||||
// now load the images into all the scanners
|
||||
parallel_for(num_threads, 0, scanners.size(), init_scanners_helper(scanners, images));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace dlib
|
|||
A detection is considered a false alarm if it doesn't match with any
|
||||
of the ground truth rectangles or if it is a duplicate detection of a
|
||||
truth rectangle. Finally, for the purposes of calculating loss, a match
|
||||
is determined using the following formula, rectangles A and B match
|
||||
is determined using the following formula where rectangles A and B match
|
||||
if and only if:
|
||||
A.intersect(B).area()/(A+B).area() > get_match_eps()
|
||||
!*/
|
||||
|
@ -77,6 +77,7 @@ namespace dlib
|
|||
structural_svm_object_detection_problem(
|
||||
const image_scanner_type& scanner,
|
||||
const test_box_overlap& overlap_tester,
|
||||
const bool auto_overlap_tester,
|
||||
const image_array_type& images,
|
||||
const std::vector<std::vector<full_object_detection> >& truth_object_detections,
|
||||
unsigned long num_threads = 2
|
||||
|
@ -95,12 +96,18 @@ namespace dlib
|
|||
attempts to learn to predict truth_object_detections[i] based on
|
||||
images[i]. Or in other words, this object can be used to learn a
|
||||
parameter vector, w, such that an object_detector declared as:
|
||||
object_detector<image_scanner_type> detector(scanner,overlap_tester,w)
|
||||
object_detector<image_scanner_type> detector(scanner,get_overlap_tester(),w)
|
||||
results in a detector object which attempts to compute the locations of
|
||||
all the objects in truth_object_detections. So if you called
|
||||
detector(images[i]) you would hopefully get a list of rectangles back
|
||||
that had truth_object_detections[i].size() elements and contained exactly
|
||||
the rectangles indicated by truth_object_detections[i].
|
||||
- if (auto_overlap_tester == true) then
|
||||
- #get_overlap_tester() == a test_box_overlap object that is configured
|
||||
using the find_tight_overlap_tester() routine and the contents of
|
||||
truth_object_detections.
|
||||
- else
|
||||
- #get_overlap_tester() == overlap_tester
|
||||
- #get_match_eps() == 0.5
|
||||
- This object will use num_threads threads during the optimization
|
||||
procedure. You should set this parameter equal to the number of
|
||||
|
@ -109,6 +116,13 @@ namespace dlib
|
|||
- #get_loss_per_false_alarm() == 1
|
||||
!*/
|
||||
|
||||
test_box_overlap get_overlap_tester (
|
||||
) const;
|
||||
/*!
|
||||
ensures
|
||||
- returns the overlap tester used by this object.
|
||||
!*/
|
||||
|
||||
void set_match_eps (
|
||||
double eps
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue