nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

"Нормируем" матрицу для вычисления аффинного преобразования

В прошлый раз мы получили такую матрицу:


Точнее, должны были получить такую, но я забыл, что уже начал её "причёсывать" и привёл в посте матрицу, где верхние 2 строки уже поделены на 8. Потом думаю "что-то не то, не могло же мне так повезти, что "сходу" все значения в диапазоне -1..+1, и все довольно крупные. Сегодня проверил и понял - действительно не могло :)

Предполагается, что мы посчитали её заблаговременно, а на этапе захвата умножаем её справа на матрицу 6x2, составленную из обнаруженных точек, расположенных в правильном порядке - и получим матрицу аффинного преобразования. Причём, если эта матрица обнаруженных точек будет в пикселях - то и вектор параллельного переноса (rx, ry) будет выражен в пикселях, а основная матрица 2х2 - в пикселях на метр.

Но нам пиксели как таковые не интересны - куда интереснее получить параллельный перенос в радианах (это и будут углы тангажа и курса), а основную матрицу - в радианах на метр. Тогда, если взять обратную величину от масштаба, мы получим ДАЛЬНОСТЬ В МЕТРАХ.

Поэтому нужно эту матрицу ещё немного подрихтовать, чтобы после умножения на неё получать настолько информативные результаты, насколько это возможно :) И ещё, может, заставить её выправить "прямоугольные пиксели", которые сейчас получаются на моём макете?


Я же пока использую аналоговую камеру, и оцифровываю её немного не на той частоте, 25 МГц. Полезная часть строки в 1280 пикселей занимает 43 мкс, то есть предполагается по 33,6 нс на пиксель, или частота дискретизации 29,8 МГц. Увы, я не могу её задать в этом макете: ФАПЧ (PLL) в ПЛИС 5576ХС4Т нету, есть два источника тактовой частоты: генератор на 80 МГц и Ethernet-контроллер. Последний можно настроить выдавать либо 25 МГц (как сейчас, "недолёт"), либо 33 МГц ("перелёт"). И даже если я туда впаяю-таки другой генератор, сейчас QuatCore на 29,8 МГц может не зафурычить, хотя я наверное знаю, как его ещё разогнать :)

Результатом становится изображение, сплющенное по горизонтали. Если по этим координатам найти матрицу аффинного преобразования, она покажет данное сплющивание, но наши алгоритмы "решат", что это мы смотрим на мишень не под прямым углом, а сбоку, оттого она и ужалась. Нехорошо!

Вообще, в лётном изделии такой проблемы быть не должно, там будет стоять фотоприёмная матрица 1205ХВ014 с квадратными пикселями и встроенными АЦП, да и оптика настолько простая (2 сферические линзы, отн. отверстие 1:11, можно было и одной обойтись скорее всего), что геометрических искажений я не ожидаю.

Для этих алгоритмов я вводил величину α - угловой размер пикселя. Для макета имеет смысл ввести две величины, αx и αy, по горизонтали и вертикали, соответственно.

Когда-то я подсчитал, что в лётном изделии должно получиться α = 2419 пикселей на радиан. Пока что зададим и для макета αy = 2419 пикс/рад, т.к по строкам у нас всё чётко, не можем же мы "мимо строк" начать считывать!

А вот αx надо уменьшить, ведь пиксели у нас получились слишком "широкие". Так что помножим на 25 МГц, поделим на 29,7 МГц, и получим αx≈2032 пикселя/рад.

Более точные значения собираюсь получить в ближайшие пару недель, поместив на заданном расстоянии от объектива "настроечную таблицу". Надо только придумать рисунок этой таблицы, распечатать её и поковыряться...

Почему-то я был уверен, что эти αx и αy можно "включить" в уже посчитанную матрицу 3х6, так что различие в масштабах "выправится" и аффинное преобразование мы получим корректное. Не тут-то было! Чтобы обработать нашу поставленную "на попа" матрицу FT по столбцам (один столбец домножить на одно число, другой столбец - на другое), умножать надо на матрицу 2х2 СПРАВА, а не слева! И свести всё к одному матричному умножению не удастся, как ни удивительно.

Ну и ладно, тогда у меня есть идейка, как скорректировать координаты ещё во время обнаружения точек... Тогда будем пока использовать "усреднённую" α, например, среднее геометрическое, 2217 пикс/рад. Просто отмасштабировать - не проблема, умножать на скаляр можно в любом месте :)

И делить тоже. Нам нужно все компоненты матрицы поделить на 2217, при этом получатся величины, не превышающие 0,0025. Работать с ними неудобно в любом виде, поэтому нужно ещё домножить на степень двойки. Хочется получить все коэффициенты в диапазоне от -1 до +1, это наш "родной" для QuatCore формат Q1.15. Моё мнение: нижнюю строку нужно домножить на 211=2048, а две верхних: на 28=256. Тогда получится следующая матрица:



Как видно, две верхние строки нельзя помножить ещё на 2, уже выйдем за диапазон. Нижняя строка далека от "насыщения", но я могу придумать вполне реальную ситуацию, где умножение её хотя бы на 2 уже приведёт к переполнению во время вычисления матрицы аффинного преобразования. Очень просто: маленький масштаб (дистанция 15 метров, когда отдельные точки наконец-то устойчиво разрешаются, не сливаясь в одно мутное пятно) и мишень, сдвинутая к краю поля зрения. Грубо говоря, получаем 6 одинаковых координат вблизи края, и чтобы не случилось переполнения, сумма коэффициентов в нижней строке должна быть меньше единицы.

