[OpenCV实战]18 Opencv中的单应性矩阵Homography

54 篇文章 34 订阅
52 篇文章 197 订阅

目录

1 介绍

1.1 什么是Homography

1.2 使用Homography进行图像对齐

1.3 Homography的应用-全景拼接

2 Homography的计算

3 总结

4 参考


《圣经》记载,当时人类联合起来兴建希望能通往天堂的高塔;为了阻止人类的计划,上帝让人类说不同的语言,使人类相互之间不能沟通,计划因此失败。

像“Homography”这样的术语经常提醒我,我们仍然在与沟通斗争。Homography(单应性)是一个简单的概念,却有一个奇怪的名字!

1 介绍

1.1 什么是Homography

考虑图1所示的同一个平面(比如书皮)的两幅图像。红点表示两幅图像中相同的物理坐标点。在计算机视觉术语中,我们称之为对应点。

Homography就是将一张图像上的点映射到另一张图像上对应点的3x3变换矩阵。因此该矩阵我们可以表示为:

让我们考虑一组对应点,位于第一张图像和位于第二张图像中。然后,Homography以下列方式映射它们:

1.2 使用Homography进行图像对齐

只要它们位于现实世界中的同一平面上,上述等式对于所有对应点都是正确的。换句话说,您可以将单应性应用于第一张图像,第一张图像中的书籍将与第二张图像中的书籍对齐!见下图。那么对于不在此平面上的点呢?这时再应用 Homography 就无法再对齐到对应点了。比如下图的桌子,地板。对于这种图像中有多个平面的情况,我们就需要针对每一个平面使用单独的Homography进行对齐。

1.3 Homography的应用-全景拼接

在上一节中,我们了解到如果已知两个图像之间的Homography,我们可以将一个图像映射到另一个图像上。但是,有一个很大的问题。图像必须位于同一个平面(书的顶部),并且只有该平面部分才会正确对齐。事实证明,如果您拍摄任何不包括一个平面的场景,然后通过旋转相机拍摄第二张照片,这两张图片就可以通过Homography相关联!您刚刚拍摄的完全随意的3D场景的两个图像可以用Homography相关联。这两个图像将共享一些可以对齐和拼接的公共区域,并且可以获得两个图像的全景图。然而这只是很粗糙的全景拼接,但基本原则是使用Homography和智能拼接。

2 Homography的计算

要计算两个图像之间的单应性,您需要知道两个图像之间至少有4个点对应关系。如果你有超过4个对应点,那就更好了。原因在于对于 H 矩阵,一般设 H22 为 1, 所以 H 有 8 个未知参数。至少需要8 个等式才能求解。而一组对应点可以提供 2 个等式,所以,至少需要 4 组对应点(任意三点不共线)来求得 H。OpenCV将稳健地估计最适合所有对应点的单应性。通常,这些点对应是通过匹配图像之间的SIFT或SURF等特征自动找到的,但在这篇文章中我们只是提前设定特征点。代码如下:

C++代码:

// OpenCV_Homography.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;



int main(int argc, char** argv)
{
	// Read source image 原图
	Mat im_src = imread("./image/book2.jpg");
	// Four corners of the book in source image 4个角点
	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("./image/book1.jpg");

	// Four corners of the book in destination image. 4个对应点
	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 计算Homography需要至少4组对应点.
	// pts_src : 源图像点坐标,pts_dst : 结果图像坐标
	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);
	return 0;
}

python代码:

#!/usr/bin/env python

import cv2
import numpy as np

if __name__ == '__main__' :

    # Read source image.
    im_src = cv2.imread('./image/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('./image/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)

3 总结

举个例子,例如虚拟广告牌,把下图1替换下图2的广告,得到下图3

实际步骤很简单

1 用选择上图2时代广场上广告屏的 4 个顶点,作为 pts_dst;

2 选取欲嵌入的图像的 4 个顶点,假设图像尺寸 W x H, 那么 四个顶点就是 (0,0), (0, W-1), (H - 1, 0), (H - 1, W - 1)。作为pts_src 类似下面代码,这样pts_src 和pts_dst就是一组对应点;

    // Create a vector of points.
    vector<Point2f> pts_src;
    pts_src.push_back(Point2f(0,0));
    pts_src.push_back(Point2f(size.width - 1, 0));
    pts_src.push_back(Point2f(size.width - 1, size.height -1));
    pts_src.push_back(Point2f(0, size.height - 1 ));

3 使用 pts_dst 和 pts_src 计算 Homography;运用opencv中的findHomography就行了

	// Calculate Homography 计算Homography需要至少4组对应点.
	// pts_src : 源图像点坐标,pts_dst : 结果图像坐标
	Mat h = findHomography(pts_src, pts_dst);

4 对 源图像应用计算得到的 Homography 从而 混合到 目标图像上;然后计算仿射变化。

    // Warp source image
    warpPerspective(im_src, im_temp, h, im_temp.size());

由于这个例子代码简单,具体代码就不贴出来了。所有代码见:

https://github.com/luohenyueji/OpenCV-Practical-Exercise

4 参考

https://www.learnopencv.com/homography-examples-using-opencv-python-c/

https://blog.csdn.net/baishuo8/article/details/80777995

 

  • 7
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
单应性矩阵Homography Matrix)是计算机视觉常用的一种变换矩阵,可以将一个平面上的点映射到另一个平面上的对应点。在OpenCV,可以使用findHomography函数来估计两个平面之间的单应性矩阵。下面是一个简单的示例代码: ``` #include <opencv2/opencv.hpp> using namespace cv; int main() { // 读取图像 Mat src1 = imread("image1.jpg"); Mat src2 = imread("image2.jpg"); // 定义特征点向量和描述子向量 std::vector<KeyPoint> keypoints1, keypoints2; Mat descriptors1, descriptors2; // 提取特征点和描述子 Ptr<ORB> orb = ORB::create(); orb->detectAndCompute(src1, noArray(), keypoints1, descriptors1); orb->detectAndCompute(src2, noArray(), keypoints2, descriptors2); // 匹配特征点 BFMatcher matcher(NORM_HAMMING); std::vector<DMatch> matches; matcher.match(descriptors1, descriptors2, matches); // 筛选出最佳匹配 double min_dist = 1000; for (int i = 0; i < descriptors1.rows; i++) { double dist = matches[i].distance; if (dist < min_dist) min_dist = dist; } std::vector<DMatch> good_matches; for (int i = 0; i < descriptors1.rows; i++) { if (matches[i].distance < 3 * min_dist) { good_matches.push_back(matches[i]); } } // 提取匹配点对 std::vector<Point2f> points1, points2; for (int i = 0; i < good_matches.size(); i++) { points1.push_back(keypoints1[good_matches[i].queryIdx].pt); points2.push_back(keypoints2[good_matches[i].trainIdx].pt); } // 计算单应性矩阵 Mat H = findHomography(points1, points2, RANSAC); return 0; } ``` 在这个示例代码,我们首先使用ORB算法提取了两幅图像的特征点和描述子。然后使用BFMatcher算法匹配了两幅图像的特征点,并筛选出最佳匹配。接下来,我们使用findHomography函数估计了两个平面之间的单应性矩阵。最后,我们可以使用这个单应性矩阵来进行图像配准或者图像拼接等操作。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值