机器人视觉项目:视觉检测识别+机器人跟随(13)

收获巨大啊

总结一下编译成功的路线,不容易啊,要哭了。

今天上午也是没有很大的成效,一直到下午睡醒(论好的睡眠的重要性),在一篇帖子中看到一种新的写法,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++容器类向量,如何进行筛选也是有、东西的。


顺势将特征匹配的结果进行筛选,并把代码做了实现,思路是用matches[i].distance判断是否满足条件,由于网上能够查阅到的资料仅仅是将计算得到的匹配特征点用drawMatch()绘制两幅图像的匹配结果,我这里是自己进行了匹配筛选,编译是能够成功的。

double averagematch_dist =0;
    for(int i = 0; i < ptsPairs; i++)
    {
     averagematch_dist = averagematch_dist + good_matches[i].distance / ptsPairs;
    }
    //averagematch = 0.5 * (good_matches[0].distance + good_matches[ptsPairs].distance);
    if(!(good_matches[0].distance < 1.0 &&
       good_matches[ptsPairs].distance < 1.0 &&
       (good_matches[0].distance - averagematch_dist < 0.5 ) &&
        good_matches[ptsPairs].distance - averagematch_dist < 0.5 ))
      continue;
    /*
      double max_dist = 0;
      double min_dist = 100;
      for(int i = 0; i < descriptor1.rows; i++)
      {
        double dist = matches[i].distance;
        if(dist < min_dist)
          min_dist = dist;
       if(dist > max_dist)
          max_dist = dist;
      }//得到匹配结果中的最小距离和最大距离
​
      //处理匹配结果:判断当前匹配的对象是否为目标,仅根据最大最小匹配距离,能否进行判断?
      if(!(min_dist < 1.0 || (max_dist - min_dist) <  2.0))// matching failed
      {
       //tracking_frame = tracking_frame;
       //body_track_rect = body_track_rect;
      continue;
      }
    */

参考资料

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/82836978