[计算机视觉] 一篇文章教你学会单应性矩阵Homography(Python/C++)

0、国外原文链接

Homography examples using OpenCV ( Python / C ++ )

1、什么是单应性?

考虑图中显示的平面。红点代表两个图像中的相同物理点。在计算机视觉术语中,我们将这些对应点。图中显示了四种不同颜色的四个对应点:红色、绿色、黄色和橙色。单应性(3 * 3的矩阵)是指从图像中的一个点映射到另一张图像中的对应点的变换。


在这里插入图片描述

3 * 3的单应矩阵可以写成如下形式:
H = [ h 00 h 01 h 02 h 10 h 11 h 12 h 20 h 21 h 22 ] H=\left[\begin{array}{lll} h_{00} & h_{01} & h_{02} \\ h_{10} & h_{11} & h_{12} \\ h_{20} & h_{21} & h_{22} \end{array}\right] H=h00h10h20h01h11h21h02h12h22
让我们考虑两幅图中对应的第一组点,单应性矩阵通过如下方式进行映射:
[ x 1 y 1 1 ] = H [ x 2 y 2 1 ] = [ h 00 h 01 h 02 h 10 h 11 h 12 h 20 h 21 h 22 ] [ x 2 y 2 1 ] \left[\begin{array}{c} x_{1} \\ y_{1} \\ 1 \end{array}\right]=H\left[\begin{array}{c} x_{2} \\ y_{2} \\ 1 \end{array}\right]=\left[\begin{array}{lll} h_{00} & h_{01} & h_{02} \\ h_{10} & h_{11} & h_{12} \\ h_{20} & h_{21} & h_{22} \end{array}\right]\left[\begin{array}{c} x_{2} \\ y_{2} \\ 1 \end{array}\right] x1y11=Hx2y21=h00h10h20h01h11h21h02h12h22x2y21
只要它们在现实世界的同一平面上,上述等式都是成立的。换句话说,可以将单应性应用到第一张图上,第一张图中的书就会和第二张图中的书对齐。
上式中的xy坐标是齐次坐标,关于其次坐标可以参考我这篇文章,什么是齐次坐标?为什么要引入齐次坐标?

但是那些不在平面上的点呢?不在平面上的点不会通过单应性对齐,场景是平面,或者近似平面,或者低视差时都可以应用单应性矩阵

如果图像中有两个平面呢?两个平面对应两个单应变换,每个平面对应一个单应性矩阵

2、使用OpenCV的单应性示例

如果两个图像之间的单应性已知,我们可以将一个图像扭曲到另一个图像上。注意图像必须包含在一个平面上,只有同一平面上才能正确对齐。事实证明,如果你拍一张任何场景的照片(不仅仅是一个平面),然后通过旋转相机拍摄第二张照片,这两张图像通过单应性联系在一起。换句话说,可以将相机安装在三脚架上并拍拍照,然后绕着垂直轴并拍摄另一张图像。

3、如何计算单应性矩阵?

为了计算两个图像之间的单应性,需要知道两个图像之间的至少4个点对应关系,多余4个对应点更好。估计出最适合所有对应点的单应性矩阵。通常,这些点对应是通过图像之间的SIFT或SURF等特征匹配自动找到的。

3.1、C++
// pts_src 和 pts_dst 是源图像和目标图像中点的向量。它们的类型为 vector<Point2f>。至少需要4个对应点。
Mat h = findHomography(pts_src, pts_dst);

// 单应性矩阵可以将原图像扭曲到目标图像,im_src 和 im_dst 属于 Mat 类型。 size 是 im_dst 的大小(宽、高)。
warpPerspective(im_src, im_dst, h, size);
3.2、C++完整代码,从两张图中分别取4个对应的点,并将原图扭曲到目标图
#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

int main(int argc, char** argv) {
    // Read source image.
    Mat im_src = imread("book2.jpg");

    // Four corners of the book in source image
    vector<Point2f> pts_src;
    pts_src.push_back(Point2f(141, 131));
    pts_src.push_back(Point2f(480, 159));
    pts_src.push_back(Point2f(493, 630));
    pts_src.push_back(Point2f(64, 601));
 
    // Read destination image.
    Mat im_dst = imread("book1.jpg");

    // Four corners of the book in destination image.
    vector<Point2f> pts_dst;
    pts_dst.push_back(Point2f(318, 256));
    pts_dst.push_back(Point2f(534, 372));
    pts_dst.push_back(Point2f(316, 670));
    pts_dst.push_back(Point2f(73, 473));

    // Calculate Homography
    Mat h = findHomography(pts_src, pts_dst);

    // Output image
    Mat im_out;
    
    // Warp source image to destination based on homography
    warpPerspective(im_src, im_out, h, im_dst.size());

    // Display images
    imshow("Source Image", im_src);
    imshow("Destination Image", im_dst);
    imshow("Warped Source Image", im_out);

    waitKey(0);
}

3.3、Python
h, status = cv2.findHomography(pts_src, pts_dst)
im_dst = cv2.warpPerspective(im_src, h, size)
3.4、Python完整代码
#!/usr/bin/env python

import cv2
import numpy as np

if __name__ == '__main__' :
    # Read source image.
    im_src = cv2.imread('book2.jpg')

    # Four corners of the book in source image
    pts_src = np.array([[141, 131], [480, 159], [493, 630],[64, 601]])

    # Read destination image.
    im_dst = cv2.imread('book1.jpg')
    
    # Four corners of the book in destination image.
    pts_dst = np.array([[318, 256],[534, 372],[316, 670],[73, 473]])

    # Calculate Homography
    h, status = cv2.findHomography(pts_src, pts_dst)

    # Warp source image to destination based on homography
    im_out = cv2.warpPerspective(im_src, h, (im_dst.shape[1],im_dst.shape[0]))

    # Display images
    cv2.imshow("Source Image", im_src)
    cv2.imshow("Destination Image", im_dst)
    cv2.imshow("Warped Source Image", im_out)

    cv2.waitKey(0)

4、单应性的应用

单应图最有趣的应用无疑是制作全景图(也就是图像拼接和图像拼接)。

4.1、使用单应性进行透视校正

点击上面图像中书本的四个角落,就可以快速获取下图所示的书本图像。

  • 首先获取原图像四个角点坐标,称为pts_src;
  • 获取书的长宽比,对于这本书,长宽比为4比3,所以可以选择输出图像尺寸为300*400,目标点pts_dst为(0, 0)、(299, 0)、(299, 399)、(0, 399);
  • 使用pts_src和pts_dst获得单应性矩阵;
  • 将单应性应用于源图像,获得目标图像;
4.2、虚拟广告牌

在许多电视转播的体育赛事中,广告实际上是在视频直播中插入的。例如,在足球和棒球比赛中,恰好位于球场边界外的小广告牌上的广告实际上是可以改变的。与向所有人展示相同的广告不同,广告商可以根据用户的人口特征、位置等选择广告。

在这些应用中,在视频中检测广告牌的四个角作为目的点。广告的四个角作为源点。基于这四个对应点计算单应性,并将其用于将广告扭曲到视频帧中。如下图所示,将广告插入到图像中,我们可以把时代广场的广告牌换成我们想要的形象。

  • 首先获取广告牌的四个角点坐标,pts_dst;
  • 想要放在虚拟广告牌上的源图像的大小为w * h,因此图像的角为(0, 0)、(w-1, 0)、(w -1, h -1)、(0, h - 1);
  • 使用pts_src和pts_dst获得单应性矩阵;
  • 对源图像进行单应性处理,将源图像与目标图像混合;
  • 19
    点赞
  • 148
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值