yolov3-tiny+realsense d455获取目标深度信息及位置信息

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

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

文件结构

 .h文件

#include <iostream>
#include <string>
#include <vector>
#include <chrono>
#include <mutex> //定义了C++11标准中的一些互斥访问的类与方法
#include <thread> //线程头文件
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/types_c.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/dnn.hpp>
#include <algorithm>
#include<librealsense2/rs.hpp>
#include<librealsense2/rsutil.h>
using namespace std;
using namespace cv;
using namespace dnn;
#define limit_L(a,b) (a-b>0)?(a-b):(0)
#define limit_H(a,b,max) (a+b>max)?(max):(a+b)

#define STREAM          RS2_STREAM_DEPTH  // rs2_stream is a types of data provided by RealSense device           //
#define FORMAT          RS2_FORMAT_Z16    // rs2_format identifies how binary data is encoded within a frame      //
#define WIDTH           640               // Defines the number of columns for each frame or zero for auto resolve//
#define HEIGHT          480                 // Defines the number of lines for each frame or zero for auto resolve  //
#define FPS             30                // Defines the rate of frames per second                                //
#define STREAM_INDEX    0                 // Defines the stream index, used for multiple streams of the same type //
#define HEIGHT_RATIO    20                // Defines the height ratio between the original frame to the new frame //
#define WIDTH_RATIO     10                // Defines the width ratio between the original frame to the new frame  //


#define STREAM1          RS2_STREAM_COLOR  // rs2_stream is a types of data provided by RealSense device           //
#define FORMAT1          RS2_FORMAT_RGB8   // rs2_format identifies how binary data is encoded within a frame      //
#define FPS1             30                // Defines the rate of frames per second                                //
#define STREAM_INDEX     0                 // Defines the stream index, used for multiple streams of the same type //

// Remove the bounding boxes with low confidence using non-maxima suppression
void postprocess(Mat& frame, const vector<Mat>& out);
// Draw the predicted bounding box
void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame);
// Get the names of the output layers
vector<String> getOutputsNames(const Net& net);
void detect_camera(string modelWeights, string modelConfiguration, string classesFile);
void postprocess(Mat& frame, const vector<Mat>& outs);
void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame);
vector<String> getOutputsNames(const Net& net);
float get_depth_unit_value(const rs2_device* const dev);
uint16_t get_color_depth(Mat color_c,rs2_intrinsics color_intri,Mat depth_c,int color_cols,int color_rows,int depth_err);
struct color_point
{
    int x;
    int y;
    double color;
}color_Point;
Mat image_yolov3,yolov3_depth;
rs2_intrinsics color_intri_all;
std::mutex mtx_yolo;



 .cpp文件

