【计算机视觉基础】5.投影变换扩展(单应性Homograph估计)

2023-05-16

1. 投影变换

投影变换分为平行投影(正交投影)中心投影(透视投影),投影变换是联系三维空间物体与二维图形的桥梁。

基础的变换参考之前的博客《【计算机视觉基础】3.矩阵变换图形》,更详细的参数计算可以参考:投影变换 - 知乎

上面的知乎的这篇博客介绍的只是确定了拍摄角度,只改变相机与物体距离的推导。 

2. 单应性变换

2.1 单应性是什么

此处给出单应性不严谨的定义:用 [无镜头畸变] 的相机从不同位置拍摄 [同一平面物体] 的图像之间存在单应性,可以用 [透视变换] 表示 。

注意:
单应性的严格定义与成立条件非常复杂,超出本文范围,有需要的朋友请自行查阅相关内容。

在计算机视觉中,平面的单应性被定义为从一个平面到另一个平面的投影映射(Projective Mapping)。单应性矩阵主要用来解决两个问题

  1. 通过透视变换实现真实世界中一个平面变换到对应的图像上(三维到二维之间的变换)
  2. 通过透视变换实现图像从一种视图变换到另外一种视图(二维到二维之间的变换)

单应性矩阵在实际问题中的应用

  1. 用来实现图像拼接时的对齐问题
  2. 可以用于计算机图形学中的纹理渲染与计算平面阴影
  3. 解决拍照时候图像扭曲问题。

简单说就是:right view图像上的点可以经过透视变换到left view图像上对应位置。

2.2 那么这个 H3×3 单应性矩阵如何求解

 

2.3 单应性矩阵8自由度

注意观察:单应性矩阵H与aH其实完全一样(其中a≠0),例如:

所以单应性矩阵H虽然有9个未知数,但只有8个自由度。在求H时一般添加约束 ℎ33=1,所以还有 ℎ11∼ℎ32 共8个未知数。

 OpenCV已经提供了相关API,代码和变换结果如下。

import cv2
import numpy as np

im1 = cv2.imread('left.jpg')
im2 = cv2.imread('right.jpg')

src_points = np.array([[581, 297], [1053, 173], [1041, 895], [558, 827]])
dst_points = np.array([[571, 257], [963, 333], [965, 801], [557, 827]])

H, _ = cv2.findHomography(src_points, dst_points)

h, w = im2.shape[:2]

im2_warp = cv2.warpPerspective(im2, H, (w, h))

 

 可以看到:

  1. 红框所在平面上内容基本对齐,但受到镜头畸变影响无法完全对齐;
  2. 平面外背景物体不符合单应性原理,偏离很大,完全无法对齐。

3. 传统方法估计单应性矩阵

一般传统方法估计单应性变换矩阵,需要经过以下4个步骤:

  1. 提取每张图SIFT/SURF/FAST/ORB等特征点
  2. 提取每个特征点对应的描述子
  3. 通过匹配特征点描述子,找到两张图中匹配的特征点对(这里可能存在错误匹配)
  4. 使用RANSAC算法剔除错误匹配
  5. 求解方程组,计算Homograph单应性变换矩阵

示例代码如下:

#coding:utf-8

# This code only tested in OpenCV 3.4.2!
import cv2 
import numpy as np

# 读取图片
im1 = cv2.imread('left.jpg')
im2 = cv2.imread('right.jpg')

# 计算SURF特征点和对应的描述子,kp存储特征点坐标,des存储对应描述子
surf = cv2.xfeatures2d.SURF_create()
kp1, des1 = surf.detectAndCompute(im1, None)
kp2, des2 = surf.detectAndCompute(im2, None)

# 匹配特征点描述子
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1, des2, k=2)

# 提取匹配较好的特征点
good = []
for m,n in matches:
    if m.distance < 0.7*n.distance:
        good.append(m)

# 通过特征点坐标计算单应性矩阵H
# (findHomography中使用了RANSAC算法剔除错误匹配)
src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2)
H, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
matchesMask = mask.ravel().tolist()

# 使用单应性矩阵计算变换结果并绘图
h, w, d = im1.shape
pts = np.float32([[0,0], [0,h-1], [w-1,h-1], [w-1,0]]).reshape(-1,1,2)
dst = cv2.perspectiveTransform(pts, H)
img2 = cv2.polylines(im2, [np.int32(dst)], True, 255, 3, cv2.LINE_AA)

draw_params = dict(matchColor = (0,255,0), # draw matches in green color
                   singlePointColor = None,
                   matchesMask = matchesMask, # draw only inliers
                   flags = 2)

im3 = cv2.drawMatches(im1, kp1, im2, kp2, good, None, **draw_params)

 4. 逆透视变换

