当前位置:   article > 正文

yolov3-tiny+realsense d455获取目标深度信息及位置信息_d455深度相机读取数据流

d455深度相机读取数据流

参考:链接:https://www.freesion.com/article/3585644384/,根据内参获取真实位置
///       https://blog.csdn.net/SFM2020/article/details/84591758 

yolov3-tiny下载:GitHub - smarthomefans/darknet-test: darknet 测试

文件结构

 .h文件

  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <chrono>
  5. #include <mutex> //定义了C++11标准中的一些互斥访问的类与方法
  6. #include <thread> //线程头文件
  7. #include <opencv2/opencv.hpp>
  8. #include <opencv2/core/core.hpp>
  9. #include <opencv2/imgproc/types_c.h>
  10. #include <opencv2/imgproc/imgproc.hpp>
  11. #include <opencv2/highgui/highgui.hpp>
  12. #include <opencv2/objdetect/objdetect.hpp>
  13. #include <opencv2/dnn.hpp>
  14. #include <algorithm>
  15. #include<librealsense2/rs.hpp>
  16. #include<librealsense2/rsutil.h>
  17. using namespace std;
  18. using namespace cv;
  19. using namespace dnn;
  20. #define limit_L(a,b) (a-b>0)?(a-b):(0)
  21. #define limit_H(a,b,max) (a+b>max)?(max):(a+b)
  22. #define STREAM RS2_STREAM_DEPTH // rs2_stream is a types of data provided by RealSense device //
  23. #define FORMAT RS2_FORMAT_Z16 // rs2_format identifies how binary data is encoded within a frame //
  24. #define WIDTH 640 // Defines the number of columns for each frame or zero for auto resolve//
  25. #define HEIGHT 480 // Defines the number of lines for each frame or zero for auto resolve //
  26. #define FPS 30 // Defines the rate of frames per second //
  27. #define STREAM_INDEX 0 // Defines the stream index, used for multiple streams of the same type //
  28. #define HEIGHT_RATIO 20 // Defines the height ratio between the original frame to the new frame //
  29. #define WIDTH_RATIO 10 // Defines the width ratio between the original frame to the new frame //
  30. #define STREAM1 RS2_STREAM_COLOR // rs2_stream is a types of data provided by RealSense device //
  31. #define FORMAT1 RS2_FORMAT_RGB8 // rs2_format identifies how binary data is encoded within a frame //
  32. #define FPS1 30 // Defines the rate of frames per second //
  33. #define STREAM_INDEX 0 // Defines the stream index, used for multiple streams of the same type //
  34. // Remove the bounding boxes with low confidence using non-maxima suppression
  35. void postprocess(Mat& frame, const vector<Mat>& out);
  36. // Draw the predicted bounding box
  37. void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame);
  38. // Get the names of the output layers
  39. vector<String> getOutputsNames(const Net& net);
  40. void detect_camera(string modelWeights, string modelConfiguration, string classesFile);
  41. void postprocess(Mat& frame, const vector<Mat>& outs);
  42. void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame);
  43. vector<String> getOutputsNames(const Net& net);
  44. float get_depth_unit_value(const rs2_device* const dev);
  45. uint16_t get_color_depth(Mat color_c,rs2_intrinsics color_intri,Mat depth_c,int color_cols,int color_rows,int depth_err);
  46. struct color_point
  47. {
  48. int x;
  49. int y;
  50. double color;
  51. }color_Point;
  52. Mat image_yolov3,yolov3_depth;
  53. rs2_intrinsics color_intri_all;
  54. std::mutex mtx_yolo;

 .cpp文件

  1. #include "./include/realsense_yolo.h"
  2. vector<string> classes;
  3. int inpWidth = WIDTH; // Width of network's input image
  4. int inpHeight= HEIGHT; // Height of network's input image
  5. string dir="/home/user-e290/Desktop/depth_yolov3/files/";
  6. float confThreshold = 0.25; // Confidence threshold
  7. float nmsThreshold = 0.45; // Non-maximum suppression threshold
  8. string modelConfiguration = dir+"yolov3-tiny.cfg";
  9. string modelWeights = dir+"yolov3-tiny.weights";
  10. //string modelConfiguration = dir+"yolov3.cfg";
  11. //string modelWeights = dir+"yolov3.weights";
  12. string classesFile = dir+"coco.names";// "coco.names";
  13. void postprocess(Mat& frame, const vector<Mat>& outs)
  14. {
  15. vector<int> classIds;
  16. vector<float> confidences;
  17. vector<Rect> boxes;
  18. for (size_t pos_i = 0; pos_i < outs.size(); ++pos_i)
  19. {
  20. // Scan through all the bounding boxes output from the network and keep only the
  21. // ones with high confidence scores. Assign the box's class label as the class
  22. // with the highest score for the box.
  23. float* data = (float*)outs[pos_i].data;
  24. for (int pos_j = 0; pos_j < outs[pos_i].rows; ++pos_j, data += outs[pos_i].cols)
  25. {
  26. Mat scores = outs[pos_i].row(pos_j).colRange(5, outs[pos_i].cols);
  27. Point classIdPoint;
  28. double confidence;
  29. // Get the value and location of the maximum score
  30. minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
  31. if (confidence > confThreshold)
  32. {
  33. int centerX = (int)(data[0] * frame.cols);
  34. int centerY = (int)(data[1] * frame.rows);
  35. int width = (int)(data[2] * frame.cols);
  36. int height = (int)(data[3] * frame.rows);
  37. int left = centerX - width / 2;
  38. int top = centerY - height / 2;
  39. classIds.push_back(classIdPoint.x);
  40. confidences.push_back((float)confidence);
  41. boxes.push_back(Rect(left, top, width, height));
  42. }
  43. }
  44. }
  45. // Perform non maximum suppression to eliminate redundant overlapping boxes with
  46. // lower confidences
  47. vector<int> indices;
  48. NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);
  49. for (size_t i = 0; i < indices.size(); ++i)
  50. {
  51. int idx = indices[i];
  52. Rect box = boxes[idx];
  53. drawPred(classIds[idx], confidences[idx], box.x, box.y,
  54. box.x + box.width, box.y + box.height, frame);
  55. get_color_depth(frame,color_intri_all,yolov3_depth,box.x + box.width/2,box.y + box.height/2,20);
  56. }
  57. }
  58. // Get the names of the output layers
  59. vector<String> getOutputsNames(const Net& net)
  60. {
  61. static vector<String> names;
  62. if (names.empty())
  63. {
  64. //Get the indices of the output layers, i.e. the layers with unconnected outputs
  65. vector<int> outLayers = net.getUnconnectedOutLayers();
  66. //get the names of all the layers in the network
  67. vector<String> layersNames = net.getLayerNames();
  68. // Get the names of the output layers in names
  69. names.resize(outLayers.size());
  70. for (size_t get_i = 0; get_i < outLayers.size(); ++get_i)
  71. names[get_i] = layersNames[outLayers[get_i] - 1];
  72. }
  73. return names;
  74. }
  75. // Draw the predicted bounding box
  76. void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame)
  77. {
  78. //Draw a rectangle displaying the bounding box
  79. rectangle(frame, Point(left, top), Point(right, bottom), Scalar(255, 178, 50), 3);
  80. //Get the label for the class name and its confidence
  81. string label = format("%.2f", conf);
  82. if (!classes.empty())
  83. {
  84. CV_Assert(classId < (int)classes.size());
  85. label = classes[classId] + ":" + label;
  86. }
  87. //Display the label at the top of the bounding box
  88. int baseLine;
  89. Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
  90. top = max(top, labelSize.height);
  91. rectangle(frame, Point(left, top - round(1.5*labelSize.height)), Point(left + round(1.5*labelSize.width), top + baseLine), Scalar(255, 255, 255), FILLED);
  92. cv::putText(frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 0), 1);
  93. }
  94. //摄像头
  95. void detect_camera(string modelWeights, string modelConfiguration, string classesFile)
  96. {
  97. Net net = readNetFromDarknet(modelConfiguration, modelWeights);
  98. net.setPreferableBackend(DNN_BACKEND_OPENCV);
  99. net.setPreferableTarget(DNN_TARGET_CPU);
  100. Mat frame, blob;
  101. // Process frames.
  102. std::this_thread::sleep_for(std::chrono::seconds(3));
  103. while (1)
  104. {
  105. frame=image_yolov3;
  106. // std::this_thread::sleep_for(std::chrono:: milliseconds (10)); //添加
  107. if (frame.empty()) {
  108. cout << "Done processing !!!" << endl;
  109. std::this_thread::sleep_for(std::chrono::seconds(3));
  110. }
  111. else{
  112. // Create a 4D blob from a frame.
  113. blobFromImage(frame, blob, 1 / 255.0, cv::Size(inpWidth, inpHeight), Scalar(0, 0, 0), true, false);
  114. //Sets the input to the network
  115. net.setInput(blob);
  116. // Runs the forward pass to get output of the output layers
  117. vector<Mat> outs;
  118. net.forward(outs, getOutputsNames(net));
  119. // Remove the bounding boxes with low confidence
  120. postprocess(frame, outs);
  121. // Put efficiency information. The function getPerfProfile returns the overall time for inference(t) and the timings for each of the layers(in layersTimes)
  122. vector<double> layersTimes;
  123. double freq = getTickFrequency() / 1000;
  124. double t = net.getPerfProfile(layersTimes) / freq;
  125. string label = format("Inference time for a frame : %.2f ms", t);
  126. putText(frame, label, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255));
  127. // Write the frame with the detection boxes
  128. Mat detectedFrame;
  129. frame.convertTo(detectedFrame, CV_8U);
  130. mtx_yolo.lock();
  131. line(frame,cv::Point(frame.cols*0.05,frame.rows*0.5),cv::Point(frame.cols*0.95,frame.rows*0.5),cv::Scalar(0, 1, 0),2); // X轴
  132. line(frame,cv::Point(frame.cols*0.5,frame.rows*0.05),cv::Point(frame.cols*0.5,frame.rows*0.95),cv::Scalar(0, 1, 0),2); // Y轴
  133. putText(frame,"x",Point(frame.cols*0.95,frame.rows*0.48),FONT_HERSHEY_PLAIN,2,cv::Scalar(0, 1, 0),2);
  134. putText(frame,"y",Point(frame.cols*0.52,frame.rows*0.05),FONT_HERSHEY_PLAIN,2,cv::Scalar(0, 1, 0),2);
  135. putText(frame,"I",Point(frame.cols*0.75,frame.rows*0.25),FONT_HERSHEY_PLAIN,2,cv::Scalar(0, 1, 0),2);
  136. putText(frame,"II",Point(frame.cols*0.25,frame.rows*0.25),FONT_HERSHEY_PLAIN,2,cv::Scalar(0, 1, 0),2);
  137. putText(frame,"III",Point(frame.cols*0.25,frame.rows*0.75),FONT_HERSHEY_PLAIN,2,cv::Scalar(0, 1, 0),2);
  138. putText(frame,"IV",Point(frame.cols*0.75,frame.rows*0.75),FONT_HERSHEY_PLAIN,2,cv::Scalar(0, 1, 0),2);
  139. imshow("deep learning",frame);
  140. waitKey(10);
  141. mtx_yolo.unlock();
  142. }
  143. }
  144. }
  145. //
  146. /// date: 2021/09/28
  147. /// input: Mat depth_c 深度图,Mat color_c rgb图,rgb图color_cols列,rgb图color_rows行,depth_err像素偏移误差
  148. /// function: 根据输入的rgb图及rgb 行和列的位置取出深度图对应的值
  149. /// output: 深度信息
  150. /// 链接:https://www.freesion.com/article/3585644384/,根据内参获取真实位置
  151. /// https://blog.csdn.net/SFM2020/article/details/84591758
  152. //
  153. uint16_t get_color_depth(Mat color_c,rs2_intrinsics color_intri,Mat depth_c,int color_cols,int color_rows,int depth_err)
  154. {
  155. char str[10];//用于存放帧率的字符串
  156. uint16_t depth_sim=limit_depth*1000;
  157. int limit_left=0,limit_right=0,limit_up=0,limit_down=0;
  158. limit_left=limit_L(color_cols,depth_err);
  159. limit_right=limit_H(color_cols,depth_err,depth_c.cols);
  160. limit_up=limit_H(color_rows,depth_err,depth_c.rows);
  161. limit_down=limit_L(color_rows,depth_err);//(row,col)
  162. for(int get_i=limit_down;get_i<limit_up;get_i++){
  163. for(int get_j=limit_left;get_j<limit_right;get_j++){
  164. if(depth_c.at<uint16_t>(get_i,get_j)!=0)
  165. {
  166. if(depth_c.at<uint16_t>(get_i,get_j)<depth_sim)
  167. depth_sim=depth_c.at<uint16_t>(get_i,get_j);
  168. }
  169. }
  170. }
  171. Point target_xy_true;
  172. target_xy_true.x=(color_cols-color_intri.ppx)*depth_sim/color_intri.fx;//cols为x
  173. target_xy_true.y=(color_intri.ppy-color_rows)*depth_sim/color_intri.fy;//rows为y
  174. string text = "Dp=";
  175. sprintf(str, "%d", depth_sim);
  176. text += str;
  177. text +=" Px=";
  178. sprintf(str, "%d", target_xy_true.x);
  179. text += str;
  180. text +=" Py=";
  181. sprintf(str, "%d", target_xy_true.y);
  182. text += str;
  183. circle(color_c,cv::Point(color_cols,color_rows),16, Scalar(0.5,0.2,0),1,8,0);//点是绿色
  184. putText(color_c, text,cv::Point(color_cols,color_rows),cv::FONT_HERSHEY_COMPLEX, 0.3, cv::Scalar(0, 1, 0), 1, 8, 0);
  185. return depth_sim;
  186. }
  187. //获取深度像素对应长度单位(米)的换算比例
  188. float get_depth_scale(rs2::device dev)
  189. {
  190. // Go over the device's sensors
  191. for (rs2::sensor& sensor : dev.query_sensors())
  192. {
  193. // Check if the sensor if a depth sensor
  194. if (rs2::depth_sensor dpt = sensor.as<rs2::depth_sensor>())
  195. {
  196. return dpt.get_depth_scale();
  197. }
  198. }
  199. throw std::runtime_error("Device does not have a depth sensor");
  200. }
  201. //深度图对齐到彩色图函数
  202. Mat align_Depth2Color(Mat depth,Mat color,rs2::pipeline_profile profile){
  203. //声明数据流
  204. auto depth_stream=profile.get_stream(RS2_STREAM_DEPTH).as<rs2::video_stream_profile>();
  205. auto color_stream=profile.get_stream(RS2_STREAM_COLOR).as<rs2::video_stream_profile>();
  206. //获取内参
  207. const auto intrinDepth=depth_stream.get_intrinsics();
  208. const auto intrinColor=color_stream.get_intrinsics();
  209. color_intri_all=intrinColor;
  210. //直接获取从深度摄像头坐标系到彩色摄像头坐标系的欧式变换矩阵
  211. //auto extrinDepth2Color=depth_stream.get_extrinsics_to(color_stream);
  212. rs2_extrinsics extrinDepth2Color;
  213. rs2_error *error;
  214. rs2_get_extrinsics(depth_stream,color_stream,&extrinDepth2Color,&error);
  215. //平面点定义
  216. float pd_uv[2],pc_uv[2];
  217. //空间点定义
  218. float Pdc3[3],Pcc3[3];
  219. //获取深度像素与现实单位比例(D435默认1毫米)
  220. float depth_scale = get_depth_scale(profile.get_device());
  221. int y=0,x=0;
  222. //初始化结果
  223. Mat result=Mat::zeros(color.rows,color.cols,CV_8UC3);
  224. //对深度图像遍历
  225. for(int row=0;row<depth.rows;row++){
  226. for(int col=0;col<depth.cols;col++){
  227. //将当前的(x,y)放入数组pd_uv,表示当前深度图的点
  228. pd_uv[0]=col;//深度图像的列,左上角为0 col为x
  229. pd_uv[1]=row;//深度图像的行,左上角为0 ros为y
  230. //取当前点对应的深度值
  231. uint16_t depth_value=depth.at<uint16_t>(row,col);//对应深度图像的深度信息
  232. //换算到米
  233. float depth_m=depth_value*depth_scale;
  234. //将深度图的像素点根据内参转换到深度摄像头坐标系下的三维点
  235. rs2_deproject_pixel_to_point(Pdc3,&intrinDepth,pd_uv,depth_m);
  236. //将深度摄像头坐标系的三维点转化到彩色摄像头坐标系下
  237. rs2_transform_point_to_point(Pcc3,&extrinDepth2Color,Pdc3);
  238. //将彩色摄像头坐标系下的深度三维点映射到二维平面上
  239. rs2_project_point_to_pixel(pc_uv,&intrinColor,Pcc3);
  240. //取得映射后的(u,v)
  241. x=(int)pc_uv[0];
  242. y=(int)pc_uv[1];
  243. x=x<0? 0:x;
  244. x=x>depth.cols-1 ? depth.cols-1:x;
  245. y=y<0? 0:y;
  246. y=y>depth.rows-1 ? depth.rows-1:y;
  247. //将成功映射的点用彩色图对应点的RGB数据覆盖
  248. /* for(int k=0;k<3;k++){
  249. //这里设置了只显示3米距离内的东西
  250. if(depth_m<3)
  251. result.at<cv::Vec3b>(y,x)[k]=
  252. color.at<cv::Vec3b>(y,x)[k];
  253. }*/
  254. if(depth_m<limit_depth)
  255. result.at<uint16_t>(y,x)=depth_value;//得到对齐后的深度图https://www.cnblogs.com/AsanoLy/p/15072691.html
  256. }
  257. }
  258. return result;
  259. }
  260. int main()
  261. {
  262. std::thread t1(&detect_camera,modelWeights, modelConfiguration, classesFile);
  263. t1.detach();
  264. //深度图像颜色map
  265. rs2::colorizer c; // Helper to colorize depth images
  266. //创建数据管道
  267. rs2::pipeline pipe;
  268. rs2::config pipe_config;
  269. pipe_config.enable_stream(RS2_STREAM_DEPTH,640,480,RS2_FORMAT_Z16,30);
  270. pipe_config.enable_stream(RS2_STREAM_COLOR,640,480,RS2_FORMAT_BGR8,30);
  271. //start()函数返回数据管道的profile
  272. rs2::pipeline_profile profile = pipe.start(pipe_config);
  273. //定义一个变量去转换深度到距离
  274. float depth_clipping_distance = 1.f;
  275. //声明数据流
  276. auto depth_stream=profile.get_stream(RS2_STREAM_DEPTH).as<rs2::video_stream_profile>();
  277. auto color_stream=profile.get_stream(RS2_STREAM_COLOR).as<rs2::video_stream_profile>();
  278. //获取内参
  279. auto intrinDepth=depth_stream.get_intrinsics();
  280. auto intrinColor=color_stream.get_intrinsics();
  281. color_intri_all=intrinColor;//将内参传递出去
  282. //直接获取从深度摄像头坐标系到彩色摄像头坐标系的欧式变换矩阵
  283. auto extrinDepth2Color=depth_stream.get_extrinsics_to(color_stream);
  284. while (1) // Application still alive?
  285. {
  286. const char* depth_win="depth_Image";
  287. namedWindow(depth_win,WINDOW_AUTOSIZE);
  288. //深度图像颜色map
  289. rs2::colorizer c; // Helper to colorize depth images
  290. //堵塞程序直到新的一帧捕获
  291. rs2::frameset frameset = pipe.wait_for_frames();
  292. //取深度图和彩色图
  293. rs2::frame color_frame = frameset.get_color_frame();//processed.first(align_to);
  294. rs2::frame depth_frame = frameset.get_depth_frame();
  295. rs2::frame depth_frame_4_show = frameset.get_depth_frame().apply_filter(c);
  296. //获取宽高
  297. const int depth_w=depth_frame.as<rs2::video_frame>().get_width();
  298. const int depth_h=depth_frame.as<rs2::video_frame>().get_height();
  299. const int color_w=color_frame.as<rs2::video_frame>().get_width();
  300. const int color_h=color_frame.as<rs2::video_frame>().get_height();
  301. //创建OPENCV类型 并传入数据
  302. Mat depth_image(Size(depth_w,depth_h),
  303. CV_16U,(void*)depth_frame.get_data(),Mat::AUTO_STEP);
  304. Mat depth_image_4_show(Size(depth_w,depth_h),
  305. CV_8UC3,(void*)depth_frame_4_show.get_data(),Mat::AUTO_STEP);
  306. Mat color_image(Size(color_w,color_h),
  307. CV_8UC3,(void*)color_frame.get_data(),Mat::AUTO_STEP);
  308. //实现深度图与彩色图对其,返回对其后的深度图
  309. Mat result=align_Depth2Color(depth_image,color_image,profile);
  310. mtx_yolo.lock();
  311. imshow(depth_win,depth_image_4_show);
  312. waitKey(10);
  313. mtx_yolo.unlock();
  314. image_yolov3=color_image;
  315. yolov3_depth=result;
  316. }
  317. return 0;
  318. }

 CMakeLists.txt

  1. cmake_minimum_required(VERSION 3.1.0)
  2. project(RealsenseExamples-Depth)
  3. set(DEPENDENCIES realsense2 ${PCL_LIBRARIES})
  4. list(APPEND DEPENDENCIES ${OPENGL_LIBRARIES})
  5. find_package(OpenCV REQUIRED)
  6. find_package(OpenGL)
  7. if(NOT WIN32)
  8. SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")
  9. endif()
  10. if(NOT OPENGL_FOUND)
  11. message(FATAL_ERROR "\n\n OpenGL package is missing!\n\n")
  12. endif()
  13. if(WIN32)
  14. list(APPEND DEPENDENCIES glfw3)
  15. else()
  16. find_package(glfw3 REQUIRED)
  17. list(APPEND DEPENDENCIES glfw)
  18. endif()
  19. add_executable(realsense_yolo realsense_yolo.cpp)
  20. target_link_libraries(realsense_yolo ${DEPENDENCIES} ${OpenCV_LIBS})

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/250771
推荐阅读
相关标签
  

闽ICP备14008679号