#include "./include/realsense_yolo.h"
vector<string> classes;
int inpWidth = WIDTH;  // Width of network's input image
int inpHeight= HEIGHT; // Height of network's input image
string dir="/home/user-e290/Desktop/depth_yolov3/files/";
float confThreshold = 0.25; // Confidence threshold
float nmsThreshold = 0.45;  // Non-maximum suppression threshold
string modelConfiguration = dir+"yolov3-tiny.cfg";
string modelWeights = dir+"yolov3-tiny.weights";
//string modelConfiguration = dir+"yolov3.cfg";
//string modelWeights = dir+"yolov3.weights";
string classesFile = dir+"coco.names";// "coco.names";
void postprocess(Mat& frame, const vector<Mat>& outs)
{
	vector<int> classIds;
	vector<float> confidences;
	vector<Rect> boxes;
	for (size_t pos_i = 0; pos_i < outs.size(); ++pos_i)
	{
		// Scan through all the bounding boxes output from the network and keep only the
		// ones with high confidence scores. Assign the box's class label as the class
		// with the highest score for the box.
		float* data = (float*)outs[pos_i].data;
		for (int pos_j = 0; pos_j < outs[pos_i].rows; ++pos_j, data += outs[pos_i].cols)
		{
			Mat scores = outs[pos_i].row(pos_j).colRange(5, outs[pos_i].cols);
			Point classIdPoint;
			double confidence;

			// Get the value and location of the maximum score
			minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
			if (confidence > confThreshold)
			{
				int centerX = (int)(data[0] * frame.cols);
				int centerY = (int)(data[1] * frame.rows);
				int width = (int)(data[2] * frame.cols);
				int height = (int)(data[3] * frame.rows);
				int left = centerX - width / 2;
				int top = centerY - height / 2;

				classIds.push_back(classIdPoint.x);
				confidences.push_back((float)confidence);
				boxes.push_back(Rect(left, top, width, height));
			}
		}
	}
	// Perform non maximum suppression to eliminate redundant overlapping boxes with
	// lower confidences
	vector<int> indices;
	NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);
	for (size_t i = 0; i < indices.size(); ++i)
	{
		int idx = indices[i];
		Rect box = boxes[idx];
		drawPred(classIds[idx], confidences[idx], box.x, box.y,
			box.x + box.width, box.y + box.height, frame);
        get_color_depth(frame,color_intri_all,yolov3_depth,box.x + box.width/2,box.y + box.height/2,20);
	}
}
// Get the names of the output layers
vector<String> getOutputsNames(const Net& net)
{
	static vector<String> names;
	if (names.empty())
	{
		//Get the indices of the output layers, i.e. the layers with unconnected outputs
		vector<int> outLayers = net.getUnconnectedOutLayers();
		//get the names of all the layers in the network
		vector<String> layersNames = net.getLayerNames();
		// Get the names of the output layers in names
		names.resize(outLayers.size());
		for (size_t get_i = 0; get_i < outLayers.size(); ++get_i)
			names[get_i] = layersNames[outLayers[get_i] - 1];
	}
	return names;
}
// Draw the predicted bounding box
void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame)
{
	//Draw a rectangle displaying the bounding box
	rectangle(frame, Point(left, top), Point(right, bottom), Scalar(255, 178, 50), 3);
	//Get the label for the class name and its confidence
	string label = format("%.2f", conf);
	if (!classes.empty())
	{
		CV_Assert(classId < (int)classes.size());
		label = classes[classId] + ":" + label;
	}	
	//Display the label at the top of the bounding box
	int baseLine;
	Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
	top = max(top, labelSize.height);
	rectangle(frame, Point(left, top - round(1.5*labelSize.height)), Point(left + round(1.5*labelSize.width), top + baseLine), Scalar(255, 255, 255), FILLED);
	cv::putText(frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 0), 1);
}
 //摄像头
 void detect_camera(string modelWeights, string modelConfiguration, string classesFile) 
 {
	Net net = readNetFromDarknet(modelConfiguration, modelWeights);
	net.setPreferableBackend(DNN_BACKEND_OPENCV);
	net.setPreferableTarget(DNN_TARGET_CPU);	
	Mat frame, blob;
	// Process frames.
    std::this_thread::sleep_for(std::chrono::seconds(3));
	while (1)
	{
        frame=image_yolov3;
       // std::this_thread::sleep_for(std::chrono:: milliseconds (10));	//添加
		if (frame.empty()) {
			cout << "Done processing !!!" << endl;
            std::this_thread::sleep_for(std::chrono::seconds(3));
		}
        else{
            // Create a 4D blob from a frame.
            blobFromImage(frame, blob, 1 / 255.0, cv::Size(inpWidth, inpHeight), Scalar(0, 0, 0), true, false);		
            //Sets the input to the network
            net.setInput(blob);
            // Runs the forward pass to get output of the output layers
            vector<Mat> outs;
            net.forward(outs, getOutputsNames(net));
            // Remove the bounding boxes with low confidence
            postprocess(frame, outs);
            // Put efficiency information. The function getPerfProfile returns the overall time for inference(t) and the timings for each of the layers(in layersTimes)
            vector<double> layersTimes;
            double freq = getTickFrequency() / 1000;
            double t = net.getPerfProfile(layersTimes) / freq;
            string label = format("Inference time for a frame : %.2f ms", t);
            putText(frame, label, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255));	
            // Write the frame with the detection boxes
            Mat detectedFrame;
            frame.convertTo(detectedFrame, CV_8U);
            mtx_yolo.lock();
            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轴
            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轴
            putText(frame,"x",Point(frame.cols*0.95,frame.rows*0.48),FONT_HERSHEY_PLAIN,2,cv::Scalar(0, 1, 0),2);
            putText(frame,"y",Point(frame.cols*0.52,frame.rows*0.05),FONT_HERSHEY_PLAIN,2,cv::Scalar(0, 1, 0),2);
            putText(frame,"I",Point(frame.cols*0.75,frame.rows*0.25),FONT_HERSHEY_PLAIN,2,cv::Scalar(0, 1, 0),2);
            putText(frame,"II",Point(frame.cols*0.25,frame.rows*0.25),FONT_HERSHEY_PLAIN,2,cv::Scalar(0, 1, 0),2);
            putText(frame,"III",Point(frame.cols*0.25,frame.rows*0.75),FONT_HERSHEY_PLAIN,2,cv::Scalar(0, 1, 0),2);
            putText(frame,"IV",Point(frame.cols*0.75,frame.rows*0.75),FONT_HERSHEY_PLAIN,2,cv::Scalar(0, 1, 0),2);
            imshow("deep learning",frame);
            waitKey(10);
            mtx_yolo.unlock();
	    }
    }	
}


