#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;
}
}
}
LK动态捕捉
最新推荐文章于 2020-02-26 22:51:28 发布