1. 程式人生 > >常見的影象變換操作——平移變換,比例變換,對稱變換,旋轉變換,投影變換

常見的影象變換操作——平移變換,比例變換,對稱變換,旋轉變換,投影變換

常見的影象變換操作

視窗檢視變換

使用者域:程式設計師用來定義草圖的整個自然空間WD,它是一個實數域,理論上WD是連續無限的。

視窗區:使用者指定的任一區域W,它是WD的子域,一般為矩形域。

螢幕域:裝置輸出圖形的最大區域DC,它是有限的整數域, 如:如顯示器有1600*1200個畫素。

檢視區:任何小於等於螢幕域的區域。一般為矩形。一個 螢幕上可定義多個檢視。

 

 

 

 

 

 

視窗和檢視之間的座標轉換

 

 

 

 

 

 

對於視窗和檢視的座標變換,我們可以根據變換的比例關係得到如下等式:

 根據公式,可以推匯出下面的變換公式:

圖形的幾何變換

對各種圖形的幾何變換,實際上是對點的變換,對原來圖形中的一點座標通過變換生成一個新的點座標。二維圖形的幾何變換的表示採用3*3矩陣的形式,稱為變換矩陣,點的座標表示採用齊次座標形式,故幾何變換操作的過程是將變換矩陣M作用於齊次座標點P生成新的座標點P´,即P´=PM。其中齊次座標齊次座標表示就是用n+1維向量表示一個n維向量,齊次座標不唯一,規範化齊次座標表示就是h=1的齊次座標。

平移變換

x´=x+Tx,y´=y+Ty

 比例變換

x’=x . Sx, y’=y . Sy

 對稱變換

x’=ax+by,y’=dx+ey

 

 旋轉變換

x´=xcosθ-ysinθ,y´=xsinθ+ycosθ

錯切變換

x’=x+by,  y’=dx+y

 

 複合變換

一般的圖形變換大多是複合變換,即由多個基本幾何變換組合而成,複合變換矩陣實際上是一系列基本幾何變換矩陣的乘積結果。

例如在圖形繞平面上的一點(x0,y0)作旋轉變換θ角度:

[x´,y´,1] = [x,y,1]T2(-x0,-y0)R2(θ)T2(x0,y0)

 

 形體的透視變換

要把現實世界的三維物體在計算機的二維螢幕上 顯示出來,必須經過投影變化,把物體從三維表示形式 轉化為二維表示形式。

 下面給出python實現的影象旋轉:

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 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 cal_rotate_point(center, point, degree):
    x, y = center
    point_ro = np.zeros_like(point)
    rad = np.deg2rad(degree)
    x1 = x - (x * np.cos(rad) - y * np.sin(rad))
    y1 = y - (x * np.sin(rad) + y * np.cos(rad))
    for i in range(point_ro.shape[0]):
        point_ro[i][0] = int(point[i][0] * np.cos(rad) - point[i][1] * np.sin(rad) + x1 + 0.5)
        point_ro[i][1] = int(point[i][0] * np.sin(rad) + point[i][1] * np.cos(rad) + y1 + 0.5)
    return point_ro


def rotate(image, center, degree):
    x, y = center[0], center[1]
    h, w = image.shape[:2]
    img = np.zeros_like(image)
    rad = np.deg2rad(degree)
    for i in range(w):
        for j in range(h):
            ir = (i-x) * np.cos(rad) - (j-y) * np.sin(rad) + x + 0.5
            jr = (i-x) * np.sin(rad) + (j-y) * np.cos(rad) + y + 0.5
            ir = int(ir)
            jr = int(jr)
            if 1 <= ir < w-1 and 1 <= jr < h-1:
                img[jr, ir, :] = image[j, i, :]
                img[jr-1, ir, :] = image[j, i, :]  # 對該畫素的周圍4個畫素進行賦值
                img[jr+1, ir, :] = image[j, i, :]
                img[jr, ir-1, :] = image[j, i, :]
                img[jr, ir+1, :] = image[j, i, :]
    return img


def rotation(image, center, degree):
    center_h, center_w = center[:2]
    M = cv2.getRotationMatrix2D((center_h, center_w), -degree, 1)  # 引數依次為旋轉中心, 旋轉角度, 變換尺度, 返回變換矩陣
    img = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
    return img


def cal_rotation_point(center, point, degree):
    center_w, center_h = center[:2]
    M = cv2.getRotationMatrix2D((center_w, center_h), -degree, 1)  # 引數依次為旋轉中心, 旋轉角度, 變換尺度, 返回變換矩陣
    point = np.array(point)
    point = np.insert(point, 2, values=np.ones(4), axis=1)
    M = np.mat(M).T
    new_point = np.dot(point, M)
    new_point = new_point.astype(int)
    new_point = [[new_point[i, 0], new_point[i, 1]] for i in range(new_point.shape[0])]
    return new_point


def my_rotate(image, point, degree, center):
    image_box = draw_line(image.copy(), point)
    img = rotate(image.copy(), (center[0], center[1]), degree)
    point_ro = cal_rotate_point((center[0], center[1]), point, degree)
    image_ro_box = draw_line(img, point_ro)
    images = np.hstack((image_box, image_ro_box))
    return images


def cv_rotate(image, point, degree, center):
    image_box = draw_line(image.copy(), point)
    img = rotation(image.copy(), (center[0], center[1]), degree)
    point_ro = cal_rotation_point((center[0], center[1]), point, degree)
    image_ro_box = draw_line(img, point_ro)
    print(point_ro)
    images = np.hstack((image_box, image_ro_box))
    return images


def main():
    image = cv2.imread(path)
    print(image.shape)
    center = (image.shape[1]//2, image.shape[0]//2)
    center = (0, 0)
    point = [[348, 183], [549, 191], [580, 613], [332, 618]]
    degree = 15
    images1 = my_rotate(image, point, degree, center)
    images2 = cv_rotate(image, point, degree, center)
    images = np.vstack((images1, images2))
    show(images)


if __name__ == '__main__':
    main()

 

&n