摄像头:实感摄像头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;
}
轮廓提取和绘制方面精度不高,经常会括出物体内部的一部分,而且关于距离方面的运用深度不足,需要改进.