2 u014173467 u014173467 于 2016.01.21 10:28 提问

单个模板的多目标识别 OPENCV

初学图像处理, 请多多指教!

我现在想解决的是用单个模板去匹配测试图中的多个目标(目标有仿射变换),参照了现成的一些SURF算法提取特征值进行匹配,可是这样只能匹配到一个目标。
后来发现匹配的knnmatch函数可以对一个 query descriptor返回k个最佳匹配,可是效果并不好, 不知有什么建议?十分感谢!

代码如下:

  Mat img1 = imread( "q.jpg", CV_LOAD_IMAGE_GRAYSCALE );
  Mat img2 = imread( "qw.jpg", CV_LOAD_IMAGE_GRAYSCALE );

    //-- Step 1: Detect the keypoints using Sift Detector
  SiftFeatureDetector  detector( hessian );

  vector<KeyPoint> queryKeypoints, trainKeypoints;

  detector.detect( img1, queryKeypoints );
  detector.detect( img2, trainKeypoints );

    //-- Step 2: Extract the keypoints using Sift Extractor
    Mat queryDescriptor,trainDescriptor;// extract keypoints
     SiftDescriptorExtractor extractor;  //Create Descriptor Extractor
    extractor.compute( img1, queryKeypoints, queryDescriptor );
    extractor.compute( img2, trainKeypoints, trainDescriptor );

        //--Step3: Match 
        vector<vector<DMatch>> m_knnMatches;
        vector<DMatch>m_Matches;
        vector<DMatch>n_Matches;
    const float minRatio = 1.f / 1.5f;

        matcher.knnMatch(queryDescriptor,trainDescriptor,m_knnMatches,3);
        for (size_t i=0; i<m_knnMatches.size(); i++)
        {
            const cv::DMatch& bestMatch = m_knnMatches[i][0];
            const cv::DMatch& betterMatch = m_knnMatches[i][1];
            const cv::DMatch& betterrMatch = m_knnMatches[i][2];
            float distanceRatio = bestMatch.distance / betterMatch.distance;
            float distanceRatio1 = betterMatch.distance / betterrMatch.distance;
            if (distanceRatio < minRatio)
        {
                m_Matches.push_back(bestMatch);
            }
            if (distanceRatio1 < minRatio)
            {
                n_Matches.push_back(betterMatch);
            }
        }

        Mat img_matches;
  drawMatches( img1,queryKeypoints,img2,trainKeypoints,m_Matches, img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

        Mat img_matches2;
  drawMatches( img1,queryKeypoints,img2,trainKeypoints,n_Matches, img_matches2, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

3个回答

wangyaninglm
wangyaninglm   Ds   Rxr 2016.01.21 10:46

我记得是可以匹配多个的哇,你代码发上来瞅瞅啊,opencv那些函数效果都一般,你得自己多调试些参数

u014173467
u014173467 感谢您的解答! 已附上代码望指教~
接近 2 年之前 回复
wangyaninglm
wangyaninglm   Ds   Rxr 2016.01.21 17:19

surf是尺度不变的啊,你这个有仿射变换问题应该也不是很大,你这个knn就找前三个?是不是有点少了
效果不好可能是特征点找多少了,先用高通滤波器滤波一下,我暂时想到这么多

u014173467
u014173467 Hi~ 感谢您的回复!我去试下滤波
接近 2 年之前 回复
wangyaninglm
wangyaninglm   Ds   Rxr 2016.02.29 10:42

特征点这块我也不是很熟,类似有这种是添加一些条件限制什么的,来筛选,距离啊,你说的knn啊什么的

 //-- Quick calculation of max and min distances between keypoints  
    for( int i = 0; i < descriptors_1.rows; i++ )  
    {   
        double dist = matches[i].distance;  
        if( dist < min_dist ) min_dist = dist;  
        if( dist > max_dist ) max_dist = dist;  
    }  
    printf("-- Max dist : %f \n", max_dist );  
    printf("-- Min dist : %f \n", min_dist );  
    //-- Draw only "good" matches (i.e. whose distance is less than 0.6*max_dist )  
    //-- PS.- radiusMatch can also be used here.  
    std::vector< DMatch > good_matches;  
    for( int i = 0; i < descriptors_1.rows; i++ )  
    {   
        if( matches[i].distance < 0.6*max_dist )  
        {   
            good_matches.push_back( matches[i]);   
        }  
    }  

    Mat img_matches;  
    drawMatches(img_1, keyPoints_1, img_2, keyPoints_2,  
        good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),  
        vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);  
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!