mirror of https://github.com/davisking/dlib.git
Add python api that generates desciptor(s) from the aligned image(s) (#1667)
* Add python api that generates desciptor(s) from the aligned image(s) * Remove asserts from face_recognition.py example/tutorial * In batch_compute_face_descriptors_from_aligned_images, use for-in loop to simplify the code Improvde the document on binding methods and the error message if the aligned image is not of size 150x150
This commit is contained in:
parent
04a2387cfc
commit
f7f6f67618
|
@ -114,6 +114,23 @@ for f in glob.glob(os.path.join(faces_folder_path, "*.jpg")):
|
||||||
# In particular, a padding of 0.5 would double the width of the cropped area, a value of 1.
|
# In particular, a padding of 0.5 would double the width of the cropped area, a value of 1.
|
||||||
# would triple it, and so forth.
|
# would triple it, and so forth.
|
||||||
|
|
||||||
|
# There is another overload of compute_face_descriptor that can take
|
||||||
|
# as an input an aligned image.
|
||||||
|
#
|
||||||
|
# Note that it is important to generate the aligned image as
|
||||||
|
# dlib.get_face_chip would do it i.e. the size must be 150x150,
|
||||||
|
# centered and scaled.
|
||||||
|
#
|
||||||
|
# Here is a sample usage of that
|
||||||
|
|
||||||
|
print("Computing descriptor on aligned image ..")
|
||||||
|
|
||||||
|
# Let's generate the aligned image using get_face_chip
|
||||||
|
face_chip = dlib.get_face_chip(img, shape)
|
||||||
|
|
||||||
|
# Now we simply pass this chip (aligned image) to the api
|
||||||
|
face_descriptor_from_prealigned_image = facerec.compute_face_descriptor(face_chip)
|
||||||
|
print(face_descriptor_from_prealigned_image)
|
||||||
|
|
||||||
dlib.hit_enter_to_continue()
|
dlib.hit_enter_to_continue()
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,15 @@ public:
|
||||||
return compute_face_descriptors(img, faces, num_jitters, padding)[0];
|
return compute_face_descriptors(img, faces, num_jitters, padding)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
matrix<double,0,1> compute_face_descriptor_from_aligned_image (
|
||||||
|
numpy_image<rgb_pixel> img,
|
||||||
|
const int num_jitters
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<numpy_image<rgb_pixel>> images{img};
|
||||||
|
return batch_compute_face_descriptors_from_aligned_images(images, num_jitters)[0];
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<matrix<double,0,1>> compute_face_descriptors (
|
std::vector<matrix<double,0,1>> compute_face_descriptors (
|
||||||
numpy_image<rgb_pixel> img,
|
numpy_image<rgb_pixel> img,
|
||||||
const std::vector<full_object_detection>& faces,
|
const std::vector<full_object_detection>& faces,
|
||||||
|
@ -127,6 +136,52 @@ public:
|
||||||
return face_descriptors;
|
return face_descriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<matrix<double,0,1>> batch_compute_face_descriptors_from_aligned_images (
|
||||||
|
const std::vector<numpy_image<rgb_pixel>>& batch_imgs,
|
||||||
|
const int num_jitters
|
||||||
|
)
|
||||||
|
{
|
||||||
|
dlib::array<matrix<rgb_pixel>> face_chips;
|
||||||
|
for (auto& img : batch_imgs) {
|
||||||
|
|
||||||
|
matrix<rgb_pixel> image;
|
||||||
|
if (is_image<unsigned char>(img))
|
||||||
|
assign_image(image, numpy_image<unsigned char>(img));
|
||||||
|
else if (is_image<rgb_pixel>(img))
|
||||||
|
assign_image(image, numpy_image<rgb_pixel>(img));
|
||||||
|
else
|
||||||
|
throw dlib::error("Unsupported image type, must be 8bit gray or RGB image.");
|
||||||
|
|
||||||
|
// Check for the size of the image
|
||||||
|
if ((image.nr() != 150) || (image.nc() != 150)) {
|
||||||
|
throw dlib::error("Unsupported image size, it should be of size 150x150. Also cropping must be done as `dlib.get_face_chip` would do it. \
|
||||||
|
That is, centered and scaled essentially the same way.");
|
||||||
|
}
|
||||||
|
|
||||||
|
face_chips.push_back(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<matrix<double,0,1>> face_descriptors;
|
||||||
|
if (num_jitters <= 1)
|
||||||
|
{
|
||||||
|
// extract descriptors and convert from float vectors to double vectors
|
||||||
|
auto descriptors = net(face_chips, 16);
|
||||||
|
|
||||||
|
for (auto& des: descriptors) {
|
||||||
|
face_descriptors.push_back(matrix_cast<double>(des));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// extract descriptors and convert from float vectors to double vectors
|
||||||
|
for (auto& fimg : face_chips) {
|
||||||
|
auto& r = mean(mat(net(jitter_image(fimg, num_jitters), 16)));
|
||||||
|
face_descriptors.push_back(matrix_cast<double>(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return face_descriptors;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
dlib::rand rnd;
|
dlib::rand rnd;
|
||||||
|
@ -300,6 +355,12 @@ void bind_face_recognition(py::module &m)
|
||||||
"If num_jitters>1 then each face will be randomly jittered slightly num_jitters times, each run through the 128D projection, and the average used as the face descriptor. "
|
"If num_jitters>1 then each face will be randomly jittered slightly num_jitters times, each run through the 128D projection, and the average used as the face descriptor. "
|
||||||
"Optionally allows to override default padding of 0.25 around the face."
|
"Optionally allows to override default padding of 0.25 around the face."
|
||||||
)
|
)
|
||||||
|
.def("compute_face_descriptor", &face_recognition_model_v1::compute_face_descriptor_from_aligned_image,
|
||||||
|
py::arg("img"), py::arg("num_jitters")=0,
|
||||||
|
"Takes an aligned face image of size 150x150 and converts it into a 128D face descriptor."
|
||||||
|
"Note that the alignment should be done in the same way dlib.get_face_chip does it."
|
||||||
|
"If num_jitters>1 then image will be randomly jittered slightly num_jitters times, each run through the 128D projection, and the average used as the face descriptor. "
|
||||||
|
)
|
||||||
.def("compute_face_descriptor", &face_recognition_model_v1::compute_face_descriptors,
|
.def("compute_face_descriptor", &face_recognition_model_v1::compute_face_descriptors,
|
||||||
py::arg("img"), py::arg("faces"), py::arg("num_jitters")=0, py::arg("padding")=0.25,
|
py::arg("img"), py::arg("faces"), py::arg("num_jitters")=0, py::arg("padding")=0.25,
|
||||||
"Takes an image and an array of full_object_detections that reference faces in that image and converts them into 128D face descriptors. "
|
"Takes an image and an array of full_object_detections that reference faces in that image and converts them into 128D face descriptors. "
|
||||||
|
@ -309,9 +370,16 @@ void bind_face_recognition(py::module &m)
|
||||||
.def("compute_face_descriptor", &face_recognition_model_v1::batch_compute_face_descriptors,
|
.def("compute_face_descriptor", &face_recognition_model_v1::batch_compute_face_descriptors,
|
||||||
py::arg("batch_img"), py::arg("batch_faces"), py::arg("num_jitters")=0, py::arg("padding")=0.25,
|
py::arg("batch_img"), py::arg("batch_faces"), py::arg("num_jitters")=0, py::arg("padding")=0.25,
|
||||||
"Takes an array of images and an array of arrays of full_object_detections. `batch_faces[i]` must be an array of full_object_detections corresponding to the image `batch_img[i]`, "
|
"Takes an array of images and an array of arrays of full_object_detections. `batch_faces[i]` must be an array of full_object_detections corresponding to the image `batch_img[i]`, "
|
||||||
"referencing faces in that image. Every face will be converting into 128D face descriptors. "
|
"referencing faces in that image. Every face will be converted into 128D face descriptors. "
|
||||||
"If num_jitters>1 then each face will be randomly jittered slightly num_jitters times, each run through the 128D projection, and the average used as the face descriptor. "
|
"If num_jitters>1 then each face will be randomly jittered slightly num_jitters times, each run through the 128D projection, and the average used as the face descriptor. "
|
||||||
"Optionally allows to override default padding of 0.25 around the face."
|
"Optionally allows to override default padding of 0.25 around the face."
|
||||||
|
)
|
||||||
|
.def("compute_face_descriptor", &face_recognition_model_v1::batch_compute_face_descriptors_from_aligned_images,
|
||||||
|
py::arg("batch_img"), py::arg("num_jitters")=0,
|
||||||
|
"Takes an array of aligned images of faces of size 150_x_150."
|
||||||
|
"Note that the alignment should be done in the same way dlib.get_face_chip does it."
|
||||||
|
"Every face will be converted into 128D face descriptors. "
|
||||||
|
"If num_jitters>1 then each face will be randomly jittered slightly num_jitters times, each run through the 128D projection, and the average used as the face descriptor. "
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue