栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

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

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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 
#include 
#include 
#include 
#include  //定义了C++11标准中的一些互斥访问的类与方法
#include  //线程头文件
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include
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& 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 getOutputsNames(const Net& net);
void detect_camera(string modelWeights, string modelConfiguration, string classesFile);
void postprocess(Mat& frame, const vector& outs);
void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame);
vector 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 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.5; // Confidence threshold
float nmsThreshold = 0.4;  // 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& outs)
{
	vector classIds;
	vector confidences;
	vector 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 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 getOutputsNames(const Net& net)
{
	static vector names;
	if (names.empty())
	{
		//Get the indices of the output layers, i.e. the layers with unconnected outputs
		vector outLayers = net.getUnconnectedOutLayers();
		//get the names of all the layers in the network
		vector 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 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 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(get_i,get_j)!=0)
       {
          if(depth_c.at(get_i,get_j)(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())
        {
            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();
    auto color_stream=profile.get_stream(RS2_STREAM_COLOR).as();
    //获取内参
    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(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数据覆盖
           
            if(depth_m(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(); 
    //const char* depth_win="depth_Image";
    // namedWindow(depth_win,WINDOW_AUTOSIZE);
    // const char* color_win="color_Image";
    // namedWindow(color_win,WINDOW_AUTOSIZE);
 
    //深度图像颜色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();
    auto color_stream=profile.get_stream(RS2_STREAM_COLOR).as();
 
    //获取内参
    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?
    {
        //堵塞程序直到新的一帧捕获
        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().get_width();
        const int depth_h=depth_frame.as().get_height();
        const int color_w=color_frame.as().get_width();
        const int color_h=color_frame.as().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);
        
        // cout<<"center distence:"<(color_image.cols/2,color_image.rows/2)<<"mm"< 

 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 "nn OpenGL package is missing!nn")
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})

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/295833.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号