rs-face-vino.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2019 Intel Corporation. All Rights Reserved.
3 
4 #include <librealsense2/rs.hpp> // Include RealSense Cross Platform API
5 
6 #include "cv-helpers.hpp" // frame_to_mat
7 
10 
11 #include <easylogging++.h>
12 #ifdef BUILD_SHARED_LIBS
13 // With static linkage, ELPP is initialized by librealsense, so doing it here will
14 // create errors. When we're using the shared .so/.dll, the two are separate and we have
15 // to initialize ours if we want to use the APIs!
17 #endif
18 
19 
20 namespace openvino = InferenceEngine;
21 
22 
23 int main(int argc, char * argv[]) try
24 {
25  el::Configurations conf;
26  conf.set( el::Level::Global, el::ConfigurationType::Format, "[%level] %msg" );
27  //conf.set( el::Level::Debug, el::ConfigurationType::Enabled, "false" );
28  el::Loggers::reconfigureLogger( "default", conf );
29  rs2::log_to_console( RS2_LOG_SEVERITY_WARN ); // only warnings (and above) should come through
30 
31  // Declare RealSense pipeline, encapsulating the actual device and sensors
33  pipe.start();
35 
36  // Start the inference engine, needed to accomplish anything. We also add a CPU extension, allowing
37  // us to run the inference on the CPU. A GPU solution may be possible but, at least without a GPU,
38  // a CPU-bound process is faster. To change to GPU, use "GPU" instead (and remove AddExtension()):
39  openvino::Core engine;
40  openvino_helpers::error_listener error_listener;
41  engine.SetLogCallback( error_listener );
42  std::string const device_name { "CPU" };
43 
44 #ifdef OPENVINO2019
45  engine.AddExtension( std::make_shared< openvino::Extensions::Cpu::CpuExtensions >(), device_name );
46 #endif
47 
49  "face-detection-adas-0001.xml",
50  0.5 // Probability threshold -- anything with less confidence will be thrown out
51  );
52  try
53  {
54  faceDetector.load_into( engine, device_name );
55  }
56  catch( const std::exception & e )
57  {
58  // The model files should have been downloaded automatically by CMake into build/wrappers/openvino/face,
59  // which is also where Visual Studio runs the sample from. However, you may need to copy these two files:
60  // face-detection-adas-0001.bin
61  // face-detection-adas-0001.xml
62  // Into the local directory where you run from (or change the path given in the ctor above)
63  LOG(ERROR) << "Failed to load model files:\n " << e.what();
64  LOG(INFO) << "Please copy the model files into the working directory from which this sample is run";
65  return EXIT_FAILURE;
66  }
67 
68 
69  const auto window_name = "OpenVINO face detection sample";
70  cv::namedWindow( window_name, cv::WINDOW_AUTOSIZE );
71 
72  bool first_frame = true;
73  cv::Mat prev_image;
75  size_t id = 0;
76 
77  while( cv::getWindowProperty( window_name, cv::WND_PROP_AUTOSIZE ) >= 0 )
78  {
79  // Wait for the next set of frames
80  auto data = pipe.wait_for_frames();
81  // Make sure the frames are spatially aligned
82  data = align_to.process( data );
83 
84  auto color_frame = data.get_color_frame();
85  auto depth_frame = data.get_depth_frame();
86 
87  // If we only received a new depth frame, but the color did not update, continue
88  static uint64 last_frame_number = 0;
89  if( color_frame.get_frame_number() == last_frame_number )
90  continue;
91  last_frame_number = color_frame.get_frame_number();
92 
93  auto image = frame_to_mat( color_frame );
94 
95  // We process the previous frame so if this is our first then queue it and continue
96  if( first_frame )
97  {
98  faceDetector.enqueue( image );
99  faceDetector.submit_request();
100  first_frame = false;
101  prev_image = image;
102  continue;
103  }
104 
105  // Wait for the results of the previous frame we enqueued: we're going to process these
106  faceDetector.wait();
107  auto const results = faceDetector.fetch_results();
108 
109  // Enqueue the current frame so we'd get the results when the next frame comes along!
110  faceDetector.enqueue( image );
111  faceDetector.submit_request();
112 
113  openvino_helpers::detected_objects prev_faces { std::move( faces ) };
114  faces.clear();
115  for( auto const & result : results )
116  {
117  cv::Rect rect = result.location;
118  rect = rect & cv::Rect( 0, 0, image.cols, image.rows );
119  auto face_ptr = openvino_helpers::find_object( rect, prev_faces );
120  if( !face_ptr )
121  // New face
122  face_ptr = std::make_shared< openvino_helpers::detected_object >( id++, std::string(), rect );
123  else
124  // Existing face; just update its parameters
125  face_ptr->move( rect );
126  faces.push_back( face_ptr );
127  }
128 
129  // Keep this image so we can actually process pieces of it once we have the results
130  prev_image = image;
131 
132  // Display the results (from the last frame) as rectangles on top (of the current frame)
133  for( auto && face : faces )
134  {
135  cv::Scalar color( 255, 255, 255 ); // BGR
136  auto r = face->get_location();
137  cv::rectangle( image, r, color );
138 
139  // Get a very crude approximation (not aligned) of the center in the depth frame, and output the distance to it
140  auto center_x = r.x + r.width / 2;
141  auto center_y = r.y + r.height / 2;
142  auto d = depth_frame.get_distance( center_x, center_y );
143  if( d )
144  {
145  std::ostringstream ss;
146  ss << std::setprecision( 2 ) << d;
147  ss << " m";
148  cv::putText( image, ss.str(), cv::Point( r.x + 5, r.y + r.height - 5 ), cv::FONT_HERSHEY_SIMPLEX, 0.3, color );
149  }
150  }
151 
152  imshow( window_name, image );
153  if( cv::waitKey( 1 ) >= 0 )
154  break;
155  }
156 
157  return EXIT_SUCCESS;
158 }
159 catch (const rs2::error & e)
160 {
161  LOG(ERROR) << "Caught RealSense exception from " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n " << e.what();
162  return EXIT_FAILURE;
163 }
164 catch (const std::exception& e)
165 {
166  LOG(ERROR) << "Unknown exception caught: " << e.what();
167  return EXIT_FAILURE;
168 }
169 
frameset wait_for_frames(unsigned int timeout_ms=RS2_DEFAULT_TIMEOUT) const
static Logger * reconfigureLogger(Logger *logger, const Configurations &configurations)
Reconfigures specified logger with new configurations.
int main(int argc, char *argv[])
std::list< detected_object::ptr > detected_objects
void set(Level level, ConfigurationType configurationType, const std::string &value)
Sets value of configuration for specified level.
LOG(INFO)<< "Log message to default logger"
GLsizei const GLchar *const * string
d
Definition: rmse.py:171
e
Definition: rmse.py:177
GLenum GLenum GLsizei void * image
const std::string & get_failed_args() const
Definition: rs_types.hpp:117
Determines format of logging corresponding level and logger.
#define INITIALIZE_EASYLOGGINGPP
GLdouble GLdouble r
frameset process(frameset frames)
void load_into(InferenceEngine::Core &ie, const std::string &deviceName)
void log_to_console(rs2_log_severity min_severity)
Definition: rs.hpp:19
Thread-safe Configuration repository.
Definition: example.hpp:70
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
Generic level that represents all the levels. Useful when setting global configuration for all levels...
#define INFO(msg)
Definition: catch.hpp:17429
std::array< float, 3 > color
Definition: model-views.h:449
void enqueue(const cv::Mat &frame)
pipeline_profile start()
GLuint64EXT * result
Definition: glext.h:10921
static cv::Mat frame_to_mat(const rs2::frame &f)
Definition: cv-helpers.hpp:11
const std::string & get_failed_function() const
Definition: rs_types.hpp:112
Definition: parser.hpp:150
GLenum GLuint GLint GLenum face
Definition: glext.h:3377
::geometry_msgs::Point_< std::allocator< void > > Point
Definition: Point.h:57
std::vector< Result > fetch_results()


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:40