图像透视变换原理与实现

仿射变换和透视变换

仿射变换是把一个二维坐标系转换到另一个二维坐标系的过程,转换过程坐标点的相对位置和属性不发生变换,是一个线性变换,该过程只发生旋转和平移过程。因此,一个平行四边形经过仿射变换后还是一个平行四边形。
所以,仿射= 旋转 + 平移

透视变换是把一个图像投影到一个新的视平面的过程,该过程包括:把一个二维坐标系转换为三维坐标系,然后把三维坐标系投影到新的二维坐标系。该过程是一个非线性变换过程,因此,一个平行四边形经过透视变换后只得到四边形,但不平行。

透视变换的变换关系如下:

 下面是通过变换关系和调用opencv得到的透视变换的代码例子:


import cv2
import numpy as np


path = 'img/a.png'




def show(image):
    # image = cv2.resize(image, (0, 0), fx=0.5, fy=0.5)
    cv2.imshow('image', image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()




def pointInPolygon(x, y, point):
    j = len(point) - 1
    flag = False
    for i in range(len(point)):
        if (point[i][1] < y <= point[j][1] or point[j][1] < y <= point[i][1]) and (point[i][0] <= x or point[j][0] <= x):
            if point[i][0] + (y - point[i][1]) / (point[j][1] - point[i][1]) * (point[j][0] - point[i][0]) < x:
                flag = not flag
        j = i
    return flag




def draw_line(image, point, color=(0, 255, 0), w=2):
    image = cv2.line(image, (point[0][0], point[0][1]), (point[1][0], point[1][1]), color, w)
    image = cv2.line(image, (point[1][0], point[1][1]), (point[2][0], point[2][1]), color, w)
    image = cv2.line(image, (point[2][0], point[2][1]), (point[3][0], point[3][1]), color, w)
    image = cv2.line(image, (point[3][0], point[3][1]), (point[0][0], point[0][1]), color, w)
    return image




def warp(image, point1, point2):
    h, w = image.shape[:2]
    print(h, w)
    img1 = np.zeros((int(point2[2][0]), int(point2[2][1]), 3), dtype=np.uint8)
    M = cv2.getPerspectiveTransform(point1, point2)
    for i in range(h):
        for j in range(w):
            # if pointInPolygon(j, i, point1):
                x = (M[0][0]*j + M[0][1]*i + M[0][2]) / (M[2][0]*j + M[2][1]*i + M[2][2]) + 0.5
                y = (M[1][0]*j + M[1][1]*i + M[1][2]) / (M[2][0]*j + M[2][1]*i + M[2][2]) + 0.5
                x, y = int(x), int(y)
                # print(x, y)
                if 1 <= x < point2[2][0]-1 and 1 <= y < point2[2][1]-1:
                    img1[y, x, :] = image[i, j, :]
                    img1[y, x-1, :] = image[i, j, :]
                    img1[y, x+1, :] = image[i, j, :]
                    img1[y-1, x, :] = image[i, j, :]
                    img1[y+1, x, :] = image[i, j, :]
    img2 = cv2.warpPerspective(image, M, (300, 300))
    img = np.hstack((img1, img2))
    show(img)




def main():
    image = cv2.imread(path)
    img = image.copy()
    point1 = np.float32([[348, 183], [549, 191], [580, 613], [332, 618]])
    point2 = np.float32([[0, 0], [300, 0], [300, 300], [0, 300]])
    warp(image, point1, point2)


    img = draw_line(img, point1)
    images = np.hstack((image, img))
    show(images)


    # point1 = np.float32([[348, 183], [549, 191], [580, 613], [332, 618]])
    # point2 = np.float32([[0, 0], [300, 0], [300, 300], [0, 300]])
    # M = cv2.getPerspectiveTransform(point1, point2)
    # print(M.shape)
    # print(M)
    # img = cv2.warpPerspective(image, M, (300, 300))
    # show(img)


if __name__ == '__main__':
  main()

 

posted @ 2020-05-08 19:40  Baby-Lily  阅读(6111)  评论(0编辑  收藏  举报