【opencv】:图像的透视变换

您所在的位置:网站首页 x线透视的过程图像能录制吗 【opencv】:图像的透视变换

【opencv】:图像的透视变换

2024-02-08 13:29| 来源: 网络整理| 查看: 265

图像的透视变换 1.透视变换数学实现原理2.code案例2.1 图像的平移2.2 图像的旋转2.3 透 视2.4 更加复杂的仿射变换

1.透视变换数学实现原理

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

以上便是透视变换的原理图,即将源图像通过投影映射,从原图像平面变换到新图像平面。通用的变换公式为: 在这里插入图片描述

(X,Y,Z)是原图像平面坐标点, 对应得到变换后的图像平面坐标点为(X’;Y’;Z’) ,因为我们处理的是二维的图像,所以可以令Z’=1,并将变换后的图像坐标除以Z’,将图片由三维降维为两维,然后可以得到以下方程: 在这里插入图片描述

一般地, 我们令a33=1(方便得到X’,Y’,使方程3等号左侧分母为1), 展开上面公式, 得到一个点的情况: 在这里插入图片描述

方程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,如下:

在这里插入图片描述 使用python,将上述推导过程定义为函数WarpPerspectiveMatrix(src, dst),计算出变换矩阵warpMatrix,如下

import numpy as np def 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=B B = 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相乘,求出warpMatrix warpMatrix = 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 warpMatrix if __name__ == '__main__': 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中,提供了仿射函数cv2.warpAffine()实现对图像的旋转

dst = cv2.warpAffine(src, M, dsize, [, flags[, borderMode[, borderValue]]]) dst代表仿射后的输出图像,dsize决定输出图像的实际大小 src代表要仿射的原始图像 M代表一个2X3的变换矩阵。使用不同的矩阵,就可以实现不同的仿射变换 dsize表示输出图像的尺寸大小 flags表示差值方法,默认为INTER_LINEAR。当值为WARP_INVERSE_MAP时,意味着M为逆变换,实现从目标图像dst到src的逆变换。具体值见下表。 borderMode表示边类型。默认为BORDER_CONSTANT。当值为BORDER_TRANSPARENT时,意味着目标图像内的值不做改变,这些值对应着原始图像的异常值。 border表示边界值,默认为0

2.code案例 2.1 图像的平移

说明:123.jpg格式为800X600 ,枫叶图像四个点坐标为: 左上角,右上角,左下角,右下角 [80, 266], [494, 27], [239, 543], [655, 300]]

import cv2 import numpy as np img = cv2.imread(r'C:\Users\Administrator\Desktop\123.jpg') height, width = img.shape[:2] x = 100 y = 200 M = np.float32([[1, 0, x], [0, 1, y]]) move1 = cv2.warpAffine(img, M, (width, height)) cv2.imshow('source', img) cv2.imshow('dst', move1) cv2.waitKey()

在这里插入图片描述

2.2 图像的旋转

使用cv2.warpAffine对图像进行旋转时,可以通过cv2.getRotationMatrix2D()获得转换矩阵。该函数的基本用法:

retval = cv2.getRotationMatrix2D(center, angle, scale)

式中:

center是旋转的中心点 angle是旋转角度,正数表示逆时针旋转,负数表示顺时针旋转 scale为变换尺寸(缩放大小) 例:要求以图像中心为旋转点,逆时针旋转45°,并将目标缩小为原始图像的0.5倍。

import cv2 img = cv2.imread(r'C:\Users\Administrator\Desktop\123.jpg') height, width = img.shape[:2] M = cv2.getRotationMatrix2D((width/2, height/2), 45, 1) rotation = cv2.warpAffine(img, M, (width, height)) cv2.imshow('source', img) cv2.imshow('dst', rotation) cv2.waitKey()

在这里插入图片描述

2.3 透 视

上面的仿射变换可以将矩形映射为任意平行四边形。透视变换可以将矩形映射成任意四边形。

透视变换通过函数cv2.warpPerspective()实现,该函数的语法是:

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

dst代表透视处理后的输出图像,dsize决定输出图像的实际大小 src代表要透视的图像 M为一个3X3的变换矩阵 dsize代表输出图像的尺寸大小 flags表示差值方法,默认为INTER_LINEAR。当值为WARP_INVERSE_MAP时,意味着M为逆变换,实现从目标图像dst到src的逆变换。具体值见下表。 borderMode表示边类型。默认为BORDER_CONSTANT。当值为BORDER_TRANSPARENT时,意味着目标图像内的值不做改变,这些值对应着原始图像的异常值。 border表示边界值,默认为0 与仿射变化一样,可以使用函数cv2.getPerspectiveTransform()来生成转换矩阵。

语法:

retval = cv2.getPerspectiveTransform(src, dst) src表示输入图像的四个顶点坐标 dst表示输出图像的四个顶点坐标 例:将图像透视。

import cv2 import numpy as np img = cv2.imread(r'C:\Users\Administrator\Desktop\123.jpg') rows, cols, ch = img.shape p1 = np.float32([[80, 266], [494, 27], [239, 543], [655, 300]]) # 左上角,右上角,左下角,右下角 p2 = np.float32( [[0, 0], [800, 0], [0, 600], [800, 600]]) M = cv2.getPerspectiveTransform(p1, p2) dst = cv2.warpPerspective(img, M, (cols, rows)) cv2.imshow('source', img) cv2.imshow('dst', dst) cv2.waitKey()

测试2:

在这里插入图片描述

2.4 更加复杂的仿射变换

对于更加复杂的变换,OpenCV提供了cv2.getAffineTransform()来生成需要的转换矩阵M。

语法:

retval = cv2.getAffineTransform(src, dst) src表示输入图像的三个点坐标 dst表示输出图像的三个点坐标 src和dst三个点坐标分别表示平行四边形的左上角、右上角、右下角的三个点。

函数cv2.warpAffine()函数以cv2.getAffineTransform(src, dst)获得的转换矩阵M为参数,将src中的点仿射到dst中,函数cv2.getAffineTransform(src, dst)对指定的点完成映射之后,将所有其他点的映射关系按照指定点的关系确定。

import cv2 import numpy as np img = cv2.imread(r'C:\Users\Administrator\Desktop\123.jpg') height, width = img.shape[:2] rows, cols, ch = img.shape p1 = np.float32([[81, 265], [240, 540], [496, 26]]) p2 = np.float32( [[0, 0], [0, 200], [300, 0]]) M = cv2.getAffineTransform(p1, p2) dst = cv2.warpAffine(img, M, (cols, rows)) cv2.imshow('source', img) cv2.imshow('dst', dst) cv2.waitKey()

在这里插入图片描述

import cv2 import numpy as np img = cv2.imread(r'C:\Users\Administrator\Desktop\123.jpg') height, width = img.shape[:2] rows, cols, ch = img.shape p1 = np.float32([[81, 265], [496, 26], [240, 540]]) p2 = np.float32( [[0, 0], [0, 200], [300, 0]]) M = cv2.getAffineTransform(p1, p2) dst = cv2.warpAffine(img, M, (cols, rows)) cv2.imshow('source', img) cv2.imshow('dst', dst) cv2.waitKey()

在这里插入图片描述

参考:



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3