主要思路是,读入视频,隔帧采用SURF计算匹配的特征点,进而计算两图的投影映射矩阵,做差分二值化,连通域检测,绘制目标。
如果背景是静态的采用camshift即可。
本文方法速度debug下大概2-3帧,release下8-9帧(SURF部分,不包含连通域以及绘制),后续可增加选定目标,动态模版小邻域中跟踪目标。实现对动态背景下的运动目标检测,模版跟踪速度可达150帧。
环境:opencv2.4.9 + vs2012
#include
#include
#include
using namespace cv;
using namespace std;
void main()
{
//VideoCapture capture(0);
VideoCapture capture("3.mov");
Mat image01,image02,imgdiff;
while (true)
{
//隔两帧配准
capture >> image01;
if (image01.empty())
{
break;
}
capture >> image02;
capture >> image02;
if (image02.empty())
{
break;
}
//GaussianBlur(image02, image02, Size(3,3), 0);
double time0 = static_cast(getTickCount());//开始计时
//灰度图转换
Mat image1,image2;
cvtColor(image01,image1,CV_RGB2GRAY);
cvtColor(image02,image2,CV_RGB2GRAY);
//提取特征点
SurfFeatureDetector surfDetector(2500); // 海塞矩阵阈值,高一点速度会快些
vector keyPoint1,keyPoint2;
surfDetector.detect(image1,keyPoint1);
surfDetector.detect(image2,keyPoint2);
//特征点描述,为下边的特征点匹配做准备
SurfDescriptorExtractor SurfDescriptor;
Mat imageDesc1,imageDesc2;
SurfDescriptor.compute(image1,keyPoint1,imageDesc1);
SurfDescriptor.compute(image2,keyPoint2,imageDesc2);
//获得匹配特征点,并提取最优配对
FlannBasedMatcher matcher;
vector matchePoints;
matcher.match(imageDesc1,imageDesc2,matchePoints,Mat());
sort(matchePoints.begin(),matchePoints.end()); //特征点排序
//获取排在前N个的最优匹配特征点
vector imagePoints1,imagePoints2;
for(int i=0; i<(int)(matchePoints.size()*0.25); i++)
{
imagePoints1.push_back(keyPoint1[matchePoints[i].queryIdx].pt);
imagePoints2.push_back(keyPoint2[matchePoints[i].trainIdx].pt);
}
//获取图像1到图像2的投影映射矩阵 尺寸为3*3
Mat homo=findHomography(imagePoints1,imagePoints2,CV_RANSAC);
//cout<<"变换矩阵为:\n"<> contours;
findContours(temp, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
if (contours.size()<1)
{
continue;
}
for (int k = 0; k < contours.size(); k++)
{
Rect bomen = boundingRect(contours[k]);
//省略由于配准带来的边缘无效信息
if (bomen.x > image02temp.cols * (1 - m_BiLi) && bomen.y > image02temp.rows * (1 - m_BiLi)
&& bomen.x + bomen.width < image02temp.cols * m_BiLi && bomen.y + bomen.height < image02temp.rows * m_BiLi)
{
rectangle(image02temp, bomen, Scalar(255,0,255), 2, 8, 0);
}
}
/*
for (int i = 50; i < image02.rows - 100; i++)
{
for (int j = 50; j < image02.cols - 100; j++)
{
uchar pixel = temp.at(i,j);
if (pixel == 255)
{
Rect bomen(j-7, i-7, 14, 14);
rectangle(image02, bomen, Scalar(255,255,255),1,8,0);
}
}
}
*/
imshow("检测与跟踪",image02temp);
waitKey(20);
}
}
检测远处运动的车辆
surf消除误匹配点
int surf2(Mat image01, Mat image02)
{
Mat image1,image2;
image1=image01.clone();
image2=image02.clone();
//提取特征点
SurfFeatureDetector surfDetector(2000); //hessianThreshold,海塞矩阵阈值,并不是限定特征点的个数
vector keyPoint1,keyPoint2;
surfDetector.detect(image1,keyPoint1);
surfDetector.detect(image2,keyPoint2);
//绘制特征点
drawKeypoints(image1,keyPoint1,image1,Scalar::all(-1),DrawMatchesFlags::DEFAULT);
drawKeypoints(image2,keyPoint2,image2,Scalar::all(-1),DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
/* imshow("KeyPoints of image1",image1);
imshow("KeyPoints of image2",image2); */
//特征点描述,为下边的特征点匹配做准备
SurfDescriptorExtractor SurfDescriptor;
Mat imageDesc1,imageDesc2;
SurfDescriptor.compute(image1,keyPoint1,imageDesc1);
SurfDescriptor.compute(image2,keyPoint2,imageDesc2);
//特征点匹配并显示匹配结果
//BruteForceMatcher> matcher;
FlannBasedMatcher matcher;
vector matchePoints;
matcher.match(imageDesc1,imageDesc2,matchePoints,Mat());
//提取强特征点
double minMatch=1;
double maxMatch=0;
for(int i=0;imatchePoints[i].distance?matchePoints[i].distance:minMatch;
maxMatch=maxMatch goodMatchePoints;
for(int i=0;i(),DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
imwrite("匹配图.jpg",imageOutput);
return 0;
}