实现步骤
1. inRange过滤
2. 形态学操作提取
3. 轮廓提取
4. 外接矩形获取
5. 位置标定
API
// 该函数输出的dst是一幅二值化之后的图像
void inRange(InputArray src,
InputArray lowerb,
InputArray upperb,
OutputArray dst
);
参数解释:
1:输入要处理的图像,可以为单通道或多通道。
2:包含下边界的数组或标量。
3:包含上边界数组或标量。
4:输出图像,与输入图像src 尺寸相同且为CV_8U 类型。
代码实现
#include<iostream>
#include <string.h>
#include<opencv2/opencv.hpp>
#include<opencv2/imgproc.hpp>
#include<librealsense2/rs.hpp>
#include <librealsense2/h/rs_option.h>
using namespace std;
using namespace cv;
using namespace rs2;
vector<vector<Point>> contours;
vector<Vec4i> hierachy;
// 图像处理函数
Mat InRange_Morphological_Process(Mat img)
{
Mat dst, src;
Scalar yellow_max = Scalar(0, 255, 255);
Scalar yellow_min = Scalar(1, 230, 230);
inRange(img, yellow_min, yellow_max, img);
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
Mat kernel2 = getStructuringElement(MORPH_RECT, Size(3, 3));
morphologyEx(img, dst, MORPH_OPEN, kernel);
dilate(dst, src, kernel2);
return src;
}
// 将表示距离的数字转为字符串的函数
string Convert(Point x)
{
ostringstream oss;
oss << x;
string str(oss.str());
return str;
}
// 绘制带旋转角度的矩形的函数
Mat draw_Wuhu(Mat start_contour)
{
vector<RotatedRect> 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 Draw_Location(Mat img_contour)
{
findContours(img_contour, img_contour, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
vector<Moments> contour_moment(contours.size());
vector<Point2f> 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(img_contour, centerpos[i], 3, Scalar(250, 250, 10));
string ch = Convert(centerpos[i]);
putText(img_contour, ch, centerpos[i], FONT_HERSHEY_SIMPLEX, 2, Scalar(0, 0, 250), 1, 8, false);
img_contour = draw_Wuhu(img_contour);
}
}
return img_contour;
}
//主函数
int main(int argc, char* argv[]) try
{
pipeline pipe;
pipe.start();
const auto window_name = " color_Image";
namedWindow(window_name, WINDOW_AUTOSIZE);
const auto window2_name = " start_Image";
namedWindow(window2_name, WINDOW_AUTOSIZE);
while (waitKey(0) < 0 && getWindowProperty(window_name, WND_PROP_AUTOSIZE) >= 0)
{
frameset data = pipe.wait_for_frames(); // 等待下一帧
frame frames = data.get_color_frame();
const int w = frames.as<video_frame>().get_width();
const int h = frames.as<video_frame>().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 = InRange_Morphological_Process(color_image);
start_image = Draw_Location(color_image);
imshow(window2_name, start_image);
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;
}