【opencv】动态背景下运动目标检测 SURF配准差分

来源:互联网 发布:mac book air视频剪辑 编辑:程序博客网 时间:2024/05/24 06:50

主要思路是,读入视频,隔帧采用SURF计算匹配的特征点,进而计算两图的投影映射矩阵,做差分二值化,连通域检测,绘制目标。

如果背景是静态的采用camshift即可。

本文方法速度debug下大概2-3帧,release下8-9帧(SURF部分,不包含连通域以及绘制),后续可增加选定目标,动态模版小邻域中跟踪目标。实现对动态背景下的运动目标检测,模版跟踪速度可达150帧。

 

环境:opencv2.4.9 + vs2012

#include <iostream>#include <opencv2/opencv.hpp>#include <opencv2/nonfree/nonfree.hpp>     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<double>(getTickCount());//开始计时                //灰度图转换          Mat image1,image2;            cvtColor(image01,image1,CV_RGB2GRAY);          cvtColor(image02,image2,CV_RGB2GRAY);          //提取特征点            SurfFeatureDetector surfDetector(2500);  // 海塞矩阵阈值,高一点速度会快些        vector<KeyPoint> 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<DMatch> matchePoints;            matcher.match(imageDesc1,imageDesc2,matchePoints,Mat());          sort(matchePoints.begin(),matchePoints.end()); //特征点排序            //获取排在前N个的最优匹配特征点          vector<Point2f> 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"<<homo<<endl<<endl; //输出映射矩阵          //图像配准          Mat imageTransform1,imgpeizhun,imgerzhi;          warpPerspective(image01,imageTransform1,homo,Size(image02.cols,image02.rows));            //imshow("经过透视矩阵变换后",imageTransform1);          absdiff(image02, imageTransform1, imgpeizhun);        //imshow("配准diff", imgpeizhun);          threshold(imgpeizhun, imgerzhi, 50, 255.0 , CV_THRESH_BINARY);        //imshow("配准二值化", imgerzhi);        //输出所需时间        time0 = ((double)getTickCount()-time0)/getTickFrequency();        cout<<1/time0<<endl;        Mat temp,image02temp;        float m_BiLi = 0.9;        image02temp = image02.clone();        cvtColor(imgerzhi,temp,CV_RGB2GRAY);          //检索连通域        Mat se=getStructuringElement(MORPH_RECT, Size(5,5));        morphologyEx(temp, temp, MORPH_DILATE, se);        vector<vector<Point>> 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<uchar>(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<KeyPoint> 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<L2<float>> matcher;        FlannBasedMatcher matcher;      vector<DMatch> matchePoints;        matcher.match(imageDesc1,imageDesc2,matchePoints,Mat());        //提取强特征点      double minMatch=1;      double maxMatch=0;      for(int i=0;i<matchePoints.size();i++)      {          //匹配值最大最小值获取          minMatch=minMatch>matchePoints[i].distance?matchePoints[i].distance:minMatch;          maxMatch=maxMatch<matchePoints[i].distance?matchePoints[i].distance:maxMatch;      }      //最大最小值输出      cout<<"最佳匹配值是: "<<minMatch<<endl;      cout<<"最差匹配值是: "<<maxMatch<<endl;        //获取排在前边的几个最优匹配结果      vector<DMatch> goodMatchePoints;     for(int i=0;i<matchePoints.size();i++)     {         if(matchePoints[i].distance<minMatch+(maxMatch-minMatch)/2)         {             goodMatchePoints.push_back(matchePoints[i]);          }     }       //绘制最优匹配点      Mat imageOutput;      drawMatches(image01,keyPoint1,image02,keyPoint2,goodMatchePoints,imageOutput,Scalar::all(-1),         Scalar::all(-1),vector<char>(),DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);         imwrite("匹配图.jpg",imageOutput);        return 0;    }


0 0
原创粉丝点击