Регистрация изображений и аффинное преобразование в Python

Я читал Programming Computer Vision with Python Яна Эрика Солема, довольно хорошую книгу. , однако я не смог прояснить вопрос о регистрации изображения.

По сути, у нас есть куча изображений (лиц), которые нужно немного выровнять, поэтому первое, что необходимо, — это выполнить жесткое преобразование через преобразование подобия:

x' = | sR t | x
     | 0  1 |

где x — это вектор (в данном случае набор координат), который нужно преобразовать в x' посредством поворота R, переноса t и, возможно, масштабирования s.

Solem вычисляет это жесткое преобразование для каждого изображения, которое возвращает матрицу вращения R и вектор смещения как tx и ty:

R,tx,ty = compute_rigid_transform(refpoints, points)

Однако по какой-то причине он переупорядочивает элементы R:

T = array([[R[1][1], R[1][0]], [R[0][1], R[0][0]]])

а позже он выполняет аффинное преобразование:

im2[:,:,i] = ndimage.affine_transform(im[:,:,i],linalg.inv(T),offset=[-ty,-tx])

В этом примере это аффинное преобразование выполняется для каждого канала, но это не имеет значения. im[:,:,i] — это изображение, которое нужно обработать, и эта процедура возвращает другое изображение.

Что такое T и почему мы инвертируем эту матрицу в аффинном преобразовании? И каковы обычные шаги для достижения регистрации изображения?

Обновлять

Здесь вы можете найти соответствующую часть этого кода в Google Книгах. Начинается внизу страницы 67.


person Robert Smith    schedule 17.10.2012    source источник
comment
Я не уверен, что происходит с переупорядочиванием R (для начала, матрица вращения в 3D должна быть 3x3), но в целом обратная матрица вращения отменяет вращение (точно так же, как отрицательные значения переводов отменяют переводы). Может быть, пример R и результирующего T поможет.   -  person beaker    schedule 18.10.2012
comment
Я так и думал, но ошибся с матрицей T. Должно быть так: T = array([[R[1][1], R[1][0]], [R[0][1], R[0][0]]]) Я не знаю, поможет ли пример R, так как он содержит кучу чисел. Как вы знаете, R равно [[cos(t) -sin(t)] [sin(t) cos(t)]] и T должно быть [[cos(t) sin(t)] [-sin(t) Стоимость)]]   -  person Robert Smith    schedule 18.10.2012
comment
Вы уверены, что у вас правильный массив T? Изменение базиса должно быть обратным R-транспонированию. (В LaTeX это было бы намного проще...)   -  person beaker    schedule 20.10.2012
comment
Я добавил обновление с соответствующей частью. Похоже, Т прав. В любом случае, почему должно быть Т?   -  person Robert Smith    schedule 20.10.2012
comment
Мне кажется ошибка в коде. T кажется просто транспонированием R, что для матрицы вращения совпадает с инверсией. Затем он выполняет инверсию (снова) в вызове ndimage.affine_transform. Я думаю, что этой функции должно быть передано либо T, либо linalg.inv(R).   -  person aganders3    schedule 20.10.2012
comment
Ты прав. По сути, это просто вычисление R, но почему вы думаете, что он должен вычислять T или T^{-1}?   -  person Robert Smith    schedule 20.10.2012
comment
Я не знаю - также оглядываясь на ваш пост, я думаю, что T - это не просто транспонирование R. Сейчас я запутался больше, чем когда-либо. Вы пробовали запустить этот код?   -  person aganders3    schedule 20.10.2012
comment
Нет, ты был прав. T — это транспонирование R, и, как и ожидалось, T^{-} — это R. По какой-то причине в последнем обновлении, которое я опубликовал, T вернулся к более ранней версии, которая содержала координату 3. Я даже не коснулся этой части сообщение ? Сейчас опять поправили.   -  person Robert Smith    schedule 20.10.2012
comment
Забыл упомянуть, что я не запускал этот код, потому что для полного воспроизведения этого примера нужна библиотека, и у меня возникли проблемы с ее установкой.   -  person Robert Smith    schedule 20.10.2012
comment
@ganders3 Если вы добавите свой комментарий в качестве ответа, я приму его. Спасибо за вашу помощь :-)   -  person Robert Smith    schedule 21.10.2012
comment
Спасибо Роберт! Надеюсь, с этим разобрались. Если вы можете запустить код, чтобы подтвердить, что это ошибка, вам следует рассмотреть возможность отправки его как такового на сайт O'Reilly.   -  person aganders3    schedule 22.10.2012


Ответы (2)


Мне кажется ошибка в коде. T кажется просто транспонированием R, что для матрицы вращения совпадает с инверсией. Затем он выполняет инверсию (снова) в вызове ndimage.affine_transform. Я думаю, что этой функции должно быть передано либо T, либо linalg.inv(R).

person aganders3    schedule 21.10.2012

Я постараюсь ответить на ваш вопрос и указать на ошибку (?) в книге. (1) Зачем использовать T = array([[R[1][1], R[1][0]], [R[0][1], R[0][0]]])? поскольку R,tx,ty = calculate_rigid_transform(refpoints, points) вычисляет матрицу поворота и перевод в форме:

|x'| = s|R[0][0] R[0][1]||x| + |tx|             Equation (1)
|y'|    |R[1][0] R[1][1]||y|   |ty|

ОДНАКО, OUT = ndimage.affine_transform(IN,A,b) требует координаты в форме (y,x) НЕ в порядке (x,y). Таким образом, приведенное выше уравнение (1) станет

|y'| = s|R[1][1] R[1][0]||y| + |ty| = T|y| + |ty|        Equation(2)
|x'|    |R[0][1] R[0][0]||x|   |tx|    |x|   |tx|

Тогда в функции ndimage.affine_transform() матрица будет linalg.inv(T), а не linalg.inv(R).

(2) Аффинное преобразование OUT = ndimage.affine_transform(IN,A,b) на самом деле равно A*OUT + b => IN . Согласно уравнению (2), перепишем его как

|y| = inv(T)|y'| - inv(T)|ty|
|x|         |x'|         |tx|

Таким образом, смещение в функции ndimage.affine_transform() равно inv(T)[-ty, -tx], а не [-ty -tx]. Я думаю, что это ошибка в исходном коде.

person ColorRGB    schedule 27.01.2013
comment
Нет необходимости ссылаться на спрашивающего в вашем ответе. Они будут автоматически уведомлены. - person ChiefTwoPencils; 27.01.2013
comment
@ColorRGB Спасибо за ваш ответ. Можете ли вы улучшить читаемость своего ответа для дальнейшего использования. Уследить за этим сейчас достаточно сложно. - person Robert Smith; 29.01.2013