//
///  date:     2021/09/28
///  input:    Mat depth_c 深度图,Mat color_c rgb图,rgb图color_cols列,rgb图color_rows行,depth_err像素偏移误差
///  function: 根据输入的rgb图及rgb 行和列的位置取出深度图对应的值
///  output:   深度信息   
///  链接:https://www.freesion.com/article/3585644384/,根据内参获取真实位置
///       https://blog.csdn.net/SFM2020/article/details/84591758
//
uint16_t get_color_depth(Mat color_c,rs2_intrinsics color_intri,Mat depth_c,int color_cols,int color_rows,int depth_err)
{
  char str[10];//用于存放帧率的字符串
  uint16_t depth_sim=limit_depth*1000;
  int limit_left=0,limit_right=0,limit_up=0,limit_down=0;
  limit_left=limit_L(color_cols,depth_err);
  limit_right=limit_H(color_cols,depth_err,depth_c.cols);
  limit_up=limit_H(color_rows,depth_err,depth_c.rows);
  limit_down=limit_L(color_rows,depth_err);//(row,col)
  for(int get_i=limit_down;get_i<limit_up;get_i++){
    for(int get_j=limit_left;get_j<limit_right;get_j++){
       if(depth_c.at<uint16_t>(get_i,get_j)!=0)
       {
          if(depth_c.at<uint16_t>(get_i,get_j)<depth_sim)
           depth_sim=depth_c.at<uint16_t>(get_i,get_j);  
       }              
    }
  } 
  Point target_xy_true;
  target_xy_true.x=(color_cols-color_intri.ppx)*depth_sim/color_intri.fx;//cols为x
  target_xy_true.y=(color_intri.ppy-color_rows)*depth_sim/color_intri.fy;//rows为y
  string text = "Dp="; 
  sprintf(str, "%d", depth_sim); 
  text += str; 
  text +=" Px=";
  sprintf(str, "%d", target_xy_true.x); 
  text += str; 
  text +=" Py=";
  sprintf(str, "%d", target_xy_true.y); 
  text += str; 
  circle(color_c,cv::Point(color_cols,color_rows),16, Scalar(0.5,0.2,0),1,8,0);//点是绿色 
  putText(color_c, text,cv::Point(color_cols,color_rows),cv::FONT_HERSHEY_COMPLEX, 0.3, cv::Scalar(0, 1, 0), 1, 8, 0); 
  return depth_sim;
}

