Commit 8b954260 authored by Davis King's avatar Davis King

Added the option to tell the optimizer there are "ignorable" rectangles

in each image.
parent 1df8c441
......@@ -263,12 +263,76 @@ namespace dlib
const std::vector<std::vector<full_object_detection> >& truth_object_detections
) const
{
std::vector<std::vector<rectangle> > empty_ignore(images.size());
return train_impl(images, truth_object_detections, empty_ignore, test_box_overlap());
}
template <
typename image_array_type
>
const trained_function_type train (
const image_array_type& images,
const std::vector<std::vector<full_object_detection> >& truth_object_detections,
const std::vector<std::vector<rectangle> >& ignore,
const test_box_overlap& ignore_overlap_tester = test_box_overlap()
) const
{
return train_impl(images, truth_object_detections, ignore, ignore_overlap_tester);
}
template <
typename image_array_type
>
const trained_function_type train (
const image_array_type& images,
const std::vector<std::vector<rectangle> >& truth_object_detections
) const
{
std::vector<std::vector<rectangle> > empty_ignore(images.size());
return train(images, truth_object_detections, empty_ignore, test_box_overlap());
}
template <
typename image_array_type
>
const trained_function_type train (
const image_array_type& images,
const std::vector<std::vector<rectangle> >& truth_object_detections,
const std::vector<std::vector<rectangle> >& ignore,
const test_box_overlap& ignore_overlap_tester = test_box_overlap()
) const
{
std::vector<std::vector<full_object_detection> > truth_dets(truth_object_detections.size());
for (unsigned long i = 0; i < truth_object_detections.size(); ++i)
{
for (unsigned long j = 0; j < truth_object_detections[i].size(); ++j)
{
truth_dets[i].push_back(full_object_detection(truth_object_detections[i][j]));
}
}
return train_impl(images, truth_dets, ignore, ignore_overlap_tester);
}
private:
template <
typename image_array_type
>
const trained_function_type train_impl (
const image_array_type& images,
const std::vector<std::vector<full_object_detection> >& truth_object_detections,
const std::vector<std::vector<rectangle> >& ignore,
const test_box_overlap& ignore_overlap_tester
) const
{
#ifdef ENABLE_ASSERTS
// make sure requires clause is not broken
DLIB_ASSERT(is_learning_problem(images,truth_object_detections) == true,
DLIB_ASSERT(is_learning_problem(images,truth_object_detections) == true && images.size() == ignore.size(),
"\t trained_function_type structural_object_detection_trainer::train()"
<< "\n\t invalid inputs were given to this function"
<< "\n\t images.size(): " << images.size()
<< "\n\t ignore.size(): " << ignore.size()
<< "\n\t truth_object_detections.size(): " << truth_object_detections.size()
<< "\n\t is_learning_problem(images,truth_object_detections): " << is_learning_problem(images,truth_object_detections)
);
......@@ -291,7 +355,8 @@ namespace dlib
#endif
structural_svm_object_detection_problem<image_scanner_type,image_array_type >
svm_prob(scanner, overlap_tester, auto_overlap_tester, images, truth_object_detections, num_threads);
svm_prob(scanner, overlap_tester, auto_overlap_tester, images,
truth_object_detections, ignore, ignore_overlap_tester, num_threads);
if (verbose)
svm_prob.be_verbose();
......@@ -312,28 +377,6 @@ namespace dlib
return object_detector<image_scanner_type>(scanner, svm_prob.get_overlap_tester(), w);
}
template <
typename image_array_type
>
const trained_function_type train (
const image_array_type& images,
const std::vector<std::vector<rectangle> >& truth_object_detections
) const
{
std::vector<std::vector<full_object_detection> > truth_dets(truth_object_detections.size());
for (unsigned long i = 0; i < truth_object_detections.size(); ++i)
{
for (unsigned long j = 0; j < truth_object_detections[i].size(); ++j)
{
truth_dets[i].push_back(full_object_detection(truth_object_detections[i][j]));
}
}
return train(images, truth_dets);
}
private:
image_scanner_type scanner;
test_box_overlap overlap_tester;
......
......@@ -318,6 +318,65 @@ namespace dlib
Therefore, this version of train() is a convenience function for for the
case where you don't have any movable components of the detection templates.
!*/
template <
typename image_array_type
>
const trained_function_type train (
const image_array_type& images,
const std::vector<std::vector<full_object_detection> >& truth_object_detections,
const std::vector<std::vector<rectangle> >& ignore,
const test_box_overlap& ignore_overlap_tester = test_box_overlap()
) const;
/*!
requires
- is_learning_problem(images, truth_object_detections) == true
- it must be valid to pass images[0] into the image_scanner_type::load() method.
(also, image_array_type must be an implementation of dlib/array/array_kernel_abstract.h)
- ignore.size() == images.size()
- for all valid i, j:
- truth_object_detections[i][j].num_parts() == get_scanner().get_num_movable_components_per_detection_template()
- all_parts_in_rect(truth_object_detections[i][j]) == true
ensures
- Uses the structural_svm_object_detection_problem to train an object_detector
on the given images and truth_object_detections.
- for all valid i:
- Within images[i] any detections that match against a rectangle in
ignore[i], according to ignore_overlap_tester, are ignored. That is,
the optimizer doesn't care if the detector outputs a detection that
matches any of the ignore rectangles or if it fails to output a
detection for an ignore rectangle. Therefore, if there are objects
in your dataset that you are unsure you want to detect or otherwise
don't care if the detector gets or doesn't then you can mark them
with ignore rectangles and the optimizer will simply ignore them.
- returns a function F with the following properties:
- F(new_image) == A prediction of what objects are present in new_image. This
is a set of rectangles indicating their positions.
!*/
template <
typename image_array_type
>
const trained_function_type train (
const image_array_type& images,
const std::vector<std::vector<rectangle> >& truth_object_detections,
const std::vector<std::vector<rectangle> >& ignore,
const test_box_overlap& ignore_overlap_tester = test_box_overlap()
) const;
/*!
requires
- is_learning_problem(images, truth_object_detections) == true
- ignore.size() == images.size()
- it must be valid to pass images[0] into the image_scanner_type::load() method.
(also, image_array_type must be an implementation of dlib/array/array_kernel_abstract.h)
- get_scanner().get_num_movable_components_per_detection_template() == 0
ensures
- This function is identical to the above train(), except that it converts
each element of truth_object_detections into a full_object_detection by
passing it to full_object_detection's constructor taking only a rectangle.
Therefore, this version of train() is a convenience function for for the
case where you don't have any movable components of the detection templates.
!*/
};
// ----------------------------------------------------------------------------------------
......
......@@ -40,12 +40,16 @@ namespace dlib
const bool auto_overlap_tester,
const image_array_type& images_,
const std::vector<std::vector<full_object_detection> >& truth_object_detections_,
const std::vector<std::vector<rectangle> >& ignore_,
const test_box_overlap& ignore_overlap_tester_,
unsigned long num_threads = 2
) :
structural_svm_problem_threaded<matrix<double,0,1> >(num_threads),
boxes_overlap(overlap_tester),
images(images_),
truth_object_detections(truth_object_detections_),
ignore(ignore_),
ignore_overlap_tester(ignore_overlap_tester_),
match_eps(0.5),
loss_per_false_alarm(1),
loss_per_missed_target(1)
......@@ -53,11 +57,14 @@ namespace dlib
#ifdef ENABLE_ASSERTS
// make sure requires clause is not broken
DLIB_ASSERT(is_learning_problem(images_, truth_object_detections_) &&
ignore_.size() == images_.size() &&
scanner.get_num_detection_templates() > 0,
"\t structural_svm_object_detection_problem::structural_svm_object_detection_problem()"
<< "\n\t Invalid inputs were given to this function "
<< "\n\t scanner.get_num_detection_templates(): " << scanner.get_num_detection_templates()
<< "\n\t is_learning_problem(images_,truth_object_detections_): " << is_learning_problem(images_,truth_object_detections_)
<< "\n\t ignore.size(): " << ignore.size()
<< "\n\t images.size(): " << images.size()
<< "\n\t this: " << this
);
for (unsigned long i = 0; i < truth_object_detections.size(); ++i)
......@@ -393,7 +400,7 @@ namespace dlib
}
}
}
else
else if (!overlaps_ignore_box(idx,dets[i].second))
{
// didn't hit anything
final_dets.push_back(dets[i].second);
......@@ -437,6 +444,19 @@ namespace dlib
return false;
}
bool overlaps_ignore_box (
const long idx,
const dlib::rectangle& rect
) const
{
for (unsigned long i = 0; i < ignore[idx].size(); ++i)
{
if (ignore_overlap_tester(ignore[idx][i], rect))
return true;
}
return false;
}
std::pair<double,unsigned int> find_best_match(
const std::vector<full_object_detection>& boxes,
const rectangle rect
......@@ -513,6 +533,8 @@ namespace dlib
const image_array_type& images;
const std::vector<std::vector<full_object_detection> >& truth_object_detections;
const std::vector<std::vector<rectangle> >& ignore;
const test_box_overlap ignore_overlap_tester;
unsigned long max_num_dets;
double match_eps;
......
......@@ -81,11 +81,14 @@ namespace dlib
const bool auto_overlap_tester,
const image_array_type& images,
const std::vector<std::vector<full_object_detection> >& truth_object_detections,
const std::vector<std::vector<rectangle> >& ignore,
const test_box_overlap& ignore_overlap_tester,
unsigned long num_threads = 2
);
/*!
requires
- is_learning_problem(images, truth_object_detections)
- ignore.size() == images.size()
- scanner.get_num_detection_templates() > 0
- scanner.load(images[0]) must be a valid expression.
- for all valid i, j:
......@@ -115,6 +118,15 @@ namespace dlib
available processing cores on your machine.
- #get_loss_per_missed_target() == 1
- #get_loss_per_false_alarm() == 1
- for all valid i:
- Within images[i] any detections that match against a rectangle in
ignore[i], according to ignore_overlap_tester, are ignored. That is,
the optimizer doesn't care if the detector outputs a detection that
matches any of the ignore rectangles or if it fails to output a
detection for an ignore rectangle. Therefore, if there are objects
in your dataset that you are unsure you want to detect or otherwise
don't care if the detector gets or doesn't then you can mark them
with ignore rectangles and the optimizer will simply ignore them.
!*/
test_box_overlap get_overlap_tester (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment