Commit 221ad16d authored by Davis King's avatar Davis King

merged

parents 79a620b1 38dd831d
......@@ -193,6 +193,10 @@ namespace dlib
T& item
);
void push_back (
T&& item
);
typedef T* iterator;
typedef const T* const_iterator;
iterator begin() { return array_elements; }
......@@ -779,6 +783,17 @@ namespace dlib
}
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename mem_manager
>
void array<T,mem_manager>::
push_back (
T&& item
) { push_back(item); }
// ----------------------------------------------------------------------------------------
template <typename T, typename MM>
......
......@@ -274,6 +274,11 @@ namespace dlib
If an exception is thrown then it has no effect on *this.
!*/
void push_back (T&& item) { push_back(item); }
/*!
enable push_back from rvalues
!*/
typedef T* iterator;
typedef const T* const_iterator;
......
......@@ -188,6 +188,20 @@ namespace dlib
// ----------------------------------------------------------------------------------------
namespace impl
{
inline size_t num_non_ignored_boxes (const std::vector<mmod_rect>& rects)
{
size_t cnt = 0;
for (auto& b : rects)
{
if (!b.ignore)
cnt++;
}
return cnt;
}
}
template <
typename array_type
>
......@@ -235,7 +249,7 @@ namespace dlib
}
}
if (!source.should_skip_empty_images() || rects.size() != 0)
if (!source.should_skip_empty_images() || impl::num_non_ignored_boxes(rects) != 0)
{
load_image(img, data.images[i].filename);
if (rects.size() != 0)
......
......@@ -51,8 +51,9 @@ namespace dlib
) const;
/*!
ensures
- returns true if we are supposed to skip images that don't have any boxes
to load when loading an image dataset using load_image_dataset().
- returns true if we are supposed to skip images that don't have any
non-ignored boxes to load when loading an image dataset using
load_image_dataset().
!*/
image_dataset_file boxes_match_label(
......
......@@ -164,7 +164,6 @@ namespace dlib
// set the initial bias values to zero
biases(params,filters.size()) = 0;
}
template <typename SUBNET>
......@@ -346,17 +345,22 @@ namespace dlib
static_assert(0 <= _padding_x && _padding_x < _nc, "The padding must be smaller than the filter size.");
cont_(
num_con_outputs o
) :
learning_rate_multiplier(1),
weight_decay_multiplier(1),
bias_learning_rate_multiplier(1),
bias_weight_decay_multiplier(0),
num_filters_(o.num_outputs),
padding_y_(_padding_y),
padding_x_(_padding_x)
{
DLIB_CASSERT(num_filters_ > 0);
}
long num_filters() const { return _num_filters; }
cont_() : cont_(num_con_outputs(_num_filters)) {}
long num_filters() const { return num_filters_; }
long nr() const { return _nr; }
long nc() const { return _nc; }
long stride_y() const { return _stride_y; }
......@@ -364,6 +368,14 @@ namespace dlib
long padding_y() const { return padding_y_; }
long padding_x() const { return padding_x_; }
void set_num_filters(long num)
{
DLIB_CASSERT(num > 0);
DLIB_CASSERT(get_layer_params().size() == 0,
"You can't change the number of filters in cont_ if the parameter tensor has already been allocated.");
num_filters_ = num;
}
double get_learning_rate_multiplier () const { return learning_rate_multiplier; }
double get_weight_decay_multiplier () const { return weight_decay_multiplier; }
void set_learning_rate_multiplier(double val) { learning_rate_multiplier = val; }
......@@ -402,6 +414,7 @@ namespace dlib
weight_decay_multiplier(item.weight_decay_multiplier),
bias_learning_rate_multiplier(item.bias_learning_rate_multiplier),
bias_weight_decay_multiplier(item.bias_weight_decay_multiplier),
num_filters_(item.num_filters_),
padding_y_(item.padding_y_),
padding_x_(item.padding_x_)
{
......@@ -427,6 +440,7 @@ namespace dlib
weight_decay_multiplier = item.weight_decay_multiplier;
bias_learning_rate_multiplier = item.bias_learning_rate_multiplier;
bias_weight_decay_multiplier = item.bias_weight_decay_multiplier;
num_filters_ = item.num_filters_;
return *this;
}
......@@ -434,18 +448,18 @@ namespace dlib
void setup (const SUBNET& sub)
{
long num_inputs = _nr*_nc*sub.get_output().k();
long num_outputs = _num_filters;
long num_outputs = num_filters_;
// allocate params for the filters and also for the filter bias values.
params.set_size(num_inputs*_num_filters + _num_filters);
params.set_size(num_inputs*num_filters_ + num_filters_);
dlib::rand rnd(std::rand());
randomize_parameters(params, num_inputs+num_outputs, rnd);
filters = alias_tensor(sub.get_output().k(),_num_filters, _nr, _nc);
biases = alias_tensor(1,_num_filters);
filters = alias_tensor(sub.get_output().k(), num_filters_, _nr, _nc);
biases = alias_tensor(1,num_filters_);
// set the initial bias values to zero
biases(params,_num_filters) = 0;
biases(params,filters.size()) = 0;
}
template <typename SUBNET>
......@@ -484,7 +498,7 @@ namespace dlib
{
serialize("cont_1", out);
serialize(item.params, out);
serialize(_num_filters, out);
serialize(item.num_filters_, out);
serialize(_nr, out);
serialize(_nc, out);
serialize(_stride_y, out);
......@@ -503,7 +517,6 @@ namespace dlib
{
std::string version;
deserialize(version, in);
long num_filters;
long nr;
long nc;
int stride_y;
......@@ -511,7 +524,7 @@ namespace dlib
if (version == "cont_1")
{
deserialize(item.params, in);
deserialize(num_filters, in);
deserialize(item.num_filters_, in);
deserialize(nr, in);
deserialize(nc, in);
deserialize(stride_y, in);
......@@ -526,14 +539,6 @@ namespace dlib
deserialize(item.bias_weight_decay_multiplier, in);
if (item.padding_y_ != _padding_y) throw serialization_error("Wrong padding_y found while deserializing dlib::con_");
if (item.padding_x_ != _padding_x) throw serialization_error("Wrong padding_x found while deserializing dlib::con_");
if (num_filters != _num_filters)
{
std::ostringstream sout;
sout << "Wrong num_filters found while deserializing dlib::con_" << std::endl;
sout << "expected " << _num_filters << " but found " << num_filters << std::endl;
throw serialization_error(sout.str());
}
if (nr != _nr) throw serialization_error("Wrong nr found while deserializing dlib::con_");
if (nc != _nc) throw serialization_error("Wrong nc found while deserializing dlib::con_");
if (stride_y != _stride_y) throw serialization_error("Wrong stride_y found while deserializing dlib::con_");
......@@ -592,6 +597,7 @@ namespace dlib
double weight_decay_multiplier;
double bias_learning_rate_multiplier;
double bias_weight_decay_multiplier;
long num_filters_;
int padding_y_;
int padding_x_;
......
......@@ -941,6 +941,24 @@ namespace dlib
- #get_bias_weight_decay_multiplier() == 0
!*/
cont_(
num_con_outputs o
);
/*!
ensures
- #num_filters() == o.num_outputs
- #nr() == _nr
- #nc() == _nc
- #stride_y() == _stride_y
- #stride_x() == _stride_x
- #padding_y() == _padding_y
- #padding_x() == _padding_x
- #get_learning_rate_multiplier() == 1
- #get_weight_decay_multiplier() == 1
- #get_bias_learning_rate_multiplier() == 1
- #get_bias_weight_decay_multiplier() == 0
!*/
long num_filters(
) const;
/*!
......@@ -950,6 +968,19 @@ namespace dlib
of filters.
!*/
void set_num_filters(
long num
);
/*!
requires
- num > 0
- get_layer_params().size() == 0
(i.e. You can't change the number of filters in cont_ if the parameter
tensor has already been allocated.)
ensures
- #num_filters() == num
!*/
long nr(
) const;
/*!
......
......@@ -1163,6 +1163,15 @@ namespace dlib
return centered_rect(tran(center(rect)), rect.width(), rect.height());
}
inline mmod_rect tform_object (
const point_transform_affine& tran,
mmod_rect rect
)
{
rect.rect = tform_object(tran, rect.rect);
return rect;
}
inline full_object_detection tform_object(
const point_transform_affine& tran,
const full_object_detection& obj
......@@ -1209,7 +1218,7 @@ namespace dlib
for (unsigned long i = 0; i < objects[j].size(); ++i)
rects.push_back(impl::tform_object(tran, objects[j][i]));
images.push_back(temp);
images.push_back(std::move(temp));
objects.push_back(rects);
}
}
......@@ -1245,7 +1254,7 @@ namespace dlib
for (unsigned long j = 0; j < num; ++j)
{
const point_transform_affine tran = flip_image_left_right(images[j], temp);
images.push_back(temp);
images.push_back(std::move(temp));
rects.clear();
for (unsigned long i = 0; i < objects[j].size(); ++i)
......@@ -1544,7 +1553,7 @@ namespace dlib
for (unsigned long j = 0; j < images.size(); ++j)
{
const point_transform_affine tran = rotate_image(images[j], temp, angles(i));
new_images.push_back(temp);
new_images.push_back(std::move(temp));
objtemp.clear();
for (unsigned long k = 0; k < objects[j].size(); ++k)
......
......@@ -499,7 +499,7 @@ namespace dlib
requires
- image_array_type == a dlib::array or std::vector of image objects that each
implement the interface defined in dlib/image_processing/generic_image.h
- T == rectangle or full_object_detection
- T == rectangle, full_object_detection, or mmod_rect
- images.size() == objects.size()
ensures
- This function computes all the left/right flips of the contents of images and
......@@ -532,8 +532,8 @@ namespace dlib
implement the interface defined in dlib/image_processing/generic_image.h
- images.size() == objects.size()
- images.size() == objects2.size()
- T == rectangle or full_object_detection
- U == rectangle or full_object_detection
- T == rectangle, full_object_detection, or mmod_rect
- U == rectangle, full_object_detection, or mmod_rect
ensures
- This function computes all the left/right flips of the contents of images and
then appends them onto the end of the images array. It also finds the
......@@ -571,8 +571,8 @@ namespace dlib
- angles.size() > 0
- images.size() == objects.size()
- images.size() == objects2.size()
- T == rectangle or full_object_detection
- U == rectangle or full_object_detection
- T == rectangle, full_object_detection, or mmod_rect
- U == rectangle, full_object_detection, or mmod_rect
ensures
- This function computes angles.size() different rotations of all the given
images and then replaces the contents of images with those rotations of the
......@@ -608,7 +608,7 @@ namespace dlib
- is_vector(angles) == true
- angles.size() > 0
- images.size() == objects.size()
- T == rectangle or full_object_detection
- T == rectangle, full_object_detection, or mmod_rect
ensures
- This function is identical to the add_image_rotations() define above except
that it doesn't have objects2 as an argument.
......
......@@ -360,6 +360,90 @@ cross_validate_trainer_threaded(trainer,
<!-- ************************************************************************* -->
<questions group="Computer Vision">
<question text="Why doesn't the object detector I trained work?">
There are three general mistakes people make when trying to train an object detector with dlib.
<ul>
<li><h3>Not labeling all the objects in each image</h3>
The tools for training object detectors in dlib use the <a href="https://arxiv.org/abs/1502.00046">Max-Margin Object Detection</a>
loss. This loss optimizes the performance of the detector on the whole image, not on some subset of windows cropped from the training data.
That means it counts the number of missed detections and false alarms for each of the training images and tries to find a way
to minimize the sum of these two error metrics. For this to be possible, <b>you must label all the objects in each training image</b>.
If you leave unannotated objects in some of your training images then the loss will think any detections on these unannotated objects
are false alarms, and will therefore try to find a detector that doesn't detect them. If you have enough unannotated objects, the
most accurate detector will be the one that never detects anything. That's obviously not what you want. So make sure you annotate all the
objects in each image.
<p>
Sometimes annotating all the objects in each image is too
onerous, or there are ambiguous objects you don't care about.
In these cases you should annotate these objects you don't
care about with ignore boxes so that the MMOD loss knows to
ignore them. You can do this with dlib's imglab tool by
selecting a box and pressing i. Moreover, there are two ways
the code treats ignore boxes. When a detector generates a
detection it compares it against any ignore boxes and ignores
it if the boxes "overlap". Deciding if they overlap is based
on either their intersection over union or just basic percent
coverage of one by another. You have to think about what
mode you want when you annotate things and configure the
training code appropriately. The default behavior is to use
intersection over union to measure overlap. However, if you
wanted to simply mask out large parts of an image you
wouldn't want to use intersection over union to measure
overlap since small boxes contained entirely within the large
ignored region would have small IoU with the big ignore region and thus not "overlap"
the ignore region. In this case you should change the
settings to reflect this before training. The available configuration
options are discussed in great detail in parts of <a href="#Whereisthedocumentationforobjectfunction">dlib's documentation</a>.
</p>
</li>
<li><h3>Using training images that don't look like the testing images</h3>
This should be obvious, but needs to be pointed out. If there
is some clear difference between your training and testing
images then you have messed up. You need to show the training
algorithm real images so it can learn what to do. If instead
you only show it images that look obviously different from your
testing images don't be surprised if, when you run the detector
on the testing images, it doesn't work. As a rule of thumb,
<b>a human should not be able to tell if an image came from the training dataset or testing dataset</b>.
<p>
Here are some examples of bad datasets:
<ul>
<li>A training dataset where objects always appear with
some specific orientation but the testing images have a
diverse set of orientations.</li>
<li>A training dataset where objects are tightly cropped, but testing images that are uncropped.</li>
<li>A training dataset where objects appear only on a perfectly white background with nothing else present, but testing images where objects appear in a normal environment like living rooms or in natural scenes.</li>
</ul>
</p>
</li>
<li><h3>Using a HOG based detector but not understanding the limits of HOG templates</h3>
The <a href="fhog_object_detector_ex.cpp.html">HOG detector</a> is very fast and generally easy to train. However, you
have to be aware that HOG detectors are essentially rigid templates that are scanned over an image. So a single HOG detector
isn't going to be able to detect objects that appear in a wide range of orientations or undergo complex deformations or have complex
articulation.
<p>
For example, a HOG detector isn't going to be able to learn to detect human faces that are upright as well as faces rotated 90 degrees.
If you wanted to deal with that you would be best off training 2 detectors. One for upright faces and another for 90 degree rotated faces.
You can efficiently run multiple HOG detectors at once using the <a href="imaging.html#evaluate_detectors">evaluate_detectors</a> function, so it's not a huge deal to do this. Dlib's imglab tool also has a --cluster option that will help you split a training dataset into clusters that can
be detected by a single HOG detector. You will still need to manually review and clean the dataset after applying --cluster, but it makes
the process of splitting a dataset into coherent poses, from the point of view of HOG, a lot easier.
</p>
<p>
However, it should be emphasized that even using multiple HOG detectors will only get you so far. So at some point you should consider
using a <a href="ml.html#loss_mmod_">CNN based detection method</a> since CNNs can generally deal with arbitrary
rotations, poses, and deformations with one unified
detector.
</p>
</li>
</ul>
</question>
</questions>
<!-- ************************************************************************* -->
<questions group="Deep Learning">
<question text="Why can't I use the DNN module with Visual Studio?">
You can, but you need to use Visual Studio 2015 Update 3 or newer since prior versions
......@@ -369,6 +453,15 @@ cross_validate_trainer_threaded(trainer,
Microsoft web page has good enough C++11 support to compile the DNN
tools in dlib. So make sure you have a version no older than October
2016.
<p>
However, as of this writing, the newest version of Visual Studio is Visual Studio 2017, which
has WORSE C++11 support that Visual Studio 2015. In particular, if you try to use
the DNN tooling in Visual Studio 2017 the compiler will just hang. So use Visual Studio 2015.
</p>
<p>
It should also be noted that not even Visual Studio 2015 has perfect C++11 support. Specifically, the
larger and more complex imagenet and metric learning training examples don't compile in Visual Studio 2015.
</p>
</question>
<question text="Why can't I change the network architecture at runtime?">
......
......@@ -34,7 +34,7 @@
<p> If you want to make a big change or feature addition, it's probably a good idea to talk to me about it first.
Additionally, you should read over the coding guidelines below
and try to follow them. It is also probably a good idea to read the books Effective C++ and
More Effective C++ by Scott Myers.
More Effective C++ by Scott Meyers.
</p>
......
......@@ -42,7 +42,7 @@
<xsl:variable name="lcletters">abcdefghijklmnopqrstuvwxyz </xsl:variable>
<xsl:variable name="ucletters">ABCDEFGHIJKLMNOPQRSTUVWXYZ </xsl:variable>
<xsl:variable name="badletters">?()&lt;&gt; /\&amp;~!@#$%^*_+=-[]{}</xsl:variable>
<xsl:variable name="badletters">'?()&lt;&gt; /\&amp;~!@#$%^*_+=-[]{}</xsl:variable>
<!-- ************************************************************************* -->
......
#!/usr/bin/python
# The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
#
# This example shows how to use dlib's face recognition tool for image alignment.
#
# COMPILING/INSTALLING THE DLIB PYTHON INTERFACE
# You can install dlib using the command:
# pip install dlib
#
# Alternatively, if you want to compile dlib yourself then go into the dlib
# root folder and run:
# python setup.py install
# or
# python setup.py install --yes USE_AVX_INSTRUCTIONS
# if you have a CPU that supports AVX instructions, since this makes some
# things run faster. This code will also use CUDA if you have CUDA and cuDNN
# installed.
#
# Compiling dlib should work on any operating system so long as you have
# CMake and boost-python installed. On Ubuntu, this can be done easily by
# running the command:
# sudo apt-get install libboost-python-dev cmake
#
# Also note that this example requires OpenCV and Numpy which can be installed
# via the command:
# pip install opencv-python numpy
# Or downloaded from http://opencv.org/releases.html
import sys
import dlib
import cv2
import numpy as np
if len(sys.argv) != 3:
print(
"Call this program like this:\n"
" ./face_alignment.py shape_predictor_5_face_landmarks.dat ../examples/faces/bald_guys.jpg\n"
"You can download a trained facial shape predictor from:\n"
" http://dlib.net/files/shape_predictor_5_face_landmarks.dat.bz2\n")
exit()
predictor_path = sys.argv[1]
face_file_path = sys.argv[2]
# Load all the models we need: a detector to find the faces, a shape predictor
# to find face landmarks so we can precisely localize the face
detector = dlib.get_frontal_face_detector()
sp = dlib.shape_predictor(predictor_path)
# Load the image using OpenCV
bgr_img = cv2.imread(face_file_path)
if bgr_img is None:
print("Sorry, we could not load '{}' as an image".format(face_file_path))
exit()
# Convert to RGB since dlib uses RGB images
img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2RGB)
# Ask the detector to find the bounding boxes of each face. The 1 in the
# second argument indicates that we should upsample the image 1 time. This
# will make everything bigger and allow us to detect more faces.
dets = detector(img, 1)
num_faces = len(dets)
if num_faces == 0:
print("Sorry, there were no faces found in '{}'".format(face_file_path))
exit()
# Find the 5 face landmarks we need to do the alignment.
faces = dlib.full_object_detections()
for detection in dets:
faces.append(sp(img, detection))
# Get the aligned face images
# Optionally:
# images = dlib.get_face_chips(img, faces, size=160, padding=0.25)
images = dlib.get_face_chips(img, faces, size=320)
for image in images:
cv_rgb_image = np.array(image).astype(np.uint8)
cv_bgr_img = cv2.cvtColor(cv_rgb_image, cv2.COLOR_RGB2BGR)
cv2.imshow('image',cv_bgr_img)
cv2.waitKey(0)
# It is also possible to get a single chip
image = dlib.get_face_chip(img, faces[0])
cv_rgb_image = np.array(image).astype(np.uint8)
cv_bgr_img = cv2.cvtColor(cv_rgb_image, cv2.COLOR_RGB2BGR)
cv2.imshow('image',cv_bgr_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
......@@ -119,7 +119,8 @@ print("Saving faces in largest cluster to output folder...")
for i, index in enumerate(indices):
img, shape = images[index]
file_path = os.path.join(output_folder_path, "face_" + str(i))
dlib.save_face_chip(img, shape, file_path)
# The size and padding arguments are optional with default size=150x150 and padding=0.25
dlib.save_face_chip(img, shape, file_path, size=150, padding=0.25)
......
scikit-image>=0.9.3
opencv-python
numpy
#!/usr/bin/python
# The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
#
# This example program shows how you can use dlib to make an object
# detector for things like faces, pedestrians, and any other semi-rigid
# object. In particular, we go though the steps to train the kind of sliding
# window object detector first published by Dalal and Triggs in 2005 in the
# paper Histograms of Oriented Gradients for Human Detection.
# This example program shows how you can use dlib to make a HOG based object
# detector for things like faces, pedestrians, and any other semi-rigid
# object. In particular, we go though the steps to train the kind of sliding
# window object detector first published by Dalal and Triggs in 2005 in the
# paper Histograms of Oriented Gradients for Human Detection.
#
#
# COMPILING/INSTALLING THE DLIB PYTHON INTERFACE
......
......@@ -166,7 +166,7 @@ boost::python::list chinese_whispers_clustering(boost::python::list descriptors,
edges.push_back(sample_pair(i,j));
}
}
const auto num_clusters = chinese_whispers(edges, labels);
chinese_whispers(edges, labels);
for (size_t i = 0; i < labels.size(); ++i)
{
clusters.append(labels[i]);
......@@ -177,13 +177,18 @@ boost::python::list chinese_whispers_clustering(boost::python::list descriptors,
void save_face_chips (
object img,
const std::vector<full_object_detection>& faces,
const std::string& chip_filename
const std::string& chip_filename,
size_t size = 150,
float padding = 0.25
)
{
if (!is_rgb_python_image(img))
throw dlib::error("Unsupported image type, must be RGB image.");
int num_faces = faces.size();
std::vector<chip_details> dets;
for (auto& f : faces)
dets.push_back(get_face_chip_details(f, 150, 0.25));
dets.push_back(get_face_chip_details(f, size, padding));
dlib::array<matrix<rgb_pixel>> face_chips;
extract_image_chips(numpy_rgb_image(img), dets, face_chips);
int i=0;
......@@ -206,14 +211,86 @@ void save_face_chips (
void save_face_chip (
object img,
const full_object_detection& face,
const std::string& chip_filename
const std::string& chip_filename,
size_t size = 150,
float padding = 0.25
)
{
std::vector<full_object_detection> faces(1, face);
save_face_chips(img, faces, chip_filename);
save_face_chips(img, faces, chip_filename, size, padding);
return;
}
BOOST_PYTHON_FUNCTION_OVERLOADS(save_face_chip_with_defaults, save_face_chip, 3, 5)
BOOST_PYTHON_FUNCTION_OVERLOADS(save_face_chips_with_defaults, save_face_chips, 3, 5)
// ----------------------------------------------------------------------------------------
boost::python::list get_face_chips (
object img,
const std::vector<full_object_detection>& faces,
size_t size = 150,
float padding = 0.25
)
{
if (!is_rgb_python_image(img))
throw dlib::error("Unsupported image type, must be RGB image.");
if (faces.size() < 1) {
throw dlib::error("No face were specified in the faces array.");
}
boost::python::list chips_list;
std::vector<chip_details> dets;
for (auto& f : faces)
dets.push_back(get_face_chip_details(f, size, padding));
dlib::array<matrix<rgb_pixel>> face_chips;
extract_image_chips(numpy_rgb_image(img), dets, face_chips);
for (auto& chip : face_chips)
{
boost::python::list img;
for(size_t row=0; row<size; row++) {
boost::python::list row_list;
for(size_t col=0; col<size; col++) {
rgb_pixel pixel = chip(row, col);
boost::python::list item;
item.append(pixel.red);
item.append(pixel.green);
item.append(pixel.blue);
row_list.append(item);
}
img.append(row_list);
}
chips_list.append(img);
}
return chips_list;
}
boost::python::list get_face_chip (
object img,
const full_object_detection& face,
size_t size = 150,
float padding = 0.25
)
{
std::vector<full_object_detection> faces(1, face);
boost::python::list result = get_face_chips(img, faces, size, padding);
size_t num_images = boost::python::len(result);
if(num_images == 1) {
return boost::python::extract<boost::python::list>(result[0]);
} else {
throw dlib::error("No face chips found!");
}
}
BOOST_PYTHON_FUNCTION_OVERLOADS(get_face_chip_with_defaults, get_face_chip, 2, 4)
BOOST_PYTHON_FUNCTION_OVERLOADS(get_face_chips_with_defaults, get_face_chips, 2, 4)
// ----------------------------------------------------------------------------------------
......@@ -232,17 +309,27 @@ void bind_face_recognition()
);
}
def("save_face_chip", &save_face_chip, (arg("img"),arg("face"),arg("chip_filename")),
"Takes an image and a full_object_detection that references a face in that image and saves the face with the specified file name prefix. The face will be rotated upright and scaled to 150x150 pixels."
);
def("save_face_chips", &save_face_chips, (arg("img"),arg("faces"),arg("chip_filename")),
"Takes an image and a full_object_detections object that reference faces in that image and saves the faces with the specified file name prefix. The faces will be rotated upright and scaled to 150x150 pixels."
);
def("save_face_chip", &save_face_chip, save_face_chip_with_defaults(
"Takes an image and a full_object_detection that references a face in that image and saves the face with the specified file name prefix. The face will be rotated upright and scaled to 150x150 pixels or with the optional specified size and padding.",
(arg("img"), arg("face"), arg("chip_filename"), arg("size"), arg("padding"))
));
def("save_face_chips", &save_face_chips, save_face_chips_with_defaults(
"Takes an image and a full_object_detections object that reference faces in that image and saves the faces with the specified file name prefix. The faces will be rotated upright and scaled to 150x150 pixels or with the optional specified size and padding.",
(arg("img"), arg("faces"), arg("chip_filename"), arg("size"), arg("padding"))
));
def("get_face_chip", &get_face_chip, get_face_chip_with_defaults(
"Takes an image and a full_object_detection that references a face in that image and returns the face as a list of lists representing the image. The face will be rotated upright and scaled to 150x150 pixels or with the optional specified size and padding.",
(arg("img"), arg("face"), arg("size"), arg("padding"))
));
def("get_face_chips", &get_face_chips, get_face_chips_with_defaults(
"Takes an image and a full_object_detections object that reference faces in that image and returns the faces as a list of list of lists representing the image. The faces will be rotated upright and scaled to 150x150 pixels or with the optional specified size and padding.",
(arg("img"), arg("faces"), arg("size"), arg("padding"))
));
def("chinese_whispers_clustering", &chinese_whispers_clustering, (arg("descriptors"), arg("threshold")),
"Takes a list of descriptors and returns a list that contains a label for each descriptor. Clustering is done using dlib::chinese_whispers."
);
{
{
typedef std::vector<full_object_detection> type;
class_<type>("full_object_detections", "An array of full_object_detection objects.")
.def(vector_indexing_suite<type>())
......
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