//获取深度像素对应长度单位(米)的换算比例
float get_depth_scale(rs2::device dev)
{
    // Go over the device's sensors
    for (rs2::sensor& sensor : dev.query_sensors())
    {
        // Check if the sensor if a depth sensor
        if (rs2::depth_sensor dpt = sensor.as<rs2::depth_sensor>())
        {
            return dpt.get_depth_scale();
        }
    }
    throw std::runtime_error("Device does not have a depth sensor");
}

//深度图对齐到彩色图函数
Mat align_Depth2Color(Mat depth,Mat color,rs2::pipeline_profile profile){
    //声明数据流
    auto depth_stream=profile.get_stream(RS2_STREAM_DEPTH).as<rs2::video_stream_profile>();
    auto color_stream=profile.get_stream(RS2_STREAM_COLOR).as<rs2::video_stream_profile>();
    //获取内参
    const auto intrinDepth=depth_stream.get_intrinsics();
    const auto intrinColor=color_stream.get_intrinsics();
    color_intri_all=intrinColor;
    //直接获取从深度摄像头坐标系到彩色摄像头坐标系的欧式变换矩阵
    //auto  extrinDepth2Color=depth_stream.get_extrinsics_to(color_stream);
    rs2_extrinsics  extrinDepth2Color;
    rs2_error *error;
    rs2_get_extrinsics(depth_stream,color_stream,&extrinDepth2Color,&error);
 
    //平面点定义
    float pd_uv[2],pc_uv[2];
    //空间点定义
    float Pdc3[3],Pcc3[3];
 
    //获取深度像素与现实单位比例(D435默认1毫米)
    float depth_scale = get_depth_scale(profile.get_device());
    int y=0,x=0;
    //初始化结果
    Mat result=Mat::zeros(color.rows,color.cols,CV_8UC3);
    //对深度图像遍历
    for(int row=0;row<depth.rows;row++){
        for(int col=0;col<depth.cols;col++){
            //将当前的(x,y)放入数组pd_uv,表示当前深度图的点
            pd_uv[0]=col;//深度图像的列,左上角为0 col为x
            pd_uv[1]=row;//深度图像的行,左上角为0 ros为y
            //取当前点对应的深度值
            uint16_t depth_value=depth.at<uint16_t>(row,col);//对应深度图像的深度信息
            //换算到米
            float depth_m=depth_value*depth_scale;
            //将深度图的像素点根据内参转换到深度摄像头坐标系下的三维点
            rs2_deproject_pixel_to_point(Pdc3,&intrinDepth,pd_uv,depth_m);
            //将深度摄像头坐标系的三维点转化到彩色摄像头坐标系下
            rs2_transform_point_to_point(Pcc3,&extrinDepth2Color,Pdc3);
            //将彩色摄像头坐标系下的深度三维点映射到二维平面上
            rs2_project_point_to_pixel(pc_uv,&intrinColor,Pcc3);
            //取得映射后的(u,v)
            x=(int)pc_uv[0];
            y=(int)pc_uv[1];
            x=x<0? 0:x;
            x=x>depth.cols-1 ? depth.cols-1:x;
            y=y<0? 0:y;
            y=y>depth.rows-1 ? depth.rows-1:y;
 
            //将成功映射的点用彩色图对应点的RGB数据覆盖
           /* for(int k=0;k<3;k++){
                //这里设置了只显示3米距离内的东西
                if(depth_m<3)
                result.at<cv::Vec3b>(y,x)[k]=
                        color.at<cv::Vec3b>(y,x)[k];                
            }*/
            if(depth_m<limit_depth)
             result.at<uint16_t>(y,x)=depth_value;//得到对齐后的深度图https://www.cnblogs.com/AsanoLy/p/15072691.html
        }
    }
    return result;
}
 
