LK动态捕捉

本文介绍了一个基于OpenCV的LK光流法实现的动态捕捉程序。该程序通过摄像头捕捉实时视频帧,并利用特征点追踪技术实现动态物体的跟踪。支持用户手动添加或删除特征点,同时提供黑白背景切换功能,增强动态捕捉效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <opencv2/opencv.hpp>
#include <iostream>
#include <algorithm>
using namespace std;
using namespace  cv;
//创建鼠标消息
Point2f g_point;//保存鼠标获取的特征点
bool g_AddRemovePt;//是否添加移动点
void MouseEvent(int event, int x, int y, int, void *)
{
	if (event==EVENT_LBUTTONDOWN)
	{
		g_point = Point2f(x, y);
		g_AddRemovePt = true;
	}
	return;
}
void Help()
{
	cout << "使用说明:"
		<< "\t ESC 退出程序\n"
		<< "\t n 黑色背景下,进行动态的捕捉\n"
		<< "\t c 移除所有的显示的特征点\n"
		<< "\t r 初始化特征点" << endl;
	return;
}
int main()
{
	VideoCapture capture(0);
	if (!capture.isOpened())
	{
		cout << "摄影头打开失败" << endl;
		return -1;
	}
	Mat frame, img, preImg, gray;
	bool binit = false;
	bool bNight = false;
	string tile = "LK 动态捕捉";
	namedWindow(tile);
	setMouseCallback(tile, MouseEvent, NULL);
	vector<Point2f> DynPoints[2];//捕捉的动态点,一个前一帧,一个后一帧
	while (true)
	{
		capture >> frame;
		if (frame.empty())
		{
			cout << "不能捕捉到影像" << endl;
			return -1;
		}
		flip(frame, frame, 1);
		frame.copyTo(img);
		cvtColor(img, gray, CV_BGR2GRAY);//转换为灰度影像
		if (bNight)//是否是黑色背景
		{
			img = Scalar::all(0);
		}
		if (binit)//是否需要捕捉特征点
		{
			//找到特征点
			goodFeaturesToTrack(gray, DynPoints[1], 500, 0.001, 5);
			//精确计算角点
			cornerSubPix(gray, DynPoints[1], Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS, 30, 0.003));
			g_AddRemovePt = false;//每一个判断中都要判断
		}
		else if (!DynPoints[0].empty())
		{
			//进行动态捕捉过程
			vector<unsigned char >stat;
			vector<float> err;
			stat.clear();
			err.clear();
			calcOpticalFlowPyrLK(preImg, gray, DynPoints[0], DynPoints[1], stat, err);
			//更新又进一步的特征点
			size_t k = 0;
			for (size_t i = 0; i < DynPoints[1].size();++i)
			{
				if (g_AddRemovePt)
				{
					if (norm(g_point-DynPoints[1][i])<=5)//假如手动添加的特征点和检测到的特征点相距比较近的话,那么新提取的特征的不计算在内
					{
						g_AddRemovePt = false;
						continue;
					}
				}
				if (!stat[i])
				{
					continue;
				}
				DynPoints[1][k++] = DynPoints[1][i];//更新特征点
				circle(img, DynPoints[1][i], 3, Scalar(0, 255, 0), -1, CV_AA);
			}
			//更新点矢量的大小
			DynPoints[1].resize(k);
		}
		if (g_AddRemovePt&&DynPoints[1].size()<500)//小于提取的最大特征点
		{
			//添加特征点
			vector<Point2f> temp;
			temp.clear();
			temp.push_back(g_point);
			//精确的角点坐标
			cornerSubPix(gray, temp, Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS, 30, 0.003));
			DynPoints[1].push_back(temp[0]);//在影像中的特征点
			g_AddRemovePt = false;
		}
		imshow(tile, img);
		std::swap(DynPoints[0], DynPoints[1]);
		gray.copyTo(preImg);
		binit = false;
		char c = waitKey(10);
		switch (c)
		{
		case 'r':
			binit = true;
			break;
		case 'n':
			bNight = !bNight;
			break;
		case 'c':
			DynPoints[0].clear();
			DynPoints[1].clear();
			break;
		case 27:
			return 0;
			break;
		default:
			break;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值