c++ opencv4.5 CAMShift目标跟踪

前言

以下为camshift目标跟踪的代码

代码

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;
//HSV
int smin = 30;
int smax = 255;
int vmin = 40;
int vmax = 255;
//calcHist参数
int histSize = 16;//区间的个数
float hue_ranges[] = { 0,180 };
const float* ranges = hue_ranges;


int main(int argc, char** argv)
{
	VideoCapture capture;
	//capture.open(0);

	capture.open(0);
	if (!capture.isOpened())
	{
		cout << "could not load video..." << endl;
		return -1;
	}

	bool firstRead = true;//用于判断是否第一次读取视频

	
	Rect selection;//selectROI用鼠标选择的ROI区域
	Mat frame,blur,hsv, mask, hue, temp_histogram, backprojection;
	Mat Histogram = Mat::zeros(300, 300, CV_8UC3);
	namedWindow("CAMShift Tracking", WINDOW_AUTOSIZE);
	while (capture.read(frame))
	{
		if (firstRead)
		{
			//获取第一帧的ROI区域
			Rect2d first_img = selectROI("CAMShift Tracking", frame);//在"CAMShift Tracking"窗口的frame图像上用鼠标选择ROI区域
			selection.x = first_img.x;
			selection.y = first_img.y;
			selection.width = first_img.width;
			selection.height = first_img.height;
			cout << "ROI的x值为:		" << selection.x << endl;
			cout << "ROI的y值为:		" << selection.y << endl;
			cout << "ROI的width值为:	" << selection.width << endl;
			cout << "ROI的height值为:	" << selection.height << endl;
			
		}


		GaussianBlur(frame,blur,Size(5,5),3,3);//使用高斯滤波进行去噪
		cvtColor(blur, hsv, COLOR_BGR2HSV);//转换到HSV空间
		//测试矩阵frame的元素是否在其他两个矩阵的值之间//提取黄色
		inRange(hsv, Scalar(0, smin, vmin), Scalar(180, smax, vmax), mask);

		hue = Mat(hsv.size(), hsv.depth());
		int channels[] = { 0,0 };//fromto映射//指定被复制通道与要复制到的位置组成的索引对
		size_t npairs = 1; //指定被复制通道与要复制到的位置channels[]组成的索引对
		mixChannels(&hsv, 1, &hue, 1, channels, npairs);	//输入矩阵通道 重新排列到 输出矩阵通道(HSV中的H值)

		if (firstRead)
		{
			//计算ROI直方图
			Mat ROI(hue, selection);//Mat& image , Rect& roi
			Mat MaskROI(mask, selection);
			calcHist(&ROI, 1, 0, MaskROI, temp_histogram, 1, &histSize, &ranges);//计算直方图
			normalize(temp_histogram, temp_histogram, 0, 255, NORM_MINMAX);//归一化

			//显示直方图图像
			int bins = Histogram.cols / histSize; //300/16 = 18.5 单个区间宽度
			//定义一个缓冲单bins矩阵,1行16列,用于存放颜色数据,用于直方图histSize个bin的“染色”
			Mat ColorIndex = Mat(1, histSize, CV_8UC3);//1行histSize=16列
			for (int i = 0; i < histSize; i++)
			{
				ColorIndex.at<Vec3b>(0, i) = Vec3b(saturate_cast<uchar>(i * 180 / histSize), 255, 255);//只是为了好看
			}
			cvtColor(ColorIndex, ColorIndex, COLOR_HSV2BGR);
			for (int j = 0; j < histSize; j++)
			{
				//value是直方图temp_histogram的相对Histogram的高度
				//temp_histogram.at(i)获取了第i个bin直方图数据,除以255后得到百分比
				//再乘以Histogram的行数就得到了相对高度,最后进行int的强制类型转换,转换为整数。
				int  value = saturate_cast<int>(temp_histogram.at<float>(j) * Histogram.rows / 255);
				//之后使用rectangle()函数进行16个bin的绘制
				//值得注意的是矩阵的坐标系以左上角为原点,y轴是向下的
				//而需要展示给人看的直方图图案是左下角为原点,y轴向上的
				//因此rectangle的两个标定点的纵坐标是Histogram.rows和(Histogram.rows - val)而不是0和val
				rectangle(Histogram,
					Point(j * bins, Histogram.rows), //矩阵对角点:左下角
					Point((j + 1) * bins, Histogram.rows - value), //矩阵对角点:右上角
					Scalar(ColorIndex.at<Vec3b>(0, j)), -1, 8, 0);
			}
			firstRead = false;//需要绘制第一帧的直方图
		}

		//直方图反向投影
		/*void calcBackProject(
			const Mat* images,  //输入的数组
			int nimages,        //输入数组的个数
			const int* channels,    //需要统计的通道索引
			InputArray hist,    //输入的直方图
			OutputArray backProject,//目标的反向投影
			const float** ranges,   //每一位数值的取值范围
			double scale=1,     //输出方向投影的缩放因子
			bool uniform=true   //指示直方图是否均匀的标识符
			)
		*/
		//用来计算像素和直方图模型中像素吻合度的方法
		calcBackProject(&hue, 1, 0, temp_histogram, backprojection, &ranges);
		backprojection &= mask;//a&=b 即 a=a&b  其中&为位与运算//给b取了一个别名叫a,所有对b的操作都是直接作用于a

		//CAMShift
		RotatedRect trackBox = CamShift(
			backprojection, //反向投影
			selection,//矩形搜索框
			TermCriteria((TermCriteria::COUNT | TermCriteria::EPS), 10, 1));//迭代中止条件

		//绘制位置更新显示在frame上

		//---------------------------------获取CamShift的返回值,是一个旋转矩形,以下为绘制跟踪结果的部分
		ellipse(frame, trackBox, Scalar(255, 0, 255), 3, 8);//根据旋转矩形绘制一个椭圆形显示在图像上作为追踪结果。
		Point2f vertices[4];//定义存储4个x,y变量的数组
		trackBox.points(vertices);//将旋转矩形的四个顶点值传入数组 
		for (int i = 0; i < 4; i++)//绘制旋转矩形的四条边
			line(frame, vertices[i], vertices[(i + 1) % 4], Scalar(0, 255, 0));
		Rect brect = trackBox.boundingRect();//返回最小旋转角度为0的外接矩形
		rectangle(frame, brect, Scalar(255, 0, 0));//绘制外接矩形
		//----------------------------------


		if (firstRead)
		{
			firstRead = false;
		}

		imshow("CAMShift Tracking", frame);
		imshow("Histogram", Histogram);


		char c = waitKey(1);
		if (c == 27)
		{
			break;
		}
	}

	capture.release();
	//waitKey(0);
	destroyAllWindows();
	return 0;
}

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页