利用opencv实现图片的配准/对齐

需求:

  同一位置不同时间拍20张照片或多或少有些偏移,需要矫正。

解决思路:

  原理就不介绍了,就是简单的图片配准(找关键点、关键点匹配、筛选关键点、计算变换矩阵、变换)

参考:

  网上搜了下大致有两种思路,试过效果都不错:

使用:

  opencv配准对其时候有四种方式:平移、欧几里得、仿射、单应。变换矩阵详细介绍
  具体使用哪一种看自己需求:比如我只希望进行图片的平移和旋转,不希望造成图片的畸变,所以我用Euclidean。
在这里插入图片描述

代码:

  就是摘自上边的链接利用ORB/SURF提取特征点、查找单应性矩阵、对图片变换Image Alignment (ECC) in OpenCV 细微的改动了下。

  利用ORB/SURF提取特征点、查找单应性矩阵、对图片变换

#include <opencv2/opencv.hpp>
#include "opencv2/xfeatures2d.hpp"
#include "opencv2/features2d.hpp"

using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;

const int MAX_FEATURES = 500;
const float GOOD_MATCH_PERCENT = 0.15f;


void alignImages(Mat &im1, Mat &im2, Mat &im1Reg, Mat &h)

{


  Mat im1Gray, im2Gray;
  cvtColor(im1, im1Gray, CV_BGR2GRAY);
  cvtColor(im2, im2Gray, CV_BGR2GRAY);

  // Variables to store keypoints and descriptors
  std::vector<KeyPoint> keypoints1, keypoints2;
  Mat descriptors1, descriptors2;

  // Detect ORB features and compute descriptors.
  Ptr<Feature2D> orb = ORB::create(MAX_FEATURES);
  orb->detectAndCompute(im1Gray, Mat(), keypoints1, descriptors1);
  orb->detectAndCompute(im2Gray, Mat(), keypoints2, descriptors2);

  // Match features.
  std::vector<DMatch> matches;
  Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
  matcher->match(descriptors1, descriptors2, matches, Mat());

  // Sort matches by score
  std::sort(matches.begin(), matches.end());

  // Remove not so good matches
  const int numGoodMatches = matches.size() * GOOD_MATCH_PERCENT;
  matches.erase(matches.begin()+numGoodMatches, matches.end());


  // Draw top matches
  Mat imMatches;
  drawMatches(im1, keypoints1, im2, keypoints2, matches, imMatches);
  imwrite("matches.jpg", imMatches);


  // Extract location of good matches
  std::vector<Point2f> points1, points2;

  for( size_t i = 0; i < matches.size(); i++ )
  {
    points1.push_back( keypoints1[ matches[i].queryIdx ].pt );
    points2.push_back( keypoints2[ matches[i].trainIdx ].pt );
  }

  // Find homography
  h = findHomography( points1, points2, RANSAC );

  // Use homography to warp image
  warpPerspective(im1, im1Reg, h, im2.size());

}


int main(int argc, char **argv)
{
  // Read reference image
  string refFilename("form.jpg"); 
  cout << "Reading reference image : " << refFilename << endl; 
  Mat imReference = imread(refFilename);


  // Read image to be aligned
  string imFilename("scanned-form.jpg");
  cout << "Reading image to align : " << imFilename << endl; 
  Mat im = imread(imFilename);


  // Registered image will be resotred in imReg. 
  // The estimated homography will be stored in h. 
  Mat imReg, h;

  // Align images
  cout << "Aligning images ..." << endl; 
  alignImages(im, imReference, imReg, h);

  // Write aligned image to disk. 
  string outFilename("aligned.jpg");
  cout << "Saving aligned image : " << outFilename << endl; 
  imwrite(outFilename, imReg);

  // Print estimated homography
  cout << "Estimated homography : \n" << h << endl; 

}

Image Alignment (ECC) in OpenCV

int main(int, char **) {
    // 【1】图像对齐(配准)
    // 读取图像
    Mat im1 = imread("/home/yx/Desktop/11/_0.png");
    Mat im2 = imread("/home/yx/Desktop/11/_18.png");
    // 将图像转换为灰度;
    Mat im1_gray, im2_gray;
    cvtColor(im1, im1_gray, CV_BGR2GRAY);
    cvtColor(im2, im2_gray, CV_BGR2GRAY);
    // 定义运动模型
    const int warp_mode = MOTION_EUCLIDEAN;
    // MOTION_TRANSLATION  平移
    // MOTION_EUCLIDEAN 欧几里得
    // MOTION_AFFINE 仿射
    // MOTION_HOMOGRAPHY 单应性
    // 根据运动模型设置2x3或3x3变形矩阵。
    Mat warp_matrix;
    // 初始化矩阵以进行标识
    if ( warp_mode == MOTION_HOMOGRAPHY ) {
        warp_matrix = Mat::eye(3, 3, CV_32F);
    } else {
        warp_matrix = Mat::eye(2, 3, CV_32F);
    }
    // 指定迭代次数。
    int number_of_iterations = 50;
    // 指定两次迭代之间相关系数增量的阈值
    double termination_eps = 1e-10;
    // 定义终止条件
    TermCriteria criteria (TermCriteria::COUNT +
                           TermCriteria::EPS,
                           number_of_iterations,
                           termination_eps);
    //运行ECC算法。结果存储在warp_matrix中。
    findTransformECC(
        im1_gray,
        im2_gray,
        warp_matrix,
        warp_mode,
        criteria
    );
    // 存放变形的图像。
    Mat im2_aligned;
    warpAffine(im2, im2_aligned, warp_matrix, im1.size(), INTER_LINEAR + WARP_INVERSE_MAP);
    // 显示最终结果
    imshow("Image 2", im2);
    imshow("Image 2 Aligned", im2_aligned);
    //【2】图像平滑 (高斯滤波)
    qint32 kernel_length = 3;
    GaussianBlur(im2_aligned, im2_aligned, Size(kernel_length, kernel_length), 0, 0);
    imshow("Image 2 Aligned GaussianBlur", im2_aligned);
    //【3】图像去血管
    waitKey(0);
}

  • 4
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Beyond欣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值