根据opencv3中camshiftdemo实现meanshift目标追踪

把opencv3自带的camshiftdemo删删改改,就实现了meanshift的目标追踪,比起camshift没有什么实际应用价值。

运行效果和代码:

#include <iostream>
#include "opencv2/opencv.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>

using namespace cv;
using namespace std;

Mat image;
bool selectObject = false;
int trackObject = 0;
Point origin;
Rect selection;

//鼠标选择函数
static void onMouse(int event, int x, int y, int, void*)
{
	if (selectObject)
	{
		selection.x = MIN(x, origin.x);//选择区域的x坐标选起点与当前点的最小值,保证鼠标不管向右下角还是左上角拉动都正确选择
		selection.y = MIN(y, origin.y);
		selection.width = std::abs(x - origin.x);
		selection.height = std::abs(y - origin.y);

		selection &= Rect(0, 0, image.cols, image.rows);//确保所选矩形在图片范围内
	}

	switch (event)
	{
	case EVENT_LBUTTONDOWN:	//按下鼠标左键,进行赋初值
		origin = Point(x, y);
		selection = Rect(x, y, 0, 0);
		selectObject = true;
		break;
	case EVENT_LBUTTONUP:	//鼠标左键抬起
		selectObject = false;
		if (selection.width > 0 && selection.height > 0)
			trackObject = -1;   // 置-1,主程序开始进行meanshift
		break;
	}
}

int main(int argc, const char** argv) {
	VideoCapture cap(0);
	Rect trackWindow;
	int hsize = 16;		//直方图特征子区间bin的数目,分成16个区间
	float hranges[] = { 0,180 };//色度 hue 范围
	const float* phranges = hranges;


	//摄像头未打开的处理方式
	if (!cap.isOpened())
	{
		cout << "***Could not initialize capturing...***\n";
		
	}

	namedWindow("meanShift", 0);
	namedWindow("Histogram", 0);
	setMouseCallback("meanShift", onMouse, 0);
	
	Mat frame,hsv, hue, hist, histimg = Mat::zeros(200, 320, CV_8UC3), backproj;
	bool paused = false;
	while (true)
	{
		if (!paused) 
		{
			cap >> frame;
			frame.copyTo(image);
			cvtColor(image, hsv, COLOR_BGR2HSV);
			if (trackObject)
			{
				int from_to[] = { 0, 0 };
				hue.create(hsv.size(), hsv.depth());
				mixChannels(&hsv, 1, &hue, 1, from_to, 1);//提取h分量

				//画直方图
				if (trackObject < 0)
				{
					Mat roi(hue, selection);
					calcHist(&roi, 1, 0, Mat(), hist, 1, &hsize, &phranges);
					normalize(hist, hist, 0, 255, NORM_MINMAX);			//直方图归一化到0-255	
					trackWindow = selection;
					trackObject = 1;									//置1,除非重新框选目标,否则只执行一次

					histimg = Scalar::all(0);
					int binW = histimg.cols / hsize;//320/16;每个区间可以占用histimg20个列(column)
					Mat buf(1, hsize, CV_8UC3);//定义一个缓冲单bin矩阵,1行16列
					for (int i = 0; i < hsize; i++)
						buf.at<Vec3b>(i) = Vec3b(saturate_cast<uchar>(i*180. / hsize), 255, 255);//Vec3b为3个char值的向量,存放颜色数据
					cvtColor(buf, buf, COLOR_HSV2BGR);

					for (int i = 0; i < hsize; i++)
					{
						int val = saturate_cast<int>(hist.at<float>(i)*histimg.rows / 255);//获取直方图高度,根据histimg图像的高换算成0到histimg.rows的值
						rectangle(histimg, Point(i*binW, histimg.rows),//画出直方图,左上角坐标,右下角坐标,高度,颜色,大小,线型
							Point((i + 1)*binW, histimg.rows - val),//rows-va1是因为矩阵是左上角开始数的,y轴向下,而要画的图是y轴向上
							Scalar(buf.at<Vec3b>(i)), -1, 8);
					}
				}
				//进行meanshift
				calcBackProject(&hue, 1, 0, hist, backproj, &phranges);
				TermCriteria criteria(TermCriteria::EPS | TermCriteria::COUNT, 10, 1);
				meanShift(backproj, trackWindow, criteria);
				rectangle(image, trackWindow, Scalar(255, 0, 0), 3);
			}


		}
		if (selectObject && selection.width>0 && selection.height > 0)

		{

			Mat roi(image, selection);

			bitwise_not(roi, roi);

		}
		imshow("meanShift", image);
		imshow("Histogram", histimg);

		char c = (char)waitKey(10);//等待用户按键
		if (c == 27)
			break;



	
	}
return 0;
}

 

 

 

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值