目录

旋转矩阵,平移矩阵讲解:

仿射变换Python例子

编辑坐标点的仿射变换:


图像的几何变换主要包括:平移、旋转、缩放、剪切、仿射、透视等。
图像的几何变换主要分为:刚性变换、相似变换、仿射变换和透视变换(也称为投影变换)。
刚性变换:平移、旋转;
相似变换:缩放、剪切;
仿射变换:从一个二维坐标系变换到另一个二维坐标系的过程,属于线性变换。通过已知3对坐标点便可求取变换矩阵。
透视变换:从二维坐标系变换到三维坐标系,在从三维坐标系投影到二维平面,属于非线性变换。通过已知4对坐标点便可求取变换矩阵。

python opencv仿射变换矩阵合并 python仿射变换代码_透视变换


仿射变换

仿射变换是把一个二维坐标系转换到另一个二维坐标系的过程,在转换过程中坐标点的相对位置和属性不发生变换,属于线性变换。在该变换过程中只发生平移和旋转,因此一个菱形在发生仿射变换后还是一个菱形。

也可以说,仿射变换是指在向量空间中进行一次线性变换(乘以线性矩阵)和一次平移(加上一个向量),变换到另一个向量空间的过程。

仿射变换代表的是两幅图像之间的映射关系,仿射变换矩阵为2X3的矩阵,

总的来说,仿射=平移+旋转。

旋转矩阵,平移矩阵讲解:

线性代数导学(八): 那些常见且特殊的矩阵与其目的 - 知乎

仿射变换Python例子

import cv2
import numpy as np

img = np.zeros((400,400,3),dtype=np.uint8)

img[50:100,50:100]=255
height, width = img.shape[:2]

# 在原图上和目标图像上各选三个点
mat_src = np.float32([[0, 15], [0, height - 20], [width - 1, 0]])
mat_dst = np.float32([[0, 15], [100, height - 100], [width - 100, 100]])

# 获得变换矩阵
mat_trans = cv2.getAffineTransform(mat_src, mat_dst)
# 进行仿射变换
dst = cv2.warpAffine(img, mat_trans, (width, height))

# 显示
imgs = np.hstack([img, dst])
cv2.namedWindow("imgs", cv2.WINDOW_NORMAL)
cv2.imshow("imgs", imgs)
cv2.waitKey(0)

python opencv仿射变换矩阵合并 python仿射变换代码_二维_02

坐标点的仿射变换:

import cv2
import numpy as np

def get_transform(mat_src,mat_dst):
    img = np.zeros((600, 600, 3), dtype=np.uint8)
    img[50:100, 50:100] = 255
    img[350:400, 350:400] = 255

    height, width = img.shape[:2]

    x1 = int((mat_src[0,0]+mat_src[1,0])*0.5)
    y1 =  int((mat_src[0,1]+mat_src[1,1])*0.5)

    cv2.circle(img, (int(x1), int(y1)), 3, (0, 0, 255), -1)

    cv2.line(img, (0, 50), (50, 100), (0, 255, 0), 1)  # 绿色,3个像素宽度
    cv2.line(img, (300, 50), (50, 100), (0, 255, 0), 1)  # 绿色,3个像素宽度
    mat_trans = cv2.getAffineTransform(mat_src, mat_dst)
    dst = cv2.warpAffine(img, mat_trans, (width, height))

    return mat_trans,dst,img

def transform_point(mat_trans,point):# point x y

    data = np.dot(mat_trans, np.asarray([point[0], point[1], 1]))
    return data

if __name__ == '__main__':


    mat_src = np.float32([[0, 50], [50, 100], [600, 50]])
    mat_dst = np.float32([[0, 0], [100, 100], [100, 200]])
    mat_trans,dst,img=get_transform(mat_src,mat_dst)


    x1 = 25
    y1 = 75

    data=transform_point(mat_trans,[x1,y1])

    x2 = data[0]
    y2 = data[1]
    print(x2, y2)

    cv2.circle(dst, (int(x2), int(y2)), 2, (0, 0, 255), -1)
    # 显示
    imgs = np.hstack([img, dst])
    # imgs = np.hstack([img, dst])
    # cv2.namedWindow("imgs", cv2.WINDOW_NORMAL)
    cv2.imshow("img_o", img)
    cv2.imshow("dst", dst)
    # cv2.imshow("imgs", imgs)
    cv2.waitKey(0)

总结,仿射变换需要的3个点是因为3个点组成一个平面,只能对在平面内的点进行变换,如果点不在这个平面内,则变换失效,那就需要投影变换。

透视变换
透视变换是将一个图像投影到新的视平面,该过程包括:1.将二维坐标系转换为三维坐标系;2.将三维坐标系投影到新的二维坐标系。该过程属于非线性变换过程,一个菱形在经过非线性变换后得到一个四边形,但是不在平行。
透视变换又可以称为投影变换,仿射变换属于透视变换的特例。透视变换能够保持“直线性”,即原图中的直线,在经透视变换后仍为直线。
透视变换示意图


透视变换矩阵变换公式为:

其中透视变换矩阵为:

要移动的点,即源目标点:

定点,即移动到的目标点:

从二维空间变换到三维空间,因为图像在二维平面,故除以Z,(X‘,Y’,Z‘)表示图像上的点。

另a33=1,展开上面的公式,可得到一个点为:

四个点,即可得到8个方程,便可求解出透视变换矩阵A。
透视变换代码:

def PerspectImage():
    img = cv2.imread("C:/Users/player/Documents/3DPrinter/StitchImage/shizi.png")
    height, width = img.shape[:2]
    # 变换前的四个点
    srcArr = np.float32([[0, 0], [0, 1080], [1920, 1080], [1920, 0]])
    # 变换后的四个点
    dstArr = np.float32([[1, 12], [6, 1060], [1915, 1075], [1918, 3]])

    # 获取变换矩阵
    MM = cv2.getPerspectiveTransform(srcArr, dstArr)

    dst = cv2.warpPerspective(img, MM, (width, height))

    cv2.imwrite("C:/Users/player/Documents/3DPrinter/StitchImage/pe.png", dst)


变换结果

原图


python opencv仿射变换矩阵合并 python仿射变换代码_计算机视觉_03


透视变换后的效果图————

python opencv仿射变换矩阵合并 python仿射变换代码_二维_04