zoukankan      html  css  js  c++  java
  • realsense 测量

    realsense  测量

    #include <iostream>
    
    using namespace std;
    #include <sstream>
    #include <iostream>
    #include <fstream>
    #include <algorithm>
    #include<string>
    
    #include<opencv2/imgproc/imgproc.hpp>
    #include<opencv2/core/core.hpp>
    #include<opencv2/highgui/highgui.hpp>
    using namespace cv;
    
    #include<librealsense2/rs.hpp>
    #include<librealsense2/rsutil.h>
    
    
    const double camera_factor = 1;
    const double camera_cx = 649.402466;
    const double camera_cy = 649.402466;
    const double camera_fx = 640.685730;
    const double camera_fy = 359.206085;
    
    double p_x = 0.0;
    double p_y = 0.0;
    double p_z = 0.0;
    
    Mat kernel1 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3), cv::Point(-1, -1));
    Mat kernel2 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(7, 7), cv::Point(-1, -1));
    Rect rect1;
    
    void processFrame(cv::Mat &mask, cv::Rect &rect2)
    {
        std::vector<std::vector<cv::Point>> vec_contours;
        std::vector<cv::Vec4i> hireachy;
        findContours(mask, vec_contours, hireachy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
        if (vec_contours.size()>0)
        {
            double maxArea = 0.0;
            for (size_t k = 0; k<vec_contours.size(); k++)
            {
                double area1 = contourArea(vec_contours[static_cast<int>(k)]);
                if (area1>maxArea)
                {
                    maxArea = area1;
                    rect2 = boundingRect(vec_contours[static_cast<int>(k)]);
                }
            }
        }
        else
        {
            rect2.x = rect2.y = rect2.width = rect2.height = 0;
        }
    
    
    }
    
    //获取深度像素对应长度单位(米)的换算比例
    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();
    
        //直接获取从深度摄像头坐标系到彩色摄像头坐标系的欧式变换矩阵
        //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(color.rows,color.cols,CV_8UC3,Scalar(0,0,0));
        Mat result = Mat(color.rows, color.cols, CV_16U, Scalar(0));
        //对深度图像遍历
        for (int row = 0; row<depth.rows; row++) {
            for (int col = 0; col<depth.cols; col++) {
                //将当前的(x,y)放入数组pd_uv,表示当前深度图的点
                pd_uv[0] = col;
                pd_uv[1] = row;
                //取当前点对应的深度值
                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];
                //            if(x<0||x>color.cols)
                //                continue;
                //            if(y<0||y>color.rows)
                //                continue;
                //最值限定
                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;
    
                result.at<uint16_t>(y, x) = depth_value;
            }
        }
        //返回一个与彩色图对齐了的深度信息图像
        return result;
    }
    
    
    void measure_distance(Mat &color, Mat depth, cv::Size range, rs2::pipeline_profile profile)
    {
        //获取深度像素与现实单位比例(D435默认1毫米)
        float depth_scale = get_depth_scale(profile.get_device());
    
    
    
        //定义图像中心点
        //cv::Point center(color.cols / 2, color.rows / 2);
    
    
        //////////////////////////////
        int  center_x1 = color.cols / 2;
        int center_y1 = color.rows / 2;
        Mat mask;
        
    
        inRange(color, cv::Scalar(0, 125, 125), cv::Scalar(50, 255, 255), mask);
    
    
        if (!mask.empty())
        {
            //imshow("mask", mask);
        }
        if (!mask.empty())
        {
    
            
            morphologyEx(mask, mask, cv::MORPH_OPEN, kernel1, cv::Point(-1, -1), 1);
            dilate(mask, mask, kernel2, cv::Point(-1, -1), 4);
            //imshow("mask", mask);
            
            processFrame(mask, rect1);//寻找轮廓
            rectangle(color, rect1, cv::Scalar(0, 0, 255), 4, 8, 0);
    
            //center_x1 = int((rect1.x + rect1.width*0.5));
            //center_y1 = int((rect1.y + rect1.height*0.5));
    
            center_x1 = int((rect1.x + rect1.width*0.5));
            center_y1 = int((rect1.y + rect1.height*0.5));
    
        }
        
    
        cv::Point center(center_x1, center_y1);
        //////////////////////////
    
        //定义计算距离的范围
        //cv::Rect RectRange(center.x - range.width / 2, center.y - range.height / 2, range.width, range.height);
    
        cv::Rect RectRange = rect1;
        //cv::Rect RectRange(rect1.x+50, rect1.y+50, 100,100);
    
    
        //遍历该范围
        float distance_sum = 0;
        int effective_pixel = 0;
        int x1 = 0;
        int y1 = 0;
    
        for (int y = RectRange.y; y<RectRange.y + RectRange.height; y++) {
            for (int x = RectRange.x; x<RectRange.x + RectRange.width; x++) {
                //如果深度图下该点像素不为0,表示有距离信息
                if (depth.at<uint16_t>(y, x)) {
                    //depth_scale*depth.at<uint16_t>(y, x);
                    //distance_sum += depth_scale*depth.at<uint16_t>(y, x);
    
                    float d_value1 = depth_scale*depth.at<uint16_t>(y, x);
                    //float x1 = (x - camera_cx)*d_value1 / camera_fx;
                    //float y1 = (y-camera_cy)*d_value1/camera_fy;
                    //std::cout << "[" <<x1<<"   "<<y1<<"  "<< d_value1 << "]"<< std::endl;
    
                    distance_sum += d_value1;
    
    
                    effective_pixel++;
    
    
    
                    //x1 = x;
                    //y1 = y;
                }
            }
        }
    
    
    
        //cout << "遍历完成,有效像素点:" << effective_pixel << "    " << x1 << "     " << y1 << "     "<<distance_sum<<endl;
        cout << "遍历完成,有效像素点:" << effective_pixel << "    " << distance_sum << endl;
    
        float effective_distance = distance_sum / effective_pixel;
    
    
        //Hauteur_XYZ(const rs2_intrinsics& intr, const rs2::depth_frame& frame, int x, int y, double H, double D, double angle, float wpoint[3], double dis_max, double dis_min)
    
    
    
        int x0 = center.x;
        int y0 = center.y;
    
        //if (depth.at<uint16_t>(y0, x0))
        //{
        float d_value1 = depth_scale*depth.at<uint16_t>(y0, x0);
        float x2 = (x0 - camera_cx)*d_value1 / camera_fx;
        float y2 = (y0 - camera_cy)*d_value1 / camera_fy;
    
        if (p_x==0 && p_y==0 && p_z==0)
        {
            p_x = x2;
            p_y = y2;
            p_z = effective_distance;
        }
    
        if (abs(x2)>0.0 && abs(y2)>0.0)
        {
            std::cout << "[" << x2 << "   " << y2 << "  " << effective_distance << "]" << std::endl;
    
            p_x = x2;
            p_y = y2;
            p_z = effective_distance;
    
            cout << "目标距离:" << effective_distance << " m" << endl;
            char distance_str[50];
            //sprintf(distance_str, "the distance is:%f m", effective_distance);
            sprintf(distance_str, "[%f,%f,%f]", p_x, p_y, p_z);
    
            cv::rectangle(color, RectRange, Scalar(0, 0, 255), 2, 8);
            cv::putText(color, (string)distance_str, cv::Point(color.cols*0.02, color.rows*0.05),
                cv::FONT_HERSHEY_PLAIN, 2, Scalar(0, 255, 0), 2, 8);
    
            cv::circle(color, center, 4, cv::Scalar(0, 0, 255), 4, 8, 0);
    
        }
        else 
        {
            char distance_str[50];
            //sprintf(distance_str, "the distance is:%f m", effective_distance);
            sprintf(distance_str, "[%f,%f,%f]", p_x, p_y, p_z);
    
            cv::rectangle(color, RectRange, Scalar(0, 0, 255), 2, 8);
            cv::putText(color, (string)distance_str, cv::Point(color.cols*0.02, color.rows*0.05),
                cv::FONT_HERSHEY_PLAIN, 2, Scalar(0, 255, 0), 2, 8);
    
            cv::circle(color, center, 4, cv::Scalar(0, 0, 255), 4, 8, 0);
        }
    
        
        //}
    
    
    
    }
    
    //
    //static void Hauteur_Y(Mat &color, , cv::Size range, const rs2_intrinsics& intr, const rs2::depth_frame& frame, std::ofstream *outFile,
    //    double H, double D, double angle, float wpoint[3], double dis_max, double dis_min)
    //{
    //    cv::Point center(color.cols / 2, color.rows / 2);
    //    //定义计算距离的范围
    //    cv::Rect RectRange(center.x - range.width / 2, center.y - range.height / 2, range.width, range.height);
    //
    //
    //    float upixel[2]; // From pixel
    //    float upoint[3]; // From point (in 3D)
    //    float xpoint[3];
    //    float extrin[4][4] = { { 1,0,0,0 },{ 0,cos(angle),sin(angle),H },{ 0,-sin(angle),cos(angle),0 },{ 0,0,0,1 } };
    //    upixel[0] = 20;
    //    upixel[1] = 20;
    //    auto udist = frame.get_distance(upixel[0], upixel[1]);
    //    rs2_deproject_pixel_to_point(upoint, &intr, upixel, udist);
    //    float b[4] = { upoint[0],upoint[1],upoint[2],1 };
    //    float out[4];
    //    for (int i = 0; i < 4; i++)
    //    {
    //        float s = 0;
    //        for (int k = 0; k < 4; k++)
    //            s += extrin[i][k] * b[k];
    //        out[i] = s;
    //
    //    };
    //    if (udist < dis_max && udist > dis_min)
    //    {
    //        *outFile << out[0] << ';' << out[2] << ';' << -out[1] << ';' << out[0] << ';' << out[2] << ';' << -out[1] << ';' << "\n";
    //        wpoint[0] = out[0];
    //        wpoint[1] = out[2];
    //        wpoint[2] = -out[1];
    //    }
    //}
    
    
    
    
    int main()
    {
    
    
    
        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::context ctx;
        //rs2::device* res_device = ctx.
    
        //创建数据管道
        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>();
    
    
        rs2::device rs_dev = profile.get_device();
    
    
        //获取内参
        auto intrinDepth = depth_stream.get_intrinsics();
        auto intrinColor = color_stream.get_intrinsics();
    
        //直接获取从深度摄像头坐标系到彩色摄像头坐标系的欧式变换矩阵
        auto  extrinDepth2Color = depth_stream.get_extrinsics_to(color_stream);
    
        while (cvGetWindowHandle(depth_win) && cvGetWindowHandle(color_win)) // 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<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);
            measure_distance(color_image, result, cv::Size(20, 20), profile);
    
    
    
    
            //显示
            imshow(depth_win, depth_image_4_show);
            imshow(color_win, color_image);
            //imshow("result",result);
            waitKey(1);
        }
        return 0;
    }

     

    #############################

  • 相关阅读:
    Postgresql中string转换成timestamp类型
    zTree节点重叠或者遮挡
    Powerdesigner+Execel
    Powerdesigner+PostgreSQL
    PostgreSQL 的 distinct on 的理解
    PostgreSql问题:ERROR: operator does not exist: timestamp without time zone > character varying
    git分支小问题
    SSH问题:系统启动时,spring配置文件解析失败,报”cvc-elt.1: 找不到元素 'beans' 的声明“异常
    PostgresSQL中的限制和级联删除
    sql语句添加删除外键及其约束
  • 原文地址:https://www.cnblogs.com/herd/p/15634422.html
Copyright © 2011-2022 走看看