OpenCV的Sample分析:real_time_tracking(5)

OpenCV的Sample分析:real_time_tracking(5)

在之前的分析中,了解了三个比较重要的类kalman,类PnPProblem,以及类RobustMatcher

今天继续分析main函数,

  KalmanFilter KF;         // instantiate Kalman Filter
  int nStates = 18;            // the number of states
  int nMeasurements = 6;       // the number of measured states
  int nInputs = 0;             // the number of control actions
  double dt = 0.125;           // time between measurements (1/FPS)

  initKalmanFilter(KF, nStates, nMeasurements, nInputs, dt);    // init function
  Mat measurements(nMeasurements, 1, CV_64F); measurements.setTo(Scalar(0));
  bool good_measurement = false;


  // Get the MODEL INFO
  vector<Point3f> list_points3d_model = model.get_points3d();  // list with model 3D coordinates
  Mat descriptors_model = model.get_descriptors();                  // list with descriptors of each 3D coordinate

这段代码交代了状态变量,观测变量以及控制变量的个数,分别是18,6,0

把模型中“角点”的3D坐标赋给vector<Point3f>变量list_points3d_model,并且把角点相应的描述子信息赋值给Mat类变量descriptors_model

setTo函数是什么意思呢?CSDN大牛是这样答复的点击打开链接

opencv的setTo函数是将图像设置为某个值,比如有一个Mat src,想将他的值全部设置成0,则可以src.setTo(0)
另外,setTo还有更为高级的用法,比如,对于一个已知的src,我们要将其中大于或者小于某个值的像素值设置为指定的值,则可以如下:
src.setTo(0,src < 10);
这句话的意思是,当src中的某个像素值小于10的时候,就将该值设置成0.
还有一点,这是自己猜想的,前面的那个0可以换成另一个图像:
src.setTo(dst,src < 10);
这里的意思是,对于src中的像素值,当其值小于10的时候,就将该值用dst中相应位置的值进行替换。

下面是加载一段视频的代码,

  namedWindow("REAL TIME DEMO", WINDOW_KEEPRATIO);

  VideoCapture cap;                           // instantiate VideoCapture
  cap.open(video_read_path);                      // open a recorded video

  if(!cap.isOpened())   // check if we succeeded
  {
    cout << "Could not open the camera device" << endl;
    return -1;
  }

对nameWindow以及VideoCapture不陌生吧

  // start and end times
  time_t start, end;

  // fps calculated using number of frames / seconds
  // floating point seconds elapsed since start
  double fps, sec;

  // frame counter
  int counter = 0;

  // start the clock
  time(&start);

  Mat frame, frame_vis;

  while(cap.read(frame) && (char)waitKey(30) != 27) // capture frame until ESC is pressed
  {
        frame_vis = frame.clone();    // refresh visualisation frame
        //..........................
  } 

从这一段基本代码,可以学到一些东西:

(1)常见的计时方式

(2)初始化一个Mat类frame,常见的视频读取的while语句

(3)用frame_vis,起到保护frame的作用

现在正式分析while语句的第一部分,

第一步,特征点匹配

    // -- Step 1: Robust matching between model descriptors and scene descriptors
    vector<DMatch> good_matches;       // to obtain the 3D points of the model
    vector<KeyPoint> keypoints_scene;  // to obtain the 2D points of the scene

    if(fast_match)
    {
      rmatcher.fastRobustMatch(frame, good_matches, keypoints_scene, descriptors_model);
    }
    else
    {
      rmatcher.robustMatch(frame, good_matches, keypoints_scene, descriptors_model);
    }

首先要注意到“model descriptors”以及“scene descriptors”的意思,为了理解其中的意思,需要分析robustMatch这个函数,在这个函数中,frame指视频中这一帧的图像,good_matchs指盒子模型角点的3D坐标,keypoints_scene指相应角点在像素坐标系下的坐标,descriptors_model指盒子模型角点的描述子

void RobustMatcher::robustMatch( const cv::Mat& frame, std::vector<cv::DMatch>& good_matches,
              std::vector<cv::KeyPoint>& keypoints_frame, const cv::Mat& descriptors_model )
{
  // 1a. Detection of the ORB features
  this->computeKeyPoints(frame, keypoints_frame);

  // 1b. Extraction of the ORB descriptors
  cv::Mat descriptors_frame;
  this->computeDescriptors(frame, keypoints_frame, descriptors_frame);

  // 2. Match the two image descriptors
  std::vector<std::vector<cv::DMatch> > matches12, matches21;

  // 2a. From image 1 to image 2
  matcher_->knnMatch(descriptors_frame, descriptors_model, matches12, 2); // return 2 nearest neighbours

  // 2b. From image 2 to image 1
  matcher_->knnMatch(descriptors_model, descriptors_frame, matches21, 2); // return 2 nearest neighbours

  // 3. Remove matches for which NN ratio is > than threshold
  // clean image 1 -> image 2 matches
  ratioTest(matches12);
  // clean image 2 -> image 1 matches
  ratioTest(matches21);

  // 4. Remove non-symmetrical matches
  symmetryTest(matches12, matches21, good_matches);

}

似乎有点复杂,但是值得深入了解(opencv的注释极大方便了使用者的学习!)

可以发现,特征点匹配需要以下几步:

(1)提取frame这一帧的特征点,并且获取该特征点的描述子

(2)建立从frame特征点到descriptors_model特征点的单射关系

            建立从descriptors_model特征点到frame特征点的单射关系

(3)寻找其中的双射关系,把双射的特征点保留下来

fastRobustMatch其实比RobustMatch少了一些罗嗦步骤,所以快一些嘛

第二步,建立2D点到3D点的匹配关系,由于时间的关系,放到下次再说













猜你喜欢

转载自blog.csdn.net/qq_39732684/article/details/80514749