Вращающееся 2D-изображение в градациях серого с матрицей преобразования - PullRequest
0 голосов
/ 17 октября 2019

Я новичок в обработке изображений, поэтому я действительно запутался в отношении системы координат с изображениями. У меня есть образец изображения, и я пытаюсь повернуть его на 45 по часовой стрелке. Моя трансформация матрица T = [ [cos45 sin45] [-sin45 cos45] ]

Вот код:

import numpy as np
from matplotlib import pyplot as plt
from skimage import io

image = io.imread('sample_image')
img_transformed = np.zeros((image.shape), dtype=np.uint8)

trans_matrix = np.array([[np.cos(45), np.sin(45)], [-np.sin(45), np.cos(45)]])

for i, row in enumerate(image):
    for j,col in enumerate(row):
        pixel_data = image[i,j] #get the value of pixel at corresponding location
        input_coord = np.array([i, j]) #this will be my [x,y] matrix
        result = trans_matrix @ input_coord 
        i_out, j_out = result #store the resulting coordinate location

        #make sure the the i and j values remain within the index range
        if (0 < int(i_out) < image.shape[0]) and (0 < int(j_out) < image.shape[1]):
            img_transformed[int(i_out)][int(j_out)] = pixel_data

plt.imshow(img_transformed, cmap='gray')

Изображение получается искаженным и кажется неправильным. Я знаю, что в пиксельных координатах источник находится в верхнем левом углу (строка, столбец). происходит ли поворот относительно начала координат в верхнем левом углу? Есть ли способ сместить начало координат в центр или любую другую заданную точку?

Спасибо всем!

1 Ответ

1 голос
/ 18 октября 2019

Да, как вы подозреваете, вращение происходит относительно верхнего левого угла, который имеет координаты (0, 0). (Также: тригонометрические функции NumPy используют радианы , а не градусы, поэтому вам нужно преобразовать угол.) Чтобы вычислить вращение относительно центра, вы делаете небольшой хак: вы вычисляете преобразование для перемещенияизображение так, чтобы оно было отцентрировано (0, 0), затем вы поворачиваете его, а затем перемещаете результат назад. Вам нужно объединить эти преобразования в последовательности, потому что если вы сделаете это одно за другим, вы потеряете все в отрицательных координатах.

Это сделать намного проще, используя Однородные координаты , которые добавляют дополнительное "фиктивное" измерение к вашему изображению. Вот как ваш код будет выглядеть в однородных координатах:

import numpy as np
from matplotlib import pyplot as plt
from skimage import io

image = io.imread('sample_image')
img_transformed = np.zeros((image.shape), dtype=np.uint8)

c, s = np.cos(np.radians(45)), np.sin(np.radians(45))
rot_matrix = np.array([[c, s, 0], [-s, c, 0], [0, 0, 1]])

x, y = np.array(image.shape) // 2
# move center to (0, 0)
translate1 = np.array([[1, 0, -x], [0, 1, -y], [0, 0, 1]])
# move center back to (x, y)
translate2 = np.array([[1, 0, x], [0, 1, y], [0, 0, 1]])

# compose all three transformations together
trans_matrix = translate2 @ rot_matrix @ translate1

for i, row in enumerate(image):
    for j,col in enumerate(row):
        pixel_data = image[i,j] #get the value of pixel at corresponding location
        input_coord = np.array([i, j, 1]) #this will be my [x,y] matrix
        result = trans_matrix @ input_coord 
        i_out, j_out, _ = result #store the resulting coordinate location

        #make sure the the i and j values remain within the index range
        if (0 < int(i_out) < image.shape[0]) and (0 < int(j_out) < image.shape[1]):
            img_transformed[int(i_out)][int(j_out)] = pixel_data

plt.imshow(img_transformed, cmap='gray')

Вышеприведенное должно работать нормально, но вы, вероятно, получите некоторые черные пятна из-за алиасинга . Может случиться так, что нет координат i, j от входной земли точно на выходном пикселе, так что пиксель никогда не обновляется. Вместо этого вам нужно выполнить итерацию по пикселям выходного изображения, а затем использовать обратное преобразование, чтобы найти, какой пиксель во входном изображении отображается ближе всего к этому выходному пикселю. Что-то вроде:

inverse_tform = np.linalg.inv(trans_matrix)

for i, j in np.ndindex(img_transformed.shape):
    i_orig, j_orig, _ = np.round(inverse_tform @ [i, j, 1]).astype(int)
    if i_orig in range(image.shape[0]) and j_orig in range(image.shape[1]):
        img_transformed[i, j] = image[i_orig, j_orig]

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...