机器人视觉检测+跟踪:行人跟随过程中对目标提取特征+匹配

今天上午也是没有很大的成效,一直到下午睡醒(论好的睡眠的重要性),在一篇帖子中看到一种新的写法,opencv3将IplImage转换为Mat格式的写法,在我们的代码中采用这种方式,改到哪里哪里的问题就消失了,这种感觉非常爽!

写完整一点,记录准确以后参考。

我在机器人视觉检测中将kinect采集到的视频数据流进行特征提取和匹配,用的是成熟快速兼于一体的surf加速鲁棒特征进行匹配,这其中的一个方法是需要先将ros中的图像信息格式sensor::message/image通过cv_bridge转换为我们的Mat格式,之后需要将Mat格式再进一步转换为IplImage格式的图像,这是因为我们需要用到cvCreateImage()函数取出来图像的像素深度和图像通道信息,这一步只能对IplImage格式进行操作,需要对原图象进行深拷贝,转换操作完后,我们要不嫌麻烦地再将IplImage图像转换为Mat图像,之后就是愉快的送入到特征检测计算器中计算,detectAndCompute()需要的参数格式很严格,上述的转换格式的原因就是需要满足这样的参数格式,详细的注释都给出在代码中。

走了很多弯路,主要就是格式转换中的代码写的原因,版本不同有不同的写法,可能只有一种合适版本的写法可以编译成功。

看代码:

  //beginging  
  Ptr<SURF> surf;
  surf = SURF::create(800);

  vector<KeyPoint>keypoint1, keypoint2;

  frame = get_one_frame(); 
  body_rect = client->getBodyRect(frame); 
  //image1 = resize(frame, rect.x:(rect.x+rect.width), rect.y:(rect.y+rect.higth))
  //Mat image1; 
  cv_bridge::CvImagePtr cv_ptr1 =cv_bridge::toCvCopy(frame, "bgr8");
  cv::Mat imframe = cv_ptr1->image;


  IplImage *im, *img1;
  CvRect rectInImage1;
  rectInImage1 = cvRect(body_rect.x, body_rect.y,body_rect.width, body_rect.height);
  CvSize size1;
  size1.width = rectInImage1.width;
  size1.height = rectInImage1.height;
  img1 = cvCreateImage(size1, imframe.depth(), imframe.channels());
  //frame->depth
  //img1 = cvCreateImage(size1, IPL_DEPTH_8U, 3);
  im = cvCreateImage(imframe.size(), imframe.depth(), imframe.channels());
  cvConvert(&imframe, im);    //深拷贝,Mat imframe -> IplImage* im
  cvSetImageROI(im, rectInImage1);//void cvSetImageROI(IplImage* image,CvRect rect);
  cvCopy(img1, im);//img1是从im上提取的目标框区域
  //cvtcolor(img1, img_1, CV_RGB2GRAY);
  //将IplImage格式的img1转换为cvMat格式的img01
  //CvMat *img01 = cvCreateMat(img1->height, img1->width, CV_64FC3);
  //cvConvert(img1, img01);
  
  //直接利用Mat定义一个Mat类矩阵,强制将括号内的IplImage*类型图像转换成Mat类
  //cv::Mat img01(IplImage* img1); 
  //Mat img01(IplImage* img1);//高版本不行
  cv::Mat img01 = cv::cvarrToMat(img1);//对应的写法可以编译
  Mat img_1, image1;  
  //void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 );
  cvtColor(img01, img_1, COLOR_RGB2GRAY);//灰度图img_1
  //检测特征点
  //detector.detect(img_1, keypoint1)
  /* detectAndCompute (InputArray image, InputArray mask, 
  std::vector< KeyPoint > &keypoints, OutputArray descriptors, 
  bool useProvidedKeypoints=false) */
  surf->detectAndCompute(img_1, Mat(), keypoint1, image1); //输出mat存放所有的特征点描述向量
  //ending 

我们机器人上的相机获得一帧图像后保存,之后目标跟踪后丢失后会出现问题,再次检测目标时进行特征匹配,并作目标筛选,获得精确目标。

为求完整性,继续上代码

    //Mat image2;
    cv_bridge::CvImagePtr cv_ptr2 =cv_bridge::toCvCopy(tracking_frame, "bgr8");
    cv::Mat imgframe = cv_ptr2->image;
    IplImage *ime, *img2;
    CvRect rectInImage2;
    rectInImage2 = cvRect(body_track_rect.x, body_track_rect.y,
                          body_track_rect.width, body_track_rect.height);
    CvSize size2;
    size2.width = rectInImage2.width;
    size2.height = rectInImage2.height;
    img2 = cvCreateImage(size2, imgframe.depth(), imgframe.channels());
    //img2 = cvCreateImage(size2, IPL_DEPTH_8U, 3);  //bug
    ime =cvCreateImage(imgframe.size(), imgframe.depth(), imgframe.channels());
    cvConvert(&imgframe, ime);
    cvSetImageROI(ime, rectInImage2);
    cvCopy(img2, ime);//img2是从tracking_frame上提取的目标框区域
    //cvtColor(img2, img_2, COLOR_RGB2GRAY);
    //这是
    //CvMat *img02 = cvCreateMat(img2->height, img2->width, CV_64FC3);
    //cvConvert(img2, img02);

    //cv::Mat img02(IplImage* img2); 
    cv::Mat img02 = cv::cvarrToMat(img2);
    cv::Mat img_2, image2; 
    cvtColor(img02, img_2, COLOR_RGB2GRAY);

    //检测特征点
    //detector.detect(img_2, keypoint2);
    surf->detectAndCompute(img_2, Mat(), keypoint2, image2);

    //计算特征点描述子
    //SurfDescriptorExtractor extractor;
    //Mat descriptor1, descriptor2;

    //extractor.compute(img1, keypoint1, descriptor1);
    //extractor.compute(img2, keypoint2, descriptor2);

    //使用flann匹配
    FlannBasedMatcher matcher;
    vector<DMatch>matches;
    matcher.match(image1, image2, matches);//匹配结束

    sort(matches.begin(), matches.end());//将matches进行排序

    vector<DMatch>good_matches;
    int ptsPairs = std::min(50, (int)(matches.size() * 0.15));
    for (int i = 0; i < ptsPairs; i++)//保存50个匹配结果
    {
      good_matches.push_back(matches[i]); 
    }

下一步还需要做的是对匹配结果进行筛选,由于匹配结果是<DMatch>的C++容器类向量,如何进行筛选也是有、东西的。

参考资料

https://blog.csdn.net/zssureqh/article/details/7608024

https://docs.opencv.org/3.3.1/d3/d63/classcv_1_1Mat.html

https://blog.csdn.net/fu_shuwu/article/details/77399835

https://www.cnblogs.com/edver/p/5187190.html

https://blog.csdn.net/yang_xian521/article/details/7755101

https://www.cnblogs.com/anqiang1995/p/7442984.html

猜你喜欢

转载自blog.csdn.net/Synioe/article/details/81630337