加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Opencv学习笔记三:Surf特征检测,实现图像匹配

(2017-03-02 10:11:46)
标签:

opencv

surf

特征匹配

分类: 上下求索
今天做项目需要进行透射变化,有角度和位置的变化,SURF是一种不错的实现方法,随了解其实现原理,并用opencv进行仿真实现,对opencv的例子做了进一步延伸,可以在检测图像上将需要的位置匹配到。
1、实现原理:
1> 分别提取检测图像和模板图像的特征点
2> 通过特征点检测到特征向量
3> 通过特征向量匹配得到合适的匹配值
4> 通过匹配距离筛选出合适的特征点
5> 通过合适的特征点计算得到仿射变化矩阵
6> 通过模板图像上的点和仿射变化矩阵得到检测图像上的位置
7> 对检测图像确定模板图像的位置,通过仿射变化矩阵抠图
2、实现代码

// step1:检测surf特征点

    int minHeassian = 400;

    // sift识别率不如surf

    //cv::Ptr ptDetector = cv::xfeatures2d::SIFT::create(minHeassian);  

    cv::Ptr<</span>Feature2D> ptDetector = cv::xfeatures2d::SURF::create(minHeassian);

    std::vector<</span>KeyPoint> vtKeypointSrc, vtKeypointMod;

    ptDetector->detect(matSrc, vtKeypointSrc);

    ptDetector->detect(matMod, vtKeypointMod);

    if (vtKeypointSrc.size() < 1 || vtKeypointMod.size() < 1)

    {

        return -1;

    }

    // step2:计算特征向量

    Mat matDescriptSrc, matDescriptMod;

    std::vector<</span>DMatch> vtMatches;

    ptDetector->compute(matSrc, vtKeypointSrc, matDescriptSrc);

    ptDetector->compute(matMod, vtKeypointMod, matDescriptMod);

    // step3:利用FLANN匹配算法匹配特征描述向量

    cv::FlannBasedMatcher basedMatcher;

    basedMatcher.match(matDescriptMod, matDescriptSrc, vtMatches);

    // test 将特征点画出来

    Mat matOutPut;

    cv::drawKeypoints(matSrc, vtKeypointSrc, matOutPut, Scalar(255, 0, 0), 0);

    cv::drawKeypoints(matMod, vtKeypointMod, matOutPut, Scalar(0, 0, 255), 0);

    cv::drawMatches(matMod, vtKeypointMod, matSrc, vtKeypointSrc, vtMatches, matOutPut,

         Scalar::all(-1), Scalar::all(-1), vector<</span>char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);

    double dMaxDist = 0, dMinDist = 100000;

   // 快速计算特征点之间的最大和最小距离,用于判断是否是好点

    for (int i = 0; i < vtMatches.size(); i++)

    {

        double dDist = vtMatches[i].distance;

        if (dDist < dMinDist)

        {

             dMinDist = dDist;

        }

        if (dDist > dMaxDist)

        {

             dMaxDist = dDist;

        }

    }

  int nSize = (int)vtMatches.size();

 // 筛选出好的匹配点(匹配特征点之间距离小于3*dMinDist)

CSorterChecker_Model *pModel = reinterpret_cast(m_pPublicModelData);

std::vector vtGoodMatches;

for (int i = 0; i < (int)vtMatches.size(); i++)

{

    if (vtMatches[i].distance <</span> dMinDist + (dMaxDist - dMinDist) * pModel->m_fFindMatchPointRadio)

    {

        vtGoodMatches.push_back(vtMatches[i]);

    }

}

 

 

nSize = (int)vtGoodMatches.size();

if ((int)vtGoodMatches.size() < 1)

{

    char strBuffer[MAX_PATH];

    sprintf_s(strBuffer, "Label Miss");

    return -1; // 好的匹配点不足

}

 

 

Mat matMatches = matSrc;

Mat matDrawMatch = matMod;

 

 

// step6:定位物体,找出匹配特征点之间的变换

std::vector vtSrc;

std::vector vtMod;

// 所有的匹配点得到匹配的中心点

float fCenterX = 0.0, fCenterY = 0.0;

for (int i = 0; i < (int)vtGoodMatches.size(); i++)

{

    // 从好的匹配中获取特征点

    Point2f ptSrc = vtKeypointSrc[vtGoodMatches[i].trainIdx].pt;

    Point2f ptMod = vtKeypointMod[vtGoodMatches[i].queryIdx].pt;

    vtSrc.push_back(ptSrc);

    vtMod.push_back(ptMod);

    fCenterX += ptSrc.x;

    fCenterY += ptSrc.y;

}

 

 

fCenterX = fCenterX / vtMatches.size();

fCenterY = fCenterY / vtMatches.size();

// 得到模板匹配后的中心点

cv::circle(matMatches, Point(fCenterX, fCenterY), 3, Scalar(255), 3);

 

 

// 找出匹配特征点之间的变换

Mat matHom = cv::findHomography(vtMod, vtSrc, CV_RANSAC);

if (matHom.data == NULL)

{

    char strBuffer[MAX_PATH];

    sprintf_s(strBuffer, "Label Miss");

    return -2; // 仿射变换矩阵为空

}

 

 

// 得到模板图像的角点(待匹配图像的大小)

std::vector vtModCorners(4);

vtModCorners[0] = cv::Point(0, 0);

vtModCorners[1] = cv::Point(matMod.cols, 0);

vtModCorners[2] = cv::Point(matMod.cols, matMod.rows);

vtModCorners[3] = cv::Point(0, matMod.rows);

 

 

std::vector vtSrcCorners(4);

// 通过仿射矩阵matHom在检测图像找到和模板图像匹配的四个角点

cv::perspectiveTransform(vtModCorners, vtSrcCorners, matHom);

 

 

// 匹配的四个点画到图像上

cv::line(matMatches, vtSrcCorners[0], vtSrcCorners[1], Scalar(0, 255, 0), 4);

cv::line(matMatches, vtSrcCorners[1], vtSrcCorners[2], Scalar(0, 255, 0), 4);

cv::line(matMatches, vtSrcCorners[2], vtSrcCorners[3], Scalar(0, 255, 0), 4);

cv::line(matMatches, vtSrcCorners[3], vtSrcCorners[0], Scalar(0, 255, 0), 4);

Mat matWarpMatrix = cv::getPerspectiveTransform(vtSrcCorners, vtModCorners);

 

 

// step7:仿射变化得到旋转后的图像

cv::warpPerspective(matMatches, matAffined, matWarpMatrix, matMod.size(), INTER_LINEAR, BORDER_CONSTANT);

3、试验图像
                                  http://s16/small/003eu7RDzy79bpq2Rsj5f&690    
特征点匹配图
4、注意事项
1> 彩色图像和灰度图像均可进行特征点检测匹配;
2> 使用drawMatches算子时,需要小图在前,大图在后。
cv::drawMatches(matMod, vtKeypointMod, matSrc, vtKeypointSrc, vtMatches, matOutPut,
Scalar::all(-1), Scalar::all(-1), vector(),
DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);


0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有