仿射變換和透視變換
仿射變換是把一個二維坐標系轉換到另一個二維坐標系的過程,轉換過程坐標點的相對位置和屬性不發生變換,是一個線性變換,該過程只發生旋轉和平移過程。因此,一個平行四邊形經過仿射變換后還是一個平行四邊形。
所以,仿射= 旋轉 + 平移
透視變換是把一個圖像投影到一個新的視平面的過程,該過程包括:把一個二維坐標系轉換為三維坐標系,然后把三維坐標系投影到新的二維坐標系。該過程是一個非線性變換過程,因此,一個平行四邊形經過透視變換后只得到四邊形,但不平行。
透視變換的變換關系如下:
下面是通過變換關系和調用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()