int main()
{
    std::thread t1(&detect_camera,modelWeights, modelConfiguration, classesFile);
    t1.detach(); 
    //深度图像颜色map
    rs2::colorizer c;                          // Helper to colorize depth images
    //创建数据管道
    rs2::pipeline pipe;
    rs2::config pipe_config;
    pipe_config.enable_stream(RS2_STREAM_DEPTH,640,480,RS2_FORMAT_Z16,30);
    pipe_config.enable_stream(RS2_STREAM_COLOR,640,480,RS2_FORMAT_BGR8,30);
 
    //start()函数返回数据管道的profile
    rs2::pipeline_profile profile = pipe.start(pipe_config);
 
    //定义一个变量去转换深度到距离
    float depth_clipping_distance = 1.f;
 
    //声明数据流
    auto depth_stream=profile.get_stream(RS2_STREAM_DEPTH).as<rs2::video_stream_profile>();
    auto color_stream=profile.get_stream(RS2_STREAM_COLOR).as<rs2::video_stream_profile>();
 
    //获取内参
    auto intrinDepth=depth_stream.get_intrinsics();
    auto intrinColor=color_stream.get_intrinsics();
    color_intri_all=intrinColor;//将内参传递出去
    //直接获取从深度摄像头坐标系到彩色摄像头坐标系的欧式变换矩阵
    auto  extrinDepth2Color=depth_stream.get_extrinsics_to(color_stream);
 
    while (1) // Application still alive?
    {
        const char* depth_win="depth_Image";
        namedWindow(depth_win,WINDOW_AUTOSIZE);
        //深度图像颜色map
        rs2::colorizer c;                          // Helper to colorize depth images
        //堵塞程序直到新的一帧捕获
        rs2::frameset frameset = pipe.wait_for_frames();
        //取深度图和彩色图
        rs2::frame color_frame = frameset.get_color_frame();//processed.first(align_to);
        rs2::frame depth_frame = frameset.get_depth_frame();
        rs2::frame depth_frame_4_show = frameset.get_depth_frame().apply_filter(c);
        //获取宽高
        const int depth_w=depth_frame.as<rs2::video_frame>().get_width();
        const int depth_h=depth_frame.as<rs2::video_frame>().get_height();
        const int color_w=color_frame.as<rs2::video_frame>().get_width();
        const int color_h=color_frame.as<rs2::video_frame>().get_height();
 
        //创建OPENCV类型 并传入数据
        Mat depth_image(Size(depth_w,depth_h),
                                CV_16U,(void*)depth_frame.get_data(),Mat::AUTO_STEP);
        Mat depth_image_4_show(Size(depth_w,depth_h),
                                CV_8UC3,(void*)depth_frame_4_show.get_data(),Mat::AUTO_STEP);
        Mat color_image(Size(color_w,color_h),
                                CV_8UC3,(void*)color_frame.get_data(),Mat::AUTO_STEP);
        //实现深度图与彩色图对其,返回对其后的深度图
        Mat result=align_Depth2Color(depth_image,color_image,profile);
        mtx_yolo.lock();      
        imshow(depth_win,depth_image_4_show);
        waitKey(10);
        mtx_yolo.unlock();
        image_yolov3=color_image;
        yolov3_depth=result;
    }
    return 0;
}

 CMakeLists.txt

cmake_minimum_required(VERSION 3.1.0)
project(RealsenseExamples-Depth)
set(DEPENDENCIES realsense2 ${PCL_LIBRARIES})
list(APPEND DEPENDENCIES ${OPENGL_LIBRARIES})
find_package(OpenCV REQUIRED)
find_package(OpenGL)
if(NOT WIN32)
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")
endif()
if(NOT OPENGL_FOUND)
    message(FATAL_ERROR "\n\n OpenGL package is missing!\n\n")
endif()
if(WIN32)
    list(APPEND DEPENDENCIES glfw3)
else()
    find_package(glfw3 REQUIRED)
    list(APPEND DEPENDENCIES glfw)
endif()

add_executable(realsense_yolo realsense_yolo.cpp)

target_link_libraries(realsense_yolo ${DEPENDENCIES} ${OpenCV_LIBS})

 

 

 

 

  • 1
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值