逆透视变换一般常用在自动驾驶场景中,把相机拍摄到的画面转换为俯视鸟瞰图,用于计算车辆前方可行驶区域等。实际上逆透视变换也是透视变换的一种特殊情况,只不过叫法不同而已,把不规则的图像变为规则俯视图(如下图,梯形变换为长方形)。

需要特别强调,根据单应性成立的基本条件,逆透视变换只在地平面内成立,两侧建筑、天空等不在地平面上的目标无法对应。 

5. 关于OpenCV中的相关API

  • warpPerspective 即透视变换函数
dst = cv2.warpPerspective(src, M, dsize, dst, flags, borderMode, borderValue)

其中 M 即为 3x3 变换矩阵。

  • warpAffine 即为仿射变换函数
dst = cv2.warpAffine(src, M, dsize, dst, flags, borderMode, borderValue)

其中 M 即为 2x3 变换矩阵(由于仿射变换 3x3 矩阵最下面一行为 0 0 1,如下公式,所以也就简写为 2x3 了)

 

从原理上来说,仿射变换是透视变换的特例,所以可以用warpPerspective来计算仿射变换。但是实际中涉及到计算速度等问题,最好还是使用对应的API吧。

6. 深度学习在单应性方向的进展

HomographyNet(深度学习end2end估计单应性变换矩阵) 

Spatial Transformer Networks(直接对CNN中的卷积特征进行变换)

参考

投影变换 - 知乎

单应性Homograph估计:从传统算法到深度学习 - 知乎

