图像畸变矫正——透视变换

article/2025/10/3 21:25:30

图像畸变矫正——透视变换

由于相机制造精度以及组装工艺的偏差引入的畸变,或者由于照片拍摄时的角度、旋转、缩放等问题, 可能会导致原始图像的失真,如果要修复这些失真,我们可以通过透视变换,对图像进行畸变矫正。

透视变换的原理推导

透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane), 也称作投影映射(Projective Mapping)。透视变换的目的就是把现实中为直线的物体, 在图片上可能呈现为斜线, 通过透视变换转换成直线的变换。

仿射变换(Affine Transformation或 Affine Map) , 又称为仿射映射, 是指在几何中, 图像进行从一个向量空间进行一次线性变换和一次平移, 变换为到另一个向量空间的过程。我们常说的仿射变换是透视变换的一个特例。

图1
以上便是透视变换的原理图,即将源图像通过投影映射,从原图像平面变换到新图像平面。通用的变换公式为:
方程1
(X,Y,Z)是原图像平面坐标点, 对应得到变换后的图像平面坐标点为(X’;Y’;Z’) ,因为我们处理的是二维的图像,所以可以令Z’=1,并将变换后的图像坐标除以Z’,将图片由三维降维为两维,然后可以得到以下方程:
方程2
一般地, 我们令a33=1(方便得到X’,Y’,使方程3等号左侧分母为1), 展开上面公式, 得到一个点的情况:
方程3
方程3中共有8个未知数(aij),如果要解出该未知数,需要列八组方程,即分别在源图像和目标图像上人为选择四个点(通常选择图片的四个顶点)

在源图像上选四个坐标点,分别为A: (x0,y0),(x1,y1),(x2,y2),(x3,y3)

在目标图像上选四个坐标点,分别为B: (X’0,Y’0),(X’1,Y’1),(X’2,Y’2),(X’3,Y’3)

带入方程3,可以得出方程4,如下:
方程4
使用python,将上述推导过程定义为函数WarpPerspectiveMatrix(src, dst),计算出变换矩阵warpMatrix,如下:

import numpy as npdef WarpPerspectiveMatrix(src, dst):assert src.shape[0] == dst.shape[0] and src.shape[0] >= 4#assert语句:用以检查某一条件是否为True,若该条件为False则会给出一个AssertionError。#注意这里src和dst的输入并不是图像,而是图像对应的顶点坐标点矩阵。nums = src.shape[0]A = np.zeros((2*nums, 8)) # A*warpMatrix=BB = np.zeros((2*nums, 1))for i in range(0, nums):A_i = src[i,:]B_i = dst[i,:]A[2*i, :] = [A_i[0], A_i[1], 1, 0, 0, 0,-A_i[0]*B_i[0], -A_i[1]*B_i[0]]B[2*i] = B_i[0]A[2*i+1, :] = [0, 0, 0, A_i[0], A_i[1], 1,-A_i[0]*B_i[1], -A_i[1]*B_i[1]]B[2*i+1] = B_i[1]A = np.mat(A)  #创建矩阵#用A.I求出A的逆矩阵,然后与B相乘,求出warpMatrixwarpMatrix = A.I * B #求出a_11, a_12, a_13, a_21, a_22, a_23, a_31, a_32#之后为结果的后处理warpMatrix = np.array(warpMatrix).T[0]   #np.array():创建一个数组,.T[0]:将Tensor进行转置warpMatrix = np.insert(warpMatrix, warpMatrix.shape[0], values=1.0, axis=0) #插入a_33 = 1'''np.insert(arr, obj, values, axis)#arr原始数组,可一可多,obj插入元素位置,values是插入内容,axis是按行按列插入。'''warpMatrix = warpMatrix.reshape((3, 3))return warpMatrixif __name__ == '__main__':'''#一个python文件通常有两种使用方法,第一是作为脚本直接执行,第二是 import 到其他的 python 脚本中被调用(模块重用)执行。# 因此 if __name__ == 'main': 的作用就是控制这两种情况执行代码的过程,在 if __name__ == 'main': 下的代码只有在第一种情况下# (即文件作为脚本直接执行)才会被执行,而 import 到其他脚本中是不会被执行的。'''print('warpMatrix')src = [[10.0, 457.0], [395.0, 291.0], [624.0, 291.0], [1000.0, 457.0]]src = np.array(src)dst = [[46.0, 920.0], [46.0, 100.0], [600.0, 100.0], [600.0, 920.0]]dst = np.array(dst)warpMatrix = WarpPerspectiveMatrix(src, dst)print(warpMatrix)

