基于OpenCV+RealSense的障碍物检测

摄像头:实感摄像头D415

基本思路:通过realsense SDK2.0 定义的类型和接口获取摄像头的数据和参数,将其转化为Mat对象对其进行图像模糊,转化为灰度图,二值化的处理,然后提取并绘制轮廓。接着计算轮廓中心点坐标,计算出坐标与摄像头的距离,绘制一定距离内的矩形,将距离参数转化为字符串显示出来.

代码实现:

#include 
#include 
#include    
#include  
#include 
#include "example.hpp" 
using namespace std;
using namespace cv;
using namespace rs2;

vector> contours;  // 存储发现的轮廓对象
vector hierachy;          // 图像拓扑结构   

// 图像处理的函数
Mat Morphological_process(Mat img)
{
    Mat img_gray, dst;
    GaussianBlur(img, img, Size(7, 7), 7, 7);
    cvtColor(img, img_gray, COLOR_BGR2GRAY);
    threshold(img_gray, dst, 127, 255, THRESH_BINARY);
    return dst;
}

// 将表示距离的数字转为字符串的函数
string Convert(float Num)
{
    ostringstream oss;
    oss << Num;
    string str(oss.str());
    return str;
}

// 绘制带旋转角度的矩形的函数
Mat draw_Wuhu(Mat start_contour)
{
    vector rotated_rect(contours.size());   //定义带旋转角度的最小矩形集合
    Point2f p[4];       //四个角的坐标集合
    for (size_t i = 0; i < contours.size(); i++)
    {
        if (contourArea(contours[i]) > 500)
        {
            if (contours[i].size() > 5)
            {
                rotated_rect[i] = minAreaRect(contours[i]);   //获取最小矩形集合
                rotated_rect[i].points(p);  //返回四个角的列表
                for (int k = 0; k < 4; k++) {
                    line(start_contour, p[k], p[(k + 1) % 4], Scalar(0, 200, 200), 2, 8);   //(k+1)%4防止数组越界
                }
            }
        }
    }
    return start_contour;
}

// 一个很多事很忙的函数
Mat get_draw_contours(Mat dst_contour, Mat start_contour, depth_frame dep)
{
    findContours(dst_contour, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
    Scalar color = Scalar(100, 100, 200);
    for (auto i = 0; i < contours.size(); ++i)
    {
        if (contourArea(contours[i]) > 500)    // 去除面积较小的物体
        {
            drawContours(start_contour, contours, i, color, 3, 8, hierachy, 1, Point(0, 0));
        }
    }
    // 计算中心点坐标
    vector contour_moment(contours.size());
    vector centerpos(contours.size());
    for (size_t i = 0; i < contours.size(); i++)
    {
        if (contourArea(contours[i]) > 500)
        {
            contour_moment[i] = moments(contours[i]);
            centerpos[i].x = contour_moment[i].m10 / contour_moment[i].m00;
            centerpos[i].y = contour_moment[i].m01 / contour_moment[i].m00;
            circle(start_contour, centerpos[i], 3, Scalar(250, 250, 10));           // 绘画中心点
            float distance = dep.get_distance(centerpos[i].x, centerpos[i].y);      // 距离单位为米
            if (distance <= 2.0)
            {
                string ch = Convert(distance);
                putText(start_contour, ch, centerpos[i], FONT_HERSHEY_SIMPLEX, 2, Scalar(0, 0, 250), 1, 8, false);
                start_contour = draw_Wuhu(start_contour);
            }
        }
    }
    return start_contour;
}

// 主函数
int main(int argc, char* argv[]) try
{
    colorizer color_map;
    pipeline pipe;  // 定义一个管道
    pipe.start();   // 开始传输流
    const auto window_name = "Display color_Image";
    namedWindow(window_name, WINDOW_AUTOSIZE);
    while (waitKey(1) < 0 && getWindowProperty(window_name, WND_PROP_AUTOSIZE) >= 0)
    {
        frameset data = pipe.wait_for_frames();           // 等待下一帧
        frame frames = data.get_color_frame()             // RGB框架
                           .apply_filter(color_map);      // 查找并着色深度数据;
        depth_frame depth = data.get_depth_frame();       // 深度框架
        const int w = frames.as().get_width();
        const int h = frames.as().get_height();
        Mat color_image(Size(w, h), CV_8UC3, (void*)frames.get_data(), Mat::AUTO_STEP);   // 由rs2::frame转为cv::Mat
        Mat start_image = color_image;
        color_image = Morphological_process(color_image);
        color_image = get_draw_contours(color_image, start_image, depth);
        imshow(window_name, color_image);
    }
    return EXIT_SUCCESS;
}
// 异常处理 
catch (const rs2::error& e)
{
    cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n    " << e.what() << endl;
    return EXIT_FAILURE;
}
catch (const std::exception& e)
{
    cerr << e.what() << endl;
    return EXIT_FAILURE;
}

       轮廓提取和绘制方面精度不高,经常会括出物体内部的一部分,而且关于距离方面的运用深度不足,需要改进.

你可能感兴趣的:(项目,opencv,人工智能,计算机视觉)