mirror of https://github.com/davisking/dlib.git
Add basic image io and remove python C-API refs from numpy_returns.cpp (#1258)
* Fixed reference count issue * Fixed refcount issue in Python dlib.jitter_image and dlib.get_face_chips * Consolidation of https://github.com/davisking/dlib/pull/1249 * Fixed build issue * Fixed: Paths in a pytest file should be relative to dlib root * Skip numpy return tests for Python 2.7 or if Numpy is not installed * Enabled numpy returns tests on Python 2.7 using cPickle.dumpspull/1265/head
parent
d7dfd8ad26
commit
e8faced822
@ -0,0 +1,59 @@
|
||||
#!/usr/bin/python
|
||||
# The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
|
||||
#
|
||||
# This example program shows how to find frontal human faces in a webcam stream using OpenCV.
|
||||
# It is also meant to demonstrate that rgb images from Dlib can be used with opencv by just
|
||||
# swapping the Red and Blue channels.
|
||||
#
|
||||
# You can run this program and see the detections from your webcam by executing the
|
||||
# following command:
|
||||
# ./opencv_face_detection.py
|
||||
#
|
||||
# This face detector is made using the now classic Histogram of Oriented
|
||||
# Gradients (HOG) feature combined with a linear classifier, an image
|
||||
# pyramid, and sliding window detection scheme. This type of object detector
|
||||
# is fairly general and capable of detecting many types of semi-rigid objects
|
||||
# in addition to human faces. Therefore, if you are interested in making
|
||||
# your own object detectors then read the train_object_detector.py example
|
||||
# program.
|
||||
#
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Compiling dlib should work on any operating system so long as you have
|
||||
# CMake installed. On Ubuntu, this can be done easily by running the
|
||||
# command:
|
||||
# sudo apt-get install cmake
|
||||
#
|
||||
# Also note that this example requires Numpy which can be installed
|
||||
# via the command:
|
||||
# pip install numpy
|
||||
|
||||
import sys
|
||||
import dlib
|
||||
import cv2
|
||||
|
||||
detector = dlib.get_frontal_face_detector()
|
||||
cam = cv2.VideoCapture(0)
|
||||
color_green = (0,255,0)
|
||||
line_width = 3
|
||||
while True:
|
||||
ret_val, img = cam.read()
|
||||
rgb_image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
||||
dets = detector(rgb_image)
|
||||
for det in dets:
|
||||
cv2.rectangle(img,(det.left(), det.top()), (det.right(), det.bottom()), color_green, line_width)
|
||||
cv2.imshow('my webcam', img)
|
||||
if cv2.waitKey(1) == 27:
|
||||
break # esc to quit
|
||||
cv2.destroyAllWindows()
|
@ -1,3 +1,2 @@
|
||||
scikit-image>=0.9.3
|
||||
opencv-python
|
||||
numpy
|
||||
|
@ -1,59 +0,0 @@
|
||||
#include "opaque_types.h"
|
||||
#include <dlib/python.h>
|
||||
#include "dlib/pixel.h"
|
||||
#include <dlib/image_transforms.h>
|
||||
|
||||
using namespace dlib;
|
||||
using namespace std;
|
||||
namespace py = pybind11;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
py::list get_jitter_images(py::object img, size_t num_jitters = 1, bool disturb_colors = false)
|
||||
{
|
||||
throw dlib::error("jitter_image is only supported if you compiled dlib with numpy installed!");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
py::list get_face_chips (
|
||||
py::object img,
|
||||
const std::vector<full_object_detection>& faces,
|
||||
size_t size = 150,
|
||||
float padding = 0.25
|
||||
)
|
||||
{
|
||||
throw dlib::error("get_face_chips is only supported if you compiled dlib with numpy installed!");
|
||||
}
|
||||
|
||||
py::object get_face_chip (
|
||||
py::object img,
|
||||
const full_object_detection& face,
|
||||
size_t size = 150,
|
||||
float padding = 0.25
|
||||
)
|
||||
{
|
||||
throw dlib::error("get_face_chip is only supported if you compiled dlib with numpy installed!");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
void bind_numpy_returns(py::module &m)
|
||||
{
|
||||
m.def("jitter_image", &get_jitter_images,
|
||||
"Takes an image and returns a list of jittered images."
|
||||
"The returned list contains num_jitters images (default is 1)."
|
||||
"If disturb_colors is set to True, the colors of the image are disturbed (default is False)",
|
||||
py::arg("img"), py::arg("num_jitters")=1, py::arg("disturb_colors")=false
|
||||
);
|
||||
|
||||
m.def("get_face_chip", &get_face_chip,
|
||||
"Takes an image and a full_object_detection that references a face in that image and returns the face as a Numpy array representing the image. The face will be rotated upright and scaled to 150x150 pixels or with the optional specified size and padding.",
|
||||
py::arg("img"), py::arg("face"), py::arg("size")=150, py::arg("padding")=0.25
|
||||
);
|
||||
|
||||
m.def("get_face_chips", &get_face_chips,
|
||||
"Takes an image and a full_object_detections object that reference faces in that image and returns the faces as a list of Numpy arrays representing the image. The faces will be rotated upright and scaled to 150x150 pixels or with the optional specified size and padding.",
|
||||
py::arg("img"), py::arg("faces"), py::arg("size")=150, py::arg("padding")=0.25
|
||||
);
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/python
|
||||
# The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
|
||||
#
|
||||
# This utility generates the test data required for the tests contained in test_numpy_returns.py
|
||||
#
|
||||
# Also note that this utility requires Numpy which can be installed
|
||||
# via the command:
|
||||
# pip install numpy
|
||||
import sys
|
||||
import dlib
|
||||
import numpy as np
|
||||
import utils
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print(
|
||||
"Call this program like this:\n"
|
||||
" ./generate_numpy_returns_test_data.py shape_predictor_5_face_landmarks.dat\n"
|
||||
"You can download a trained facial shape predictor from:\n"
|
||||
" http://dlib.net/files/shape_predictor_5_face_landmarks.dat.bz2\n")
|
||||
exit()
|
||||
|
||||
|
||||
detector = dlib.get_frontal_face_detector()
|
||||
predictor = dlib.shape_predictor(sys.argv[1])
|
||||
|
||||
img = dlib.load_rgb_image("../../../examples/faces/Tom_Cruise_avp_2014_4.jpg")
|
||||
dets = detector(img)
|
||||
shape = predictor(img, dets[0])
|
||||
|
||||
utils.save_pickled_compatible(shape, "shape.pkl")
|
||||
|
||||
face_chip = dlib.get_face_chip(img, shape)
|
||||
np.save("test_face_chip", face_chip)
|
Binary file not shown.
@ -0,0 +1,66 @@
|
||||
import sys
|
||||
import pickle
|
||||
|
||||
import dlib
|
||||
import pytest
|
||||
|
||||
import utils
|
||||
|
||||
# Paths are relative to dlib root
|
||||
image_path = "examples/faces/Tom_Cruise_avp_2014_4.jpg"
|
||||
shape_path = "tools/python/test/shape.pkl"
|
||||
face_chip_path = "tools/python/test/test_face_chip.npy"
|
||||
|
||||
def get_test_image_and_shape():
|
||||
img = dlib.load_rgb_image(image_path)
|
||||
shape = utils.load_pickled_compatible(shape_path)
|
||||
return img, shape
|
||||
|
||||
def get_test_face_chips():
|
||||
rgb_img, shape = get_test_image_and_shape()
|
||||
shapes = dlib.full_object_detections()
|
||||
shapes.append(shape)
|
||||
return dlib.get_face_chips(rgb_img, shapes)
|
||||
|
||||
def get_test_face_chip():
|
||||
rgb_img, shape = get_test_image_and_shape()
|
||||
return dlib.get_face_chip(rgb_img, shape)
|
||||
|
||||
# The tests below will be skipped if Numpy is not installed
|
||||
@pytest.mark.skipif(not utils.is_numpy_installed(), reason="requires numpy")
|
||||
def test_get_face_chip():
|
||||
import numpy
|
||||
face_chip = get_test_face_chip()
|
||||
expected = numpy.load(face_chip_path)
|
||||
assert numpy.array_equal(face_chip, expected)
|
||||
|
||||
@pytest.mark.skipif(not utils.is_numpy_installed(), reason="requires numpy")
|
||||
def test_get_face_chips():
|
||||
import numpy
|
||||
face_chips = get_test_face_chips()
|
||||
expected = numpy.load(face_chip_path)
|
||||
assert numpy.array_equal(face_chips[0], expected)
|
||||
|
||||
@pytest.mark.skipif(not utils.is_numpy_installed(), reason="requires numpy")
|
||||
def test_regression_issue_1220_get_face_chip():
|
||||
"""
|
||||
Memory leak in Python get_face_chip
|
||||
https://github.com/davisking/dlib/issues/1220
|
||||
"""
|
||||
face_chip = get_test_face_chip()
|
||||
# we expect two references:
|
||||
# 1.) the local variable
|
||||
# 2.) the temporary passed to getrefcount
|
||||
assert sys.getrefcount(face_chip) == 2
|
||||
|
||||
@pytest.mark.skipif(not utils.is_numpy_installed(), reason="requires numpy")
|
||||
def test_regression_issue_1220_get_face_chips():
|
||||
"""
|
||||
Memory leak in Python get_face_chip
|
||||
https://github.com/davisking/dlib/issues/1220
|
||||
"""
|
||||
face_chips = get_test_face_chips()
|
||||
count = sys.getrefcount(face_chips)
|
||||
assert count == 2
|
||||
count = sys.getrefcount(face_chips[0])
|
||||
assert count == 2
|
@ -0,0 +1,48 @@
|
||||
import pkgutil
|
||||
import sys
|
||||
|
||||
def save_pickled_compatible(obj_to_pickle, file_name):
|
||||
'''
|
||||
Save an object to the specified file in a backward compatible
|
||||
way for Pybind objects. See:
|
||||
http://pybind11.readthedocs.io/en/stable/advanced/classes.html#pickling-support
|
||||
and https://github.com/pybind/pybind11/issues/271
|
||||
'''
|
||||
try:
|
||||
import cPickle as pickle # Use cPickle on Python 2.7
|
||||
except ImportError:
|
||||
import pickle
|
||||
data = pickle.dumps(obj_to_pickle, 2)
|
||||
with open(file_name, "wb") as handle:
|
||||
handle.write(data)
|
||||
|
||||
def load_pickled_compatible(file_name):
|
||||
'''
|
||||
Loads a pickled object from the specified file
|
||||
'''
|
||||
try:
|
||||
import cPickle as pickle # Use cPickle on Python 2.7
|
||||
except ImportError:
|
||||
import pickle
|
||||
|
||||
with open(file_name, "rb") as handle:
|
||||
data = handle.read()
|
||||
if not is_python3():
|
||||
return pickle.loads(data)
|
||||
else:
|
||||
return pickle.loads(data, encoding="bytes")
|
||||
|
||||
def is_numpy_installed():
|
||||
'''
|
||||
Returns True if Numpy is installed otherwise False
|
||||
'''
|
||||
if pkgutil.find_loader("numpy"):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def is_python3():
|
||||
'''
|
||||
Returns True if using Python 3 or above, otherwise False
|
||||
'''
|
||||
return sys.version_info >= (3, 0)
|
Loading…
Reference in new issue