亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

圖像的二維旋轉

圖像的二維旋轉

jeck貓 2023-05-16 14:54:41
我正在嘗試將圖像旋轉任何給定角度。我以圖像的中心為原點旋轉。但是代碼沒有按預期進行旋轉。我附上下面的代碼。import mathimport numpy as npimport cv2im = cv2.imread("Samples\\baboon.jpg", cv2.IMREAD_GRAYSCALE)new = np.zeros(im.shape,np.uint8)new_x = im.shape[0] // 2new_y = im.shape[1] // 2x = int(input("Enter the angle : "))trans_mat = np.array([[math.cos(x), math.sin(x), 0],[-math.sin(x), math.cos(x), 0],[0, 0, 1]])for i in range(-new_x, im.shape[0] - new_x):    for j in range(-new_y, im.shape[1] - new_y):        vec = np.matmul([i, j, 1], trans_mat)        if round(vec[0] + new_x) < 512 and round(vec[1] + new_y) < 512:            new[round(vec[0]+new_x), round(vec[1]+new_y)] = im[i+new_x,j+new_y]cv2.imshow("rot",new)cv2.imshow("1",im)cv2.waitKey(0)cv2.destroyAllWindows()
查看完整描述

3 回答

?
慕少森

TA貢獻2019條經驗 獲得超9個贊

看起來您正在嘗試實施最近鄰重采樣器。您正在做的是遍歷圖像并將每個輸入像素映射到輸出圖像中的新位置。這可能會導致像素錯誤地相互覆蓋、輸出像素留空等問題。


我會建議(根據經驗)你正在向后看問題。您不應查看輸入像素在輸出中的最終位置,而應考慮每個輸出像素在輸入中的起始位置。這樣,您就不會對最近的鄰居產生歧義,并且整個圖像數組都將被填充。


你想繞中心旋轉。您正在使用的當前旋轉矩陣圍繞 旋轉(0, 0)。為了彌補這一點,您需要將圖像的中心平移到(0, 0),旋轉,然后再平移回來。我不會開發完整的仿射矩陣,而是會向您展示如何手動執行各個操作,然后如何將它們組合到變換矩陣中。


人工計算


首先得到一張輸入輸出圖像:


im = cv2.imread("Samples\\baboon.jpg", cv2.IMREAD_GRAYSCALE)

new = np.zeros_like(im)

然后確定旋轉中心。清楚你的維度x通常是列 (dim 1),而不是行 (dim 0):


center_row = im.shape[0] // 2

center_col = im.shape[1] // 2

計算圖像中每個像素的徑向坐標,整形為相應的維度:


row_coord = np.arange(im.shape[0])[:, None] - center_row

col_coord = np.arange(im.shape[1]) - center_col

row_coord是輸出col_coord圖像中距中心的距離?,F在計算它們在輸入中的位置。請注意,我們可以使用廣播來避免循環的需要。我在這里遵循您最初的角度定義約定,并找到反向旋轉以確定源位置。這里的最大區別在于度數的輸入被轉換為弧度,因為這是三角函數所期望的:


angle = float(input('Enter Angle in Degrees: ')) * np.pi / 180.0 

source_row = row_coord * np.cos(angle) - col_coord * np.sin(angle) + center_row

source_col = row_coord * np.sin(angle) + col_coord * np.cos(angle) + center_col

如果保證所有索引都落在輸入圖像中,您甚至不需要預先分配輸出。你可以從字面上做new = im[source_row, source_col]。但是,您需要屏蔽索引:


mask = source_row >= 0 & source_row < im.shape[0] & source_col >= 0 & source_col < im.shape[1]

new[mask] = im[source_row[mask].round().astype(int), source_col[mask].round().astype(int)]

仿射變換


現在讓我們看一下使用仿射變換。首先,您想從坐標中減去中心。假設您有一個列向量[[r], [c], [1]]。轉換為零將是矩陣


[[r']    [[1  0 -rc]  [[r]

 [c']  =  [0  1 -cc] . [c]

 [1 ]]    [0  0  1 ]]  [1]]

然后應用(向后)旋轉:


[[r'']    [[cos(a) -sin(a) 0]  [[r']

 [c'']  =  [sin(a)  cos(a) 0] . [c']

 [ 1 ]]    [  0       0    1]]  [1 ]]

最后,你需要翻譯回中心:


[[r''']    [[1  0 rc]  [[r'']

 [c''']  =  [0  1 cc] . [c'']

 [ 1  ]]    [0  0  1]]  [ 1 ]]