(16条消息) 投影变换_进击的路飞桑的博客-CSDN博客

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【计算机视觉基础】5.投影变换扩展(单应性Homograph估计) 的相关文章

  • Ubuntu 16.04使用Wireshark 抓包分析USB Audio Class 设备流程

    0 前言 为了分析usb麦克风的交互流程 xff0c 需要进行usb抓包 1 安装相关插件 安装usbmon sudo addgroup usbmon sudo gpasswd a USER usbmon echo 39 SUBSYSTEM
  • QT5.5实现串口通信

    QT5 1以上版本自带QtSerialPort集成库 xff0c 只要在头文件中集成 include lt QtSerialPort QSerialPort gt include lt QtSerialPort QSerialPortInf
  • “JTAG Warning: T-bit of XPSR is 0 but should be 1. Changed to 1.” 解决方案

    最近在调试一块GD32F107RCT6 xff0c 无法进行下载 错误提示 xff1a JTAG Warning T bit of XPSR is 0 but should be 1 Changed to 1 1 判断BOOT0 BOOT1
  • Windows无法访问Ubuntu Samba 解决方案

    好久没用Windows访问Ubuntu的共享文件 xff0c 忘记了密码 xff0c 重装Samba后提示Windows无法访问 可以打开文件但是无法访问 查看log var log samba log 192 168 1 39 smbd
  • keil C数组声明问题

    C语言中 xff0c 我们声明一个一维数组 xff0c 可以用以下几种方法 int buf 3 int buf 61 0 int buf 3 61 1 2 3 但是今天在keil中 使用int buf 61 0 这种方式进行声明 xff0c
  • 初学QML之qmlRegisterType

    qmlRegisterType 是一个可以将C 43 43 实现的类在QML中调用的 xff0c 连接C 43 43 和QML的一个工具 首先来看QtAssistant的介绍 int qmlRegisterType const char u
  • 在IDEA中引入jQuery无效

    在idea开发前端页面中 xff0c 引入jQuery后 xff0c 使用 会出现下划线 xff0c 提示未定义 虽然不影响使用 xff0c 运行后可以得到正常结果 xff0c 但还是看的很不爽 解决办法 xff1a Preferences
  • Asterisk WebRTC 搭建指南

    1 WebRTC简介 WEBRTC是一个开源项目 xff0c 其宗旨是让WEB浏览器通过简单的JavaScript具备实时通信 Real Time Communications RTC 的能力 WEBRTC目前支持JS和HTML5 xff0
  • UDP三种通讯方式

    单播 xff1a 单播用于两个主机之间的端对端通信 组播 xff1a 组播用于对一组特定的主机进行通信 广播 xff1a 广播用于一个主机对整个局域网上所有主机上的数据通信 单播实现 发送端 public class SendDemo pu
  • ArduPilot——如何对飞控LOG进行简易振动分析

    版权声明 xff1a 本文为博主原创博文 xff0c 未经允许不得转载 xff0c 若要转载 xff0c 请说明出处并给出博文链接 首先 xff0c 你得先有一架可以飞的且刷的是ArduPilot飞控代码的无人机和地面站Misson Pla
  • SITL Simulator —— ArduPilot —— Windows

    版权声明 xff1a 本文为博主原创博文 xff0c 未经允许不得转载 xff0c 若要转载 xff0c 请说明出处并给出博文链接 参考网页 xff1a http ardupilot org dev docs sitl native on
  • ArduCopter——ArduPilot——航点导航WPNav(一)

    版权声明 xff1a 本文为博主原创博文 xff0c 未经允许不得转载 xff0c 若要转载 xff0c 请说明出处并给出博文链接 现如今 xff0c 四旋翼飞行器已经从几年前的遥控航模变成真正可以超视距操控的无人机 xff0c 离不开伟大
  • 多频超声波清洗换能器用于高精密清洗系统

    多频超声波清洗换能器因加工方式和工作要求不同 xff0c 超声波换能器的工作方式可分为连续工作和脉冲式工作 xff0c 不同的工作方式对换能器的要求是不同的 连续式工作是不停机工作 xff0c 工作电流不是很大 xff0c 一般使用在清洗方
  • 超声波发生器电源控制电路线路板设计

    超声波发生器电源控制电路线路板是由匹配电容 xff0c 驱动变压器 xff0c 高功率的IGBT功率管 xff0c 匹配电感盒MOS管组成 xff0c 所有的组件一目了然 xff0c 零部件少 xff0c 故障率低 xff0c 造价成本低
  • 洗碗机超声波换能器振子设计

    超声波的声波是一种可以穿透液体和固体的声学化学能量 xff0c 超声波的污染非常小穿透力强 xff0c 所以人们就想到了用它来清洗餐具 xff0c 于是乎超声波洗碗机就应运而生了 洗碗机超声波换能器振子作为超声波洗碗机的三大组件之一 xff
  • 超声波清洗机电路板线路板设计

    在我们日常生活中遇见的超声波清洗设备 xff0c 大多是使用低频率或低功率的超声波 xff0c 而且由于被清洗件尺寸往往较小 xff0c 所以清洗槽的尺寸往往也较小 xff0c 清洗槽内壁高度一般不高于400mm 这类清洗机清洗物品涉及范围
  • 在Mac中开发STM32单片机

    想要在Mac下开发32单片机 xff0c 又不想装虚拟机的同学可以看看 使用工具 xff1a CLion xff08 JetBrains家族一员 xff09 STM32CubeMX xff08 配置芯片 xff0c 生成初始化代码 xff0
  • 超声波电路板驱动线路设计

    超声波电路板驱动线路通电交流电压220V 10 xff0c 电源电压需稳定 体积小 占用空间小 功率大 清洗效果好 自动化程度高 超声波电路板驱动线路驱动超声清洗换能器依次启动低频初洗 中频精洗 换水 高频漂洗 排水等工序 超声波发生器的输
  • 小型超声波PCB电路板设计

    小型超声波PCB电路板通过自动频率跟踪技术 PWM调功控制技术 电容阻抗匹配技术来匹配超声波清洗换能器 小型超声波PCB电路板在驱动负载工作时 xff0c 负载参数会发生变化 xff0c 这就是需要小型超声波PCB电路板能及时捕捉到新的谐振
  • 压电陶瓷超声波换能器设计

    压电陶瓷超声波换能器是值由电能通过压电陶瓷片转化为机械能 xff0c 通过结构件放大传播出去的一种机械运动 压电陶瓷超声波换能器的压电陶瓷片尺寸越大 xff0c 输出的功率越大 xff0c 相应的频率越低 xff0c 而尺寸越小频率相对应的

随机推荐

  • 数字式小型超声波清洗机设计

    数字式小型超声波清洗机可以超声 加热 定时LED数码显示 xff0c 整机为不锈钢结构 使用新型加热方式 xff0c 有效提升加热效果 xff1b 结构工艺上提升防漏水等级 xff0c 同时兼容无效热能导出结构 xff1b 压花处理不锈钢工
  • 超声波清洗振板盒带发生器设计

    超声波清洗振板盒带发生器投入式清洗 xff0c 方便携带移动使用 xff1b 时间可调 xff1a 1 99分钟可调 xff0c 可常开 xff1b 功率可调 xff1a 10 100 可调 xff1b 304外壳 xff1a SUS304
  • PE塑料超声波焊接机设备设计

    聚乙烯 xff08 polyethylene xff0c 简称PE xff09 是乙烯经聚合制得的一种热塑性树脂 在工业上 xff0c 也包括乙烯与少量 烯烃的共聚物 聚乙烯无臭 xff0c 无毒 xff0c 手感似蜡 xff0c 具有优良
  • jetson nx fan auto pwm

    参考 xff1a Jetson Nano PWM自动调速 Ay yzx的博客 CSDN博客 代码 xff1a usr bin env python import os import commands from the path of thi
  • 关于github px4 gps 驱动的开发的总结

    源码编译上边已经写过文章了 遇到的几个问题 1 解决虚拟机不能共享文件夹的问题 一开始虚拟机的更新 vmware tools 是灰色的 xff0c 不能点 xff0c 然后通过关掉虚拟机 xff0c 然后再开启的时候 xff0c 在没有启动
  • 解决Android Studio 安装gradle失败、很慢

    拉取新的项目工程是 xff0c 总是会遇到gradle 下载特别特别慢 xff0c 而且经常都是等了很久最终还以失败告终 这时 xff0c 我们可以使用浏览器自己去下载gradle xff0c 或者找同事要一份相同版本的gradle xff
  • 基于数传电台的多主通讯系统的实现

  • JNI基础简介

    导读 在前面的几篇文章中 xff0c 笔者介绍了C 43 43 中的指针 引用 智能指针 多线程 类型转换 异常处理等相关知识点 xff0c 如果想要熟练掌握 xff0c 并能在实际项目中运用 xff0c 光是看肯定是毫无用处 xff0c
  • C++ class

    namespace 在变量或函数前面加上命名空间 xff0c 用来区分其它位置中的同名函数或变量 span class token macro property span class token directive keyword incl
  • realsense r200使用过程记录

    realsense r200 相机 采用的结构光 43 双目立体视觉 xff0c 使用可以使用室外场景 xff0c 但是有些注意的事项 xff0c 该款相机在sdk 方面貌似总有些bug 相比之前的测过的zed astra kinectv1
  • 从io模型到ppc,tpc,reactor,preactor

    所有的系统I O都分为两个阶段 xff1a 等待就绪和操作 读就是等待系统可读和真正的读 写就是等待系统可写和真正的写 1 网络io模型 这是我们常见的一张图 1 传统的bio 就是同步阻塞的 当调用socket read的时候 会阻塞 直
  • ip校验和 及 udp校验和 的计算方法

    一 ip校验和的计算 计算方法 1 ip包头 共20个字节 按照每16个bit作为一个值依次进行相加 2 将计算结果的进位加到低16位上 3 将结果取反 ip包头的内存内容 eg 45 00 00 20 0F B8 00 00 80 11
  • 轻量化固态激光雷达的三维定位与建图

    点云PCL免费知识星球 xff0c 点云论文速读 文章 xff1a Lightweight 3 D Localization and Mapping for Solid State LiDAR 作者 xff1a Han Wang Chen
  • 嵌入式Linux下CAN接口socket发送调试

    1 简介 最近在做嵌入式linux can通讯的调试 xff0c 需要用到扩展帧 xff0c 参照示例代码和linux库改为扩展帧格式发送 参考链接 链接 https blog csdn net toradexsh article deta
  • 矩阵转置与矩阵相乘

    1 转置矩阵 1 1转置矩阵简介 把矩阵A的行换成同序数的列得到的新矩阵 xff0c 叫做A的转置矩阵 Transpose of a Matrix xff0c 记作ATAT 例如 xff1a 因此 xff0c 转置矩阵的特点 xff1a x
  • Python+Opencv:解决打开摄像头慢的问题,现在秒开视频

    前言 打开摄像头非常慢 大概需要5 11秒才能输出视频 这个问题困扰了我很久 一直没得到解决 今天终于得到解决 实现了秒开 值得记录和庆贺一下 我的开发环境 不同的开发环境可能不会遇到我这样的问题 1 操作系统是windows10 64位
  • WAP网页游戏

    最近利用空余时间开发了一款类似3GQQ家园的网页游戏 使用apache 43 mysql 43 php 游戏地址 xff1a www cmdandxgz top bug可能很多 xff0c 正在测试 游戏页面如下
  • WPS里公式居中、编号右对齐

    WPS里 xff0c 我目前没找到公式自动编号的方式 xff0c 在此提供一种还算编辑的手动编号并右对齐的方式 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 6
  • 【计算机视觉基础】8.内部参数描述

    目录 1 Film Coords gt Pixel Coords 2 变换 2 1 平移 2 2 尺度变换 2 3 旋转 2 4 刚体运动 2 5 刚体 43 尺度变换 2 6 仿射变换 2 7 投影变换 3 2D变换总结如下图 1 Fil
  • 【计算机视觉基础】5.投影变换扩展(单应性Homograph估计)

    1 投影变换 投影变换分为平行投影 xff08 正交投影 xff09 和中心投影 xff08 透视投影 xff09 xff0c 投影变换是联系三维空间物体与二维图形的桥梁 基础的变换参考之前的博客 计算机视觉基础 3 矩阵变换图形 xff0