Сумма модулей коэффициентов на верхней строке составляет 0,97, т.е меньше единицы. Это значит, что если каждый положительный коэффициент умножать на максимальное положительное число 32767, а каждый отрицательный - на максимальное отрицательное -32768, то всё равно переполнения случиться не сможет, не только "в конце", но и в процессе вычислений.

Вторая строка в этом плане более "рискованная": сумма модулей равна 2,61, т.е если брать произвольные входные данные, переполнение вызвать легко. Но если мы имеем дело непосредственно с нашей мишенью, переполнения быть не может, даже если она заполнит собой всё поле зрения. Обосновать это можно следующим образом: максимальный коэффициент у нас получится при крене в 0, 90, 180 или 270 градусов, когда весь масштаб "сосредоточен" в 2 из 4 элементах матрицы 2х2, и они оба будут по модулю равны масштабу.

Надо просто сообразить, какой максимальный масштаб может быть записан. В матрице F у нас будут значения от -1 до +1, где единица соответствует 512 пикселям. Поэтому, если бы мы не трогали исходную матрицу, то масштаб имел бы размерность "половина поля зрения на метр", или 12 градусов на метр. (поле зрения 24°).

Когда мы поделили его на 2217 пикс/рад, то должны бы получиться "радианы на метр", если бы матрица F представлялась в пикселях, а так в 512 раз больше (т.к 512 пикселей соотв. "единице"). Действительно, если число уменьшилось в 2217 раз, то "единица" будет соответствовать масштабу в 2217 раз больше, т.е 12 градусов/м * 2217 ≈ 464 рад/м. Если бы взяли свои 2419 пикс/рад, получили бы здесь 507 рад/м. Немного всё криво, поскольку фотоприёмная матрица плоская само собой, и уже между tg(12°) и просто 12° в радианах есть небольшая разница.

Затем мы помножили эту матрицу на 256 - и получили размерность "два радиана на метр". То есть, если масштаб = 1 (крайнее представимое значение), это на самом деле 2 рад/м. Возьмём обратную величину - и выходит 0,5 метра - КАК В АПТЕКЕ! Ведь 0,5 метра - это как раз минимальная дальность, которую мы должны измерять. На самом деле, 0,5 метра - от кромки ВИПС до кромки мишени, а учитывая, что эти 6 уголковых отражателей ещё "утоплены" минимум на 6 см, выйдет и того больше, а масштаб, соответственно, меньше.

Остаётся последний вопрос: не может ли случиться переполнения посреди вычислений? Тут я всё-таки поковырялся в экселе, попробовал прибавить "постоянную составляющую" - сдвинуть всю мишень на один край поля зрения при максимальном масштабе. Тогда уже появилось чередование знаков, т.е промежуточные результаты оказались чуть выше финальных:


Но это не страшно: в QuatCore аккумулятор имеет дополнительный старший бит, позволяющий представлять числа от -2 до +2, так что ничего страшного не случится заведомо. Так подумать, даже если б не было этого дополнительного бита, должно всё правильно посчитаться: один раз перескочит единицу и запишет "1,077" как "-0,923", но потом вычтет из него 0,15765 - и "волшебным образом" получит 0,919. Само по себе АЛУ не делает насыщения результата, он насыщается только когда результаты переносишь на шину данных.


Итак, матрицу, которую мы посчитали по красивой формуле, нужно ещё поделить на α - "количество пикселей на радиан", а потом нижнюю строку умножить на 2048, а верхние строки на 256. И результат представить в формате Q1.15:



И в память её надо поместить столбец за столбцом. Сейчас так и сделаем - и опробуем процедуру перемножения матриц...
Tags: ПЛИС, математика, программки, работа, странные девайсы
Subscribe

Recent Posts from This Journal

  • Тестируем atan1 на QuatCore

    Пора уже перебираться на "железо" потихоньку. Решил начать с самого первого алгоритма, поскольку он уже был написан на ассемблере. В программу внёс…

  • Формулы приведения, что б их... (и atan на ТРЁХ умножениях)

    Формулу арктангенса на 4 умножениях ещё немножко оптимизировал с помощью алгоритма Ремеза: Ошибка уменьшилась с 4,9 до 4,65 угловой секунды, и…

  • Алгоритм Ремеза в экселе

    Вот и до него руки дошли, причина станет ясна в следующем посте. Изучать чужие библиотеки было лениво (в том же BOOSTе сам чёрт ногу сломит), писать…

  • atan на ЧЕТЫРЁХ умножениях

    Мишка такой человек — ему обязательно надо, чтоб от всего была польза. Когда у него бывают лишние деньги, он идёт в магазин и покупает какую-нибудь…

  • Ай да Пафнутий Львович!

    Решил ещё немного поковыряться со своим арктангенсом. Хотел применить алгоритм Ремеза, но начал с узлов Чебышёва. И для начала со своего "линейного…

  • atan(y/x) на двух умножениях!

    Чего-то никак меня не отпустит эта тема, всё кажется, что есть очень простой и эффективный метод, надо только его найти! Сейчас вот такое…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments