diff --git a/python_examples/face_detector_scores_idx.py b/python_examples/face_detector_scores_idx.py new file mode 100644 index 000000000..4156bfcb1 --- /dev/null +++ b/python_examples/face_detector_scores_idx.py @@ -0,0 +1,13 @@ + +from PIL import Image +import numpy as np +import dlib + +img = np.array(Image.open('../examples/faces/2008_002506.jpg')) +detector = dlib.get_frontal_face_detector() + +dets, scores, idx = detector.run(img, 1) + +for i, d in enumerate(dets): + print d, scores[i], idx[i] + diff --git a/tools/python/src/object_detection.cpp b/tools/python/src/object_detection.cpp index 6efd9c6ab..09a785c0c 100644 --- a/tools/python/src/object_detection.cpp +++ b/tools/python/src/object_detection.cpp @@ -342,7 +342,7 @@ ensures \n\ "Loads an object detector from a file that contains the output of the \n\ train_simple_object_detector() routine or a serialized C++ object of type\n\ object_detector>>.") - .def("__call__", run_detector_with_upscale, (arg("image"), arg("upsample_num_times")=0), + .def("__call__", run_detector_with_upscale2, (arg("image"), arg("upsample_num_times")=0), "requires \n\ - image is a numpy ndarray containing either an 8bit grayscale or RGB \n\ image. \n\ @@ -350,6 +350,18 @@ object_detector>>.") ensures \n\ - This function runs the object detector on the input image and returns \n\ a list of detections. \n\ + - Upsamples the image upsample_num_times before running the basic \n\ + detector. If you don't know how many times you want to upsample then \n\ + don't provide a value for upsample_num_times and an appropriate \n\ + default will be used.") + .def("run", run_rect_detector, (arg("image"), arg("upsample_num_times")), +"requires \n\ + - image is a numpy ndarray containing either an 8bit grayscale or RGB \n\ + image. \n\ + - upsample_num_times >= 0 \n\ +ensures \n\ + - This function runs the object detector on the input image and returns \n\ + a tuple of (list of detections, list of scores, list of weight_indices). \n\ - Upsamples the image upsample_num_times before running the basic \n\ detector. If you don't know how many times you want to upsample then \n\ don't provide a value for upsample_num_times and an appropriate \n\ diff --git a/tools/python/src/simple_object_detector_py.h b/tools/python/src/simple_object_detector_py.h index ac00ce6fc..0bd103bff 100644 --- a/tools/python/src/simple_object_detector_py.h +++ b/tools/python/src/simple_object_detector_py.h @@ -13,20 +13,48 @@ namespace dlib { typedef object_detector > > simple_object_detector; - inline std::vector run_detector_with_upscale ( + inline void split_rect_detections ( + std::vector& rect_detections, + std::vector& rectangles, + std::vector& detection_confidences, + std::vector& weight_indices + ) + { + rectangles.clear(); + detection_confidences.clear(); + weight_indices.clear(); + + for (unsigned long i = 0; i < rect_detections.size(); ++i) + { + rectangles.push_back(rect_detections[i].rect); + detection_confidences.push_back(rect_detections[i].detection_confidence); + weight_indices.push_back(rect_detections[i].weight_index); + } + } + + + inline std::vector run_detector_with_upscale1 ( dlib::simple_object_detector& detector, boost::python::object img, - const unsigned int upsampling_amount + const unsigned int upsampling_amount, + std::vector& detection_confidences, + std::vector& weight_indices ) { pyramid_down<2> pyr; + std::vector rectangles; + std::vector rect_detections; + if (is_gray_python_image(img)) { array2d temp; if (upsampling_amount == 0) { - return detector(numpy_gray_image(img)); + detector(numpy_gray_image(img), rect_detections, 0.0); + split_rect_detections(rect_detections, rectangles, + detection_confidences, weight_indices); + return rectangles; } else { @@ -38,10 +66,14 @@ namespace dlib pyramid_up(temp); } - std::vector res = detector(temp); - for (unsigned long i = 0; i < res.size(); ++i) - res[i] = pyr.rect_down(res[i], upsampling_amount); - return res; + detector(temp, rect_detections, 0.0); + for (unsigned long i = 0; i < rect_detections.size(); ++i) + rect_detections[i].rect = pyr.rect_down(rect_detections[i].rect, + upsampling_amount); + split_rect_detections(rect_detections, rectangles, + detection_confidences, weight_indices); + + return rectangles; } } else if (is_rgb_python_image(img)) @@ -49,7 +81,10 @@ namespace dlib array2d temp; if (upsampling_amount == 0) { - return detector(numpy_rgb_image(img)); + detector(numpy_rgb_image(img), rect_detections, 0.0); + split_rect_detections(rect_detections, rectangles, + detection_confidences, weight_indices); + return rectangles; } else { @@ -61,10 +96,14 @@ namespace dlib pyramid_up(temp); } - std::vector res = detector(temp); - for (unsigned long i = 0; i < res.size(); ++i) - res[i] = pyr.rect_down(res[i], upsampling_amount); - return res; + detector(temp, rect_detections, 0.0); + for (unsigned long i = 0; i < rect_detections.size(); ++i) + rect_detections[i].rect = pyr.rect_down(rect_detections[i].rect, + upsampling_amount); + split_rect_detections(rect_detections, rectangles, + detection_confidences, weight_indices); + + return rectangles; } } else @@ -73,6 +112,37 @@ namespace dlib } } + inline std::vector run_detector_with_upscale2 ( + dlib::simple_object_detector& detector, + boost::python::object img, + const unsigned int upsampling_amount + ) + { + std::vector detection_confidences; + std::vector weight_indices; + + return run_detector_with_upscale1(detector, img, upsampling_amount, + detection_confidences, weight_indices); + } + + inline boost::python::tuple run_rect_detector ( + dlib::simple_object_detector& detector, + boost::python::object img, + const unsigned int upsampling_amount) + { + boost::python::tuple t; + + std::vector detection_confidences; + std::vector weight_indices; + std::vector rectangles; + + rectangles = run_detector_with_upscale1(detector, img, upsampling_amount, + detection_confidences, weight_indices); + + return boost::python::make_tuple(rectangles, + detection_confidences, weight_indices); + } + struct simple_object_detector_py { simple_object_detector detector; @@ -82,11 +152,18 @@ namespace dlib simple_object_detector_py(simple_object_detector& _detector, unsigned int _upsampling_amount) : detector(_detector), upsampling_amount(_upsampling_amount) {} - std::vector run_detector1 (boost::python::object img, const unsigned int upsampling_amount_) - { return run_detector_with_upscale(detector, img, upsampling_amount_); } + std::vector run_detector1 (boost::python::object img, + const unsigned int upsampling_amount_) + { + return run_detector_with_upscale2(detector, img, upsampling_amount_); + } std::vector run_detector2 (boost::python::object img) - { return run_detector_with_upscale(detector, img, upsampling_amount); } + { + return run_detector_with_upscale2(detector, img, upsampling_amount); + } + + }; }