opencv-svm+kcf跟踪

还是基于老鼠

#include <iostream>
#include <fstream>
#include <ctime>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/ml/ml.hpp>
#include <opencv2/tracking.hpp>

using namespace std;
using namespace cv;
using namespace cv::ml;

vector<float> train(HOGDescriptor& hog)
{
	Ptr<SVM> svm = Algorithm::load<SVM>("mouse.xml");

	Mat svmat = svm->getSupportVectors();//获取每个支持向量,
	int cols = svm->getVarCount();//支持向量的维数,也就是svmat.cols
	int rows = svmat.rows;//支持向量的个数
	Mat alphamat = Mat::zeros(rows, cols, CV_32F);//初始化拉格朗日乘子,也就是α_i,α_j,其中alpmat不为0的也就是支持向量
	Mat svindex = Mat::zeros(1, rows, CV_64F);//初始化一个记录支持向量编号的索引,也就是i,j

	Mat Result;//ω
	double rho;//b
	rho = svm->getDecisionFunction(0, alphamat, svindex);//获得决策函数,解出α,b,注意因为y=wx+b,-b=wx-y,-wx=b-y,这里解出来的α和b是反的。 0代表1-2分类 n分类可自己设n
	alphamat.convertTo(alphamat, CV_32F);//因为getDecisionFunction会改变类型 将alphamat元素的数据类型重新转成CV_32F 不然会报错

	Result = -alphamat * svmat;//推导的过程中我们知道是α_i * α_j*x_i*x_j,也就是列向量ω,因为上文我们知道α和b是反的,所以*-1变正

	vector<float> vec;//分类器
	
	for (int i = 0; i < cols; i++)
	{
		vec.push_back(Result.at<float>(0, i));
	} 
	vec.push_back(rho);//+b
	cout << "检测子维数:" << vec.size() << endl;

	ofstream fopen1("svm_vec.txt");//保存vec写入文件
	for (int i = 0; i < vec.size(); i++)
	{
		fopen1 << vec[i] << " ";
	}
	fopen1.close();

	return vec;
}

void track()
{
	Mat frame;
	Rect2d roi;

	HOGDescriptor hog(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);
	vector<float> vec;
	vec = train(hog);//HOG特征 + SVM训练
	hog.setSVMDetector(vec);//设置SVM检测器

	//VideoCapture cap("mouse.mp4",0);//跟踪视频
	VideoCapture cap(0);//跟踪摄像头
	cap >> frame;
	int p = 4;
	resize(frame, frame, Size(frame.cols /p,frame.rows /p));


	if (frame.empty())
	{
		cout << "视频不存在" << endl;
	}
	vector<Rect> found, found_filtered;

	clock_t startTime, finishTime;
	cout << "开始检测" << endl;

	startTime = clock();
	hog.detectMultiScale(frame, found, 0, Size(2, 2), Size(4, 4), 1.05, 2);//多尺度检测目标,返回的矩形从大到小排列

	finishTime = clock();
	cout << "检测所用时间为" << (finishTime - startTime)*1.0 / CLOCKS_PER_SEC << " 秒 " << endl;
	cout << endl << "矩形框的尺寸为 : " << found.size() << endl;

	for (size_t i = 0; i < found.size(); i++)
	{
		Rect r = found[i];
		size_t j;
		for (j = 0; j < found.size(); j++)// 如果有嵌套的话,则取外面最大的那个矩形框放入found_filtered中
			if (j != i && (r & found[j]) == r)
				break;
		if (j == found.size())
			found_filtered.push_back(r);
	}
	cout << "嵌套矩形框尺寸= " << found_filtered.size() << " Rects" << endl;
	for (size_t i = 0; i < found_filtered.size(); i++)//因为检测到的roi总是大于实际的,所以我们做下调整
	{
		roi = found_filtered[i];
		// hog检测结果返回的矩形比实际的要大一些
		roi.x += cvRound(roi.width * 0.1);
		roi.width = cvRound(roi.width * 0.8);
		roi.y += cvRound(roi.height * 0.07);
		roi.height = cvRound(roi.height * 0.8);
	}//多个嵌套矩阵
	Ptr<TrackerKCF> tracker = TrackerKCF::create();
	//下面这三条语句很重要,把多目标框筛出来的框作为感兴趣的区域传递给跟踪器,实现自动跟踪
	
	tracker->init(frame, roi);//追踪第一帧

	while(1)
	{
		cap >> frame;

		resize(frame, frame, Size(frame.cols /p, frame.rows /p));

		tracker->update(frame,roi);//刷新ROI的位置

		rectangle(frame, roi, Scalar(255, 0, 0), 2, 1);

		imshow("捕捉老鼠", frame);

		//quit on ESC button
		if (char(waitKey(1)) == 'q')//按键退出视频
		{
			cv::destroyWindow("捕捉老鼠");
			break;
		}
	}
}
int main()
{
	track();
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值