基于颜色的对象检测与跟踪

实现步骤

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;
}

猜你喜欢

转载自blog.csdn.net/m0_61897853/article/details/124098771