24 using ptr = std::shared_ptr< detected_face >;
30 cv::Rect
const& depth_location = cv::Rect{},
42 _age = (_age == -1) ? value : 0.95f * _age + 0.05f * value;
50 _male_score += value - 0.5f;
52 _female_score += 0.5f -
value;
56 int get_age()
const {
return static_cast< int >( std::floor( _age + 0.5f )); }
57 bool is_male()
const {
return( _male_score > _female_score ); }
66 InferenceEngine::Core
_ie;
72 std::shared_ptr< atomic_objects_in_frame >
_objects;
82 "face-detection-adas-0001.xml",
88 "age-gender-recognition-retail-0013.xml",
96 release_background_worker();
109 LOG(
INFO) <<
"Loading CPU extensions...";
113 _ie.AddExtension(std::make_shared< openvino::Extensions::Cpu::CpuExtensions >(), device_name);
116 _face_detector.
load_into( _ie, device_name);
117 _age_detector.
load_into( _ie, device_name);
127 cv::Rect
const & depth_bbox,
128 float * p_mean_depth )
138 int const top = depth_bbox.y;
139 int const bot = top + depth_bbox.height;
140 int const left = depth_bbox.x;
141 int const right = left + depth_bbox.width;
144 int center_x = (left +
right) / 2;
145 int center_index = (top + bot) / 2 * depth_width + center_x;
146 for(
int d = 1; !pdw[center_index] &&
d < 10; ++
d )
148 if( pdw[center_index + d] ) center_index +=
d;
149 if( pdw[center_index - d] ) center_index -=
d;
150 if( pdw[center_index + depth_width] ) center_index +=
depth_width;
151 if( pdw[center_index - depth_width] ) center_index -=
depth_width;
153 if( !pdw[center_index] )
159 float const d_center = pdw[center_index] *
depth_scale;
163 float const d_far_threshold = d_center + 0.2f;
164 float const d_near_threshold = std::max( d_center - 0.5
f, 0.001
f );
169 float total_luminance = 0;
170 float total_depth = 0;
171 unsigned pixel_count = 0;
172 #pragma omp parallel for schedule(dynamic) //Using OpenMP to try to parallelise the loop 173 for(
int y = top;
y < bot; ++
y )
175 auto depth_pixel_index =
y * depth_width +
left;
176 for(
int x = left;
x <
right; ++
x, ++depth_pixel_index )
179 auto d = depth_scale * pdw[depth_pixel_index];
182 if( d >= d_near_threshold && d <= d_far_threshold )
185 auto const coffset = depth_pixel_index * color_bpp;
186 auto const pc = &pcb[coffset];
190 total_luminance += 0.2989f *
r + 0.5870f * g + 0.1140f *
b;
199 *p_mean_depth = pixel_count ? total_depth / pixel_count : 0;
200 return pixel_count ? total_luminance / pixel_count : 1;
211 df = fs.get_depth_frame();
223 LOG(ERROR) << get_context(fs) <<
"color format must be RGB8; it's " << cf.
get_profile().
format();
231 LOG(ERROR) << get_context(fs) <<
"depth format must be Z16; it's " << df.
get_profile().
format();
238 get_trinsics( cf, df, color_intrin, depth_intrin, color_extrin, depth_extrin );
242 cv::Mat
image( color_intrin.
height, color_intrin.
width, CV_8UC3, const_cast<void *>(cf.
get_data()), cv::Mat::AUTO_STEP );
243 _face_detector.
enqueue( image );
249 for(
auto &&
result : results )
251 cv::Rect
rect =
result.location & cv::Rect( 0, 0, image.cols, image.rows );
258 float depth = 0, intensity = 1;
262 rs2::rect depth_bbox = project_rect_to_depth(
263 rs2::rect { float( rect.x ), float( rect.y ), float( rect.width ), float( rect.height ) },
265 color_intrin, depth_intrin, color_extrin, depth_extrin
268 if( depth_bbox == depth_bbox.
intersection(
rs2::rect { 0.f, 0.f, float( depth_intrin.width ), float( depth_intrin.height) } ) )
270 depth_rect = cv::Rect(
int( depth_bbox.
x ),
int( depth_bbox.
y ),
int( depth_bbox.
w ),
int( depth_bbox.
h ) );
271 intensity = calc_face_attrs( cf, df, depth_rect, &depth );
275 LOG(
DEBUG) << get_context(fs) <<
"depth_bbox is no good!";
282 float intensity_change = face ? std::abs( intensity - face->get_intensity() ) / face->get_intensity() : 1;
283 float depth_change = ( face && face->get_depth() ) ? std::abs( depth - face->get_depth() ) / face->get_depth() : 0;
285 if( intensity_change > 0.07f || depth_change > 0.2f )
288 float age = 0, maleProb = 0.5;
290 cv::Mat face_image =
image(
292 & cv::Rect( 0, 0, image.cols, image.rows ) );
293 _age_detector.
enqueue( face_image );
295 _age_detector.
wait();
296 auto age_gender = _age_detector[0];
297 age = age_gender.age;
298 maleProb = age_gender.maleProb;
300 face = std::make_shared< detected_face >( _id++, rect, maleProb, age, depth_rect, intensity,
depth );
304 face->move( rect, depth_rect, intensity, depth );
307 _faces.push_back( face );
311 LOG(ERROR) << get_context(fs) <<
"Unhandled exception!!!";
315 for(
auto &&
object : _faces )
319 rs2::rect bbox { float( loc.x ), float( loc.y ), float( loc.width ), float( loc.height ) };
321 rs2::rect normalized_depth_bbox = normalized_color_bbox;
324 cv::Rect
const & depth_loc =
face->get_depth_location();
325 rs2::rect depth_bbox { float( depth_loc.x ), float( depth_loc.y ), float( depth_loc.width ), float( depth_loc.height ) };
328 objects.emplace_back(
331 normalized_color_bbox,
332 normalized_depth_bbox,
337 std::lock_guard< std::mutex >
lock( _objects->mutex );
338 if( is_pb_enabled() )
340 if( _objects->sensor_is_on )
341 _objects->swap( objects );
348 catch(
const std::exception &
e )
350 LOG(ERROR) << get_context(fs) << e.what();
354 LOG(ERROR) << get_context(fs) <<
"Unhandled exception caught in openvino_face_detection";
364 std::lock_guard< std::mutex >
lock( _objects->mutex );
372 static auto it = post_processing_filters_list::register_filter< openvino_face_detection >(
"Face Detection : OpenVINO" );
static const textual_icon lock
openvino_helpers::age_gender_detection _age_detector
GLboolean GLboolean GLboolean b
~openvino_face_detection()
void on_processing_block_enable(bool e) override
float calc_intensity(const cv::Mat &src)
GLuint const GLchar * name
GLdouble GLdouble GLdouble top
detected_object(size_t id, std::string const &label, cv::Rect const &location, cv::Rect const &depth_location=cv::Rect{}, float intensity=1, float depth=0)
rect intersection(const rect &other) const
std::list< detected_object::ptr > detected_objects
stream_profile get_profile() const
int get_bytes_per_pixel() const
GLint GLint GLsizei GLsizei GLsizei depth
LOG(INFO)<< "Log message to default logger"
const void * get_data() const
std::string stream_name() const
GLsizei const GLchar *const * string
std::array< point3d, 4 > object
void submit_request() override
std::shared_ptr< atomic_objects_in_frame > _objects
GLenum GLenum GLsizei void * image
video_frame get_color_frame() const
std::shared_ptr< atomic_objects_in_frame > detected_objects
cv::Rect adjust_face_bbox(cv::Rect const &r, float enlarge_coefficient=1, float dx_coefficient=1, float dy_coefficient=1)
void worker_start() override
void load_into(InferenceEngine::Core &ie, const std::string &deviceName)
void start(rs2::subdevice_model &model) override
cv::Rect const & get_location() const
virtual void on_processing_block_enable(bool e)
std::vector< object_in_frame > objects_in_frame
void update_age(float value)
void worker_body(rs2::frame f) override
void update_gender(float value)
InferenceEngine::Core _ie
Cross-stream extrinsics: encodes the topology describing how the different devices are oriented...
rs2_format format() const
void start(rs2::subdevice_model &model) override
void enqueue(const cv::Mat &face)
detected_object::ptr find_object(cv::Rect rect, detected_objects const &objects)
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
rect normalize(const rect &normalize_to) const
static float calc_face_attrs(const rs2::video_frame &cf, const rs2::depth_frame &df, cv::Rect const &depth_bbox, float *p_mean_depth)
openvino_helpers::object_detection _face_detector
openvino_face_detection(std::string const &name)
void enqueue(const cv::Mat &frame)
void submit_request() override
std::shared_ptr< detected_face > ptr
GLenum GLuint GLint GLenum face
std::vector< Result > fetch_results()
openvino_helpers::detected_objects _faces
detected_face(size_t id, cv::Rect const &location, float male_prob, float age, cv::Rect const &depth_location=cv::Rect{}, float intensity=1, float depth=0)
std::string to_string(T value)