c_cpp 摄像头物体跟踪定位(应用最小矩形)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp 摄像头物体跟踪定位(应用最小矩形)相关的知识,希望对你有一定的参考价值。

#include<opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include<iostream>
#define BIN_DIV 120

using namespace std;
using namespace cv;

int main()
{
	VideoCapture capture(0);
	Mat srcImg;
	while (1)
	{
		Mat frame;
		capture >> frame;
		frame.copyTo(srcImg);
		Mat xianshi = srcImg.clone();
		Mat redChannel;
		namedWindow("【视频原画】", WINDOW_NORMAL);
		imshow("【视频原画】", srcImg);
		Mat grayImg;
		vector<Mat> channels; //vector容器,用来存放split(需要进行分离的多通道数组,输出的数组或vector容器)
		split(srcImg, channels); //分离色彩通道;进行通道分离的split函数。
		//cvtColor(srcImg,grayImg,COLOR_BGR2GRAY);
		//-----------------------------------------------------------------
		//    根据OpenCV的BGR色彩空间(blue,Green,Red,蓝绿红),
		//    其中channels.at(0)就表示引用取出channels中的蓝色分量,
		//    channels.at(1)就表示引用取出channels中的绿色色分量,
		//    channels.at(2)就表示引用取出channels中的红色分量。
		//-----------------------------------------------------------------
		grayImg = channels.at(0);
		redChannel = channels.at(2);
		namedWindow("【视频灰度画面】", WINDOW_NORMAL);
		imshow("【视频灰度画面】", grayImg);
		//------------------------均值滤波---------------------------------
		//        描述:灰度图经过中值滤波后可以得到去噪后的图片。
		//-----------------------------------------------------------------
		blur(grayImg, grayImg, Size(20, 20), Point(-1, -1));
		namedWindow("【视频均值滤波后】", WINDOW_NORMAL);
		imshow("【视频均值滤波后】", grayImg);
		//----------------------------------------转化为二值图-----------------------------------------
		//  描述:根据原图的蓝色通道和红色通道的大概取值范围,我们可得到比较满意的二值图。
		//        在OpenCV中使用轮廓发现相关函数时候要求输入图像是二值图像,这样便于轮廓提取、边缘提取等操作。
		//-------------------------------------------------------------------------------------------
		Mat midImg1 = grayImg.clone();
		int rowNumber = midImg1.rows;
		int colNumber = midImg1.cols;

		for (int i = 0; i < rowNumber; i++)
		{
			uchar* data = midImg1.ptr<uchar>(i);  //取第i行的首地址
			uchar* redData = redChannel.ptr<uchar>(i);
			for (int j = 0; j < colNumber; j++)
			{
				if (data[j] > BIN_DIV && redData[j] < BIN_DIV / 2)
					data[j] = 0;
				else
					data[j] = 255;
			}
		}
		namedWindow("【视频二值画面】", WINDOW_NORMAL);
		imshow("【视频二值画面】", midImg1);
		//--------------------------------------开运算-----------------------------------------------
		//  描述:目前使用的是开运算
		//        为了去掉物体中少量的黑色部分,可以用闭运算。闭运算目前来看就是把MORPH_OPEN换成MORPH_CLOSE
		//------------------------------------------------------------------------------------------
		Mat midImg2 = midImg1.clone();
		Mat element = getStructuringElement(MORPH_RECT, Size(20, 20));
		morphologyEx(midImg1, midImg2, MORPH_OPEN, element);
		namedWindow("【视频开运算后】", WINDOW_NORMAL);
		imshow("【视频开运算后】", midImg2);
		cout << "midImg1.channel=" << midImg1.channels() << endl;
		cout << "mdiImg1.depth" << midImg1.depth() << endl;
		//---------------------------------查找图像轮廓--------------------------------
		Mat midImg3 = Mat::zeros(midImg2.rows, midImg2.cols, CV_8UC3);
		vector<vector<Point>> contours;
		vector<Vec4i> hierarchy;
		findContours(midImg2, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
		int index = 0;
		for (; index >= 0; index = hierarchy[index][0])
		{
			Scalar color(255, 255, 255);
			drawContours(midImg3, contours, index, color, NULL, 8, hierarchy);
		}
		namedWindow("【视频轮廓画面】", WINDOW_NORMAL);
		imshow("【视频轮廓画面】", midImg3);
		Mat midImg4 = midImg3.clone();
		//--------------------------创建包围轮廓的矩形边界--------------------------
		//             描述:找到能包围轮廓的最小矩形。
		//--------------------------------------------------------------------------
		for (int i = 0; i < contours.size(); i++)
		{
			//每个轮廓
			vector<Point> points = contours[i];
			//对给定的2D点集,寻找最小面积的包围矩形
			RotatedRect box = minAreaRect(Mat(points));
			Point2f vertex[4];
			box.points(vertex);
			//绘制出最小面积的包围矩形
			line(xianshi, vertex[0], vertex[1], Scalar(100, 200, 211), 6, LINE_AA);
			line(xianshi, vertex[1], vertex[2], Scalar(100, 200, 211), 6, LINE_AA);
			line(xianshi, vertex[2], vertex[3], Scalar(100, 200, 211), 6, LINE_AA);
			line(xianshi, vertex[3], vertex[0], Scalar(100, 200, 211), 6, LINE_AA);
			//绘制中心的光标
			Point s1, l, r, u, d;
			s1.x = (vertex[0].x + vertex[2].x) / 2.0;
			s1.y = (vertex[0].y + vertex[2].y) / 2.0;
			l.x = s1.x - 10;
			l.y = s1.y;

			r.x = s1.x + 10;
			r.y = s1.y;

			u.x = s1.x;
			u.y = s1.y - 10;

			d.x = s1.x;
			d.y = s1.y + 10;
			line(xianshi, l, r, Scalar(100, 200, 211), 2, LINE_AA);
			line(xianshi, u, d, Scalar(100, 200, 211), 2, LINE_AA);

			printf("\t 输出内容: 面积和轮廓长度\n");
			//输出内容
			for (unsigned int i = 0; i < contours.size(); i++)
			{
				printf("计算出的面积=%.2f , 长度: %.2f \n", contourArea(contours[i]), arcLength(contours[i], true));
			}
		}
		namedWindow("【绘制的最小面积矩形】", WINDOW_AUTOSIZE);//输出视频自适应尺寸
		imshow("【绘制的最小面积矩形】", xianshi);
		waitKey(30);
	}
	return 0;
}

以上是关于c_cpp 摄像头物体跟踪定位(应用最小矩形)的主要内容,如果未能解决你的问题,请参考以下文章

如何找到移动物体的坐标来绘制矩形

从车辆图像中提取车牌

目标跟踪基于Kalman滤波跟踪视频运动目标matlab代码

opencv 目标跟踪一定要把被跟踪的物体圈出来吗?

matlab调用摄像头运用差帧法实现双物体跟踪

树莓派视觉小车 -- 物体跟踪(OpenCV)