1.原理

透视变换的映射原理基于线性变换和矩阵运算,通过透视变换矩阵将原始图像中的像素映射到目标图像中的对应位置,从而实现图像的透视变换。这种映射过程可以将图像投影到一个新的视角,校正图像的倾斜,提取图像中感兴趣的区域等。
1.对于原始图像中的每个像素 (x, y),将其表示为齐次坐标形式 (x, y, 1)。
将齐次坐标 (x, y, 1) 与透视变换矩阵相乘,得到新的齐次坐标 (x’, y’, w’)。这是通过矩阵乘法实现的。
2.对于新的齐次坐标 (x’, y’, w’),进行归一化处理,将其转换为图像坐标 (x’, y’)。这是通过除以 w’ 来实现的,即 (x’, y’) = (x’ / w’, y’ / w’)。
3.最后,根据插值方法,将原始图像中的像素值映射到目标图像中的 (x’, y’) 位置。常用的插值方法包括最近邻插值、双线性插值和双立方插值。
我们其实只要简单的知道,图像是一个二维的,将其映射到三维中也就是变换成齐次坐标,在将其变换到二维,中间的矩阵就可以通过cv2.getPerspectiveTransform(src_points, dst_points) 计算得到透视变换矩阵。该矩阵描述了原始图像中的四个点与目标图像中的对应四个点之间的映射关系。

2.cv2.warpPerspective()函数参数

warped = cv2.warpPerspective(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])

参数解释:
src:源图像,即待进行透视变换的图像,通常是一个二维数组(如灰度图像)或三维数组(如彩色图像)。
M:透视变换矩阵,是一个 3x3 的变换矩阵,可以通过函数 cv2.getPerspectiveTransform() 获得。
dsize:输出图像的大小,即变换后的图像大小,可以指定为 (width, height) 的元组。
dst:输出图像,可选参数。如果指定了该参数,函数会将变换后的图像存储在这个参数中,不会创建新的数组。
flags:插值方法的标志,用于指定在变换过程中如何对像素进行插值。常用的取值有 cv2.INTER_LINEAR(双线性插值,默认值)和 cv2.INTER_NEAREST(最近邻插值)等。
borderMode:边界填充模式的标志,用于指定在变换过程中超出边界的像素如何处理。常用的取值有 cv2.BORDER_CONSTANT(使用常数填充,默认值)和 cv2.BORDER_REPLICATE(使用边界像素进行复制填充)等。
borderValue:边界填充的常数值,当 borderMode 参数为 cv2.BORDER_CONSTANT 时使用。

函数执行后会返回透视变换后的图像 warped。透视变换可以将图像从一种透视投影(如俯视图)转换为另一种透视投影(如鸟瞰图),通过变换矩阵 M 的不同设置可以实现不同的图像变换效果。

3.应用举例

import cv2
import numpy as np

# 读取倾斜的文档图像
image = cv2.imread("page.jpg")

# 将图像转为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 使用边缘检测算法检测图像中的边缘
edges = cv2.Canny(gray, 50, 150)

# 检测图像中的轮廓
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 获取图像中的最大轮廓
max_contour = max(contours, key=cv2.contourArea)

# 计算最大轮廓的凸包,得到四个角点坐标 
# 这一步可以用外界矩形代替多边形的逼近
approx = cv2.approxPolyDP(max_contour, 0.02 * cv2.arcLength(max_contour, True), True)
corner_points = np.squeeze(approx)

# 定义目标图像的宽高
dst_width = 800
dst_height = 1000

# 定义目标图像的四个角点坐标
dst_points = np.float32([[0, 0], [dst_width - 1, 0], [dst_width - 1, dst_height - 1], [0, dst_height - 1]])

# 计算透视变换矩阵
M = cv2.getPerspectiveTransform(corner_points.astype(np.float32), dst_points)

# 执行透视变换
warped = cv2.warpPerspective(image, M, (dst_width, dst_height))

# 显示原图像和校正后的图像
cv2.imshow("Original Image", image)
cv2.imshow("Warped Image", warped)
cv2.waitKey(0)
cv2.destroyAllWindows()

由于图像坐标是以0为起点的,所以最右边的像素在 x 轴上的坐标是 dst_width - 1。因此,为了确保所选的目标图像角点坐标不超出目标图像的范围,我们使用 dst_width - 1 作为最右边角点的 x 坐标。

输出结果:
分别表示:原图、变更后的图在这里插入图片描述

Logo

分享最新、最前沿的AI大模型技术,吸纳国内前几批AI大模型开发者

更多推荐