如果你從右到左依次將這三個矩陣相乘,你會得到


   [[cos(a)   -sin(a)    cc * sin(a) - rc * cos(a) + rc]

M = [sin(a)    cos(a)   -cc * cos(a) - rc * sin(a) + cc]

    [  0         0                      1              ]]

如果您構建一個完整的輸出坐標矩陣而不是我們開始的子集數組,您可以使用np.matmul,也就是@運算符為您進行乘法運算。對于這樣一個簡單的案例,不需要這種復雜程度:


matrix = np.array([[np.cos(angle), -np.sin(angle),  col_center * np.sin(angle) - row_center * np.cos(angle) + row_center],

                   [np.sin(angle),  np.cos(angle), -col_center * np.cos(angle) - row_center * np.sin(angle) + col_center],

                   [0, 0, 1]])


coord = np.ones((*im.shape, 3, 1))

coord[..., 0, :] = np.arange(im.shape[0]).reshape(-1, 1, 1, 1)

coord[..., 1, :] = np.arange(im.shape[1]).reshape(-1, 1, 1)


source = (matrix @ coord)[..., :2, 0]

處理的其余部分與手動計算非常相似:


mask = (source >= 0 & source_row < im.shape).all(axis=-1)

new[mask] = im[source[0, mask].round().astype(int), source_col[1, mask].round().astype(int)]



查看完整回答
反對 回復 2023-05-16
?
躍然一笑

TA貢獻1826條經驗 獲得超6個贊

我試圖實現 Madphysicist 的矩陣乘法方法。這是實現,對于那些關心的人:


#!/usr/bin/env python

# -*- coding: utf-8 -*-


import numpy as np

import matplotlib.pyplot as plt

from pathlib import Path


path = Path(".")

img = plt.imread(path.resolve().parent / "img_align" / "faces_imgs" / "4.jpg")

angle = 15



def _transform(rot_mat, x, y):

    """

    conveninece method for matrix multiplication

    """

    return np.matmul(rot_mat, np.array([x, y, 1]))



def rotate(img, angle):

    angle %= 360

    angle = np.radians(angle)

    new = np.zeros_like(img)

    cx, cy = tuple(x / 2 for x in img.shape[:2])


    # Angles are reverse as we are interpolating from destination to source

    rot_mat = np.array(

        [

            [np.cos(-angle), -np.sin(-angle), 0],

            [np.sin(-angle), np.cos(-angle), 0],

            [0, 0, 1],

        ]

    )


    rot_mat[0, 2], rot_mat[1, 2], _ = _transform(rot_mat, -cx, -cy)


    # build combined affine transformation matrrix

    rot_mat[0, 2] += cx

    rot_mat[1, 2] += cy


    coord = np.ones((*img.shape, 3, 1))  # [576x336x3x3x1]

    coord[..., 0, :] = np.arange(img.shape[0]).reshape(-1, 1, 1, 1)

    coord[..., 1, :] = np.arange(img.shape[1]).reshape(-1, 1, 1)


    source = (rot_mat @ coord)[..., :2, 0]

    x_mask = source[..., 0]

    y_mask = source[..., 1]

    mask = (

        (x_mask >= 0)

        & (x_mask < img.shape[0])

        & (y_mask >= 0)

        & (y_mask < img.shape[1])

    ).all(axis=-1)


    # Clipping values to avoid IndexError

    new[mask] = img[

        x_mask[..., 0][mask].round().astype(int).clip(None, img.shape[0] - 1),

        y_mask[..., 1][mask].round().astype(int).clip(None, img.shape[1] - 1),

    ]

    plt.imsave("test.jpg", new)



if __name__ == "__main__":

    rotate(img, angle)


查看完整回答
反對 回復 2023-05-16
?
嚕嚕噠

TA貢獻1784條經驗 獲得超7個贊

我認為這就是您要尋找的?

這是代碼

ang = int(input("Enter the angle : "))

im = cv2.imread("Samples\\baboon.jpg", cv2.IMREAD_GRAYSCALE)



def rotimage(image):

? ? row,col = image.shape[0:2]

? ? center=tuple(np.array([col,row])/2)

? ? rot_mat = cv2.getRotationMatrix2D(center,ang,1.0)

? ? new_image = cv2.warpAffine(image, rot_mat, (col,row))

? ? return new_image



new_image = rotimage(im)

cv2.imshow("1",new_image)

cv2.waitKey(0)


查看完整回答
反對 回復 2023-05-16
  • 3 回答
  • 0 關注
  • 174 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號