结果为:

warpMatrix
[[-5.01338334e-01 -1.35357643e+00  5.82386716e+02][-1.38100642e-15 -4.84035391e+00  1.38781980e+03][-2.29650079e-19 -4.14856327e-03  1.00000000e+00]]

上述推导过程是为了,让大家更加直观的的了解透视变换。在实际工程上,opencv库早已将上述过程集成为函数,我们选择网上流行的一张图片校验该opencv库中的畸变矫正算法。

图2

代码块为:

import cv2
import numpy as npimg = cv2.imread('photo1.jpg')result3 = img.copy()#img = cv2.GaussianBlur(img,(3,3),0)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
"""
cv2.Canny(image,            # 输入原图(必须为单通道图)threshold1, threshold2,       # 较大的阈值2用于检测图像中明显的边缘[, edges[, apertureSize[,    # apertureSize:Sobel算子的大小L2gradient ]]])   # 参数(布尔值):true: 使用更精确的L2范数进行计算(即两个方向的倒数的平方和再开放),false:使用L1范数(直接将两个方向导数的绝对值相加)。
"""
edges = cv2.Canny(gray,50,150,apertureSize = 3)
#cv2.imwrite("canny.jpg", edges)'''
注意这里src和dst的输入并不是图像,而是图像对应的顶点坐标点矩阵。
'''
src = np.float32([[207, 151], [517, 285], [17, 601], [343, 731]])
dst = np.float32([[0, 0], [337, 0], [0, 488], [337, 488]])
# 生成透视变换矩阵;进行透视变换
'''
1 cv2.getPerspectiveTransform(src, dst) → retval参数说明
src:源图像中待测矩形的四点坐标
sdt:目标图像中矩形的四点坐标
返回由源图像中矩形到目标图像矩形变换的矩阵
'''
m = cv2.getPerspectiveTransform(src, dst)       #适用于一组点
'''
cv2.warpPerspective(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst
参数为:
src:输入图像
M:变换矩阵
dsize:目标图像shape
flags:插值方式,interpolation方法INTER_LINEAR或INTER_NEAREST
borderMode:边界补偿方式,BORDER_CONSTANT or BORDER_REPLICATE
borderValue:边界补偿大小,常值,默认为0
'''
result = cv2.warpPerspective(result3, m, (337, 488))  #适用于图片
cv2.imshow("src", img)
cv2.imshow("result", result)
cv2.waitKey(0)

输出的结果为
图3


http://chatgpt.dhexx.cn/article/e4gCSgL2.shtml

相关文章

透视变换原理实例代码详解

导读 在上篇文章中,我们介绍了仿射变换,我们只需要通过一个两行三列的变换矩阵M就能够对图像实现平移、缩放、翻转、旋转操作。我们发现这些变换其实都属于平面变换,如果我们想要进行空间变换呢? 将上图的扑克牌单独提取出来&am…

[解疑]图像、矩阵的二维空间变换

本文经过参考多个文章整理而成,感谢各位博主的无私分享。 综述 图像(2维平面)到图像(2维平面)的四种变换包括:等距变换,相似变换,仿射变换,投影变换。对图像的几何变换…

数字图像处理(入门篇)十四 透视变换

目录 一 透视变换 二 实践 (1)代码 (2)结果图 一 透视变换 现实生活中的空间是三维的,图像中的物体存在近大远小的特征,这种畸变仿射变换不能矫正。因此,我们需要使用到三维空间的变化&…

【图像理论】透视变换

透视变换: 定义:本质是将图像投影到一个新的视平面。仿射变换可以理解为透视变换的特殊形式。利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使承影面(透视面)绕迹线(透视轴)旋转某…

Python图像处理之透视变换

1 引言 如果你想对图像进行校准,那么透视变换是非常有效的变换手段。透视变换的定义为将图像投影到一个新的视平面,通常也被称之为投影映射。 2 公式 一般来说,通用的图像变换公式如下所示: 上述公式中,u,v代表原…

维特比算法 python_维特比算法理解与实现(Python)

前言 写这篇文章就是想以通俗易懂的方式解析维特比算法,最后给出Python代码的实现。下面的公式和原理均出自《统计学习方法》。 算法的原理 算法的原理1.PNG 算法的原理2.PNG 上面写了一大堆,意思就是:每个时刻选择出概率最大的路径&#xf…

viterbi-algorithm 维特比算法的例子解析

维特比算法的目的: 寻找最可能的隐藏状态序列(Finding most probable sequence of hidden states) 关于原理的讲解可以参考下面两篇文章,讲的比较清楚 小白给小白详解维特比算法1. 小白给小白详解维特比算法2. 本文通过分析维特比算法的例子&#xff0c…

维特比算法代码

维特比算法实现python语言版 本文主要写一个关于维特比算法的代码,具体理论请参考一文搞懂HMM(隐马尔可夫模型): HMM(隐马尔可夫模型)是用来描述隐含未知参数的统计模型,举一个经典的例子&…

维特比算法学习

参考文章1: 简直不要太通俗易懂,这篇文章,很值得看 参考文章2: 解释一些概念性的问题,我把他的一些内容写下来 维特比(Viterbi)算法的核心是动态规划。 对于 HMM 而言,其中一个重要的任务就是要找出最有…

5分钟理解维特比算法

安德鲁维特比老人家发明了维特比算法,用非常巧妙的方法简化了隐马尔可夫第二个问题运算过程。维特比先生后来发明了CDMA技术并与人一起创办了高通公司,高通现在是通信巨头,不生产产品却每年收取大量的专利费。 下面我们用简单的例子&#xff…

Viterbi-Algorithm(维特比算法)

Viterbi-Algorithm 维特比算法是一个特殊但应用最广的动态规划算法。利用动态规划,可以解决任何一个图中的最短路径问题。而维特比算法是针对一个特殊的图-篱笆网了(Lattice)的有向图最短路径问题而提出来的。它之所以重要,是因为…

NLP学习笔记06-维特比算法

一序 本文属于NLP学习笔记系列。 上一篇整理了前向最大匹配算法与所有组合算法缺点(时间复杂度太高了)。 二 维特比算法 log(x*y*z) log(x)log(y)log(z) 概率上为了避免小数练乘出现的超范围溢出,改用log,改用-log,使得原来求概…

HMM-维特比算法

HMM-维特比算法(viterbi) HMM回顾隐马科夫链解法:维特比算法(Viterbi) HMM回顾 最终的公式可以解释主要分为两个部分: P(xi|yi),发射概率,字面意思是从一个词性中发射/生成出某一个…

Viterbi算法(维特比算法)

维特比算法背景: 安德鲁维特比(Andrew J. Viterbi),CDMA之父,IEEE Fellow,高通公司创始人之一,高通首席科学家。他开发了卷积码编码的最大似然算法而享誉全球。1991年香农奖(Claude …

HMM+维特比算法

一、简介 Viterbi 算法 考虑到穷举方法的缺点,可以采用:Viterbi 算法: 动态搜索最优状态序列,这样每个节点保存的是到当前节点的局部最优概率;依据最后一个时刻中概率最高的状态,逆向找其路径中的上一个最大部分最优路…

维特比算法的java实现_原创:维特比算法

看了宗成庆博士的《统计自然语言处理(中文信息处理)》的第六章,对维特比算法有着非常精辟的讲解。把其中的讲解上传上来,个人感觉比较正统。 今天用Java实现了这个算法,也可以转换为C代码: package com.nlp.hmm.algorithm.viterbi…

隐马尔可夫(HMM)、前/后向算法、Viterbi算法 再次总结

本总结是是个人为防止遗忘而作,不得转载和商用。 说明:此篇是作者对“隐马尔可夫模型”的第二次总结,因此可以算作对上次总结的查漏补缺以及更进一步的理解,所以很多在第一次总结中已经整理过的内容在本篇中将不再重复&#xff0c…

维特比(Viterbi)算法

维特比算法 (Viterbi algorithm) 是机器学习中应用非常广泛的动态规划算法,在求解隐马尔科夫、条件随机场的预测以及seq2seq模型概率计算等问题中均用到了该算法。实际上,维特比算法不仅是很多自然语言处理的解码算法,也是现代数字通信中使用…

小白给小白详解维特比算法(一)

小白给小白详解维特比算法(一) 小白给小白详解维特比算法一 篱笆网络Lattice的最短路径问题 这个问题长什么样子这个问题难在哪里简化成这个模样你总能回答了吧下一步我们该干什么 别倒立了我们再从头想一下这个问题 我们是怎么走过来的来我们从A开始走这…

viterbi算法

维特比算法(Viterbi Algorithm) 标签(空格分隔): 未分类 维特比算法(Viterbi Algorithm) viterbi算法用于寻找最可能的隐藏状态序列(Finding most probable sequence of hidden states) 对于…