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)]

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)

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)
添加回答
舉報