Перейти к содержанию
    

Сбор идей по повороту картинки

Всем доброго дня!

Ищутся мысли по поводу оптимальной реализации поворота картинки.

Что сделано:

Поворот картинки через CORDIC. Производится поворот координаты каждого пикселя (по конвейеру) на заданный угол, вычисляется адрес пикселя в читаемой (не повернутой) картинке, прочитанные пиксели выводятся последовательно в формате ITU656.  

Что не устраивает:

При повороте пиксели из исходной картинки читаются не через burst transfer, а по одному, т.к. при повороте получаем чтение не по последовательным, а по произвольным адресам. Поэтому шина ДДР сильно просаживается по производительности. Мало того что пиксели читаются по разным адресам, так еще из 32битного прочитанного слова мне надо только один пиксель, т.е. 8бит. 

Даже если не сразу выводить картинку, а скидывать в память повернутую, а потом выводить - ничего не меняется, т.к.  если читаем по последовательным адресам, тогда записывать повернутую картинку придется по произвольным, так же по одному пикселю. 

Может кто-то как-то решал подобные проблемы неэффективного использования ДДР шины?

Реализация поворота полностью аппаратная.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При повороте края обрезаются или картинка уменьшается и добавляются чёрные поля?

В одном случае считываемых точек больше - в другом записываемых...

 

И потом в ПЛИС обычно множественный доступ по чтению (например к кешу) будет быстрее  множественного доступа по записи (нужен мультиплексор).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

55 минут назад, _4afc_ сказал:

При повороте края обрезаются или картинка уменьшается и добавляются чёрные поля?

В одном случае считываемых точек больше - в другом записываемых...

 

И потом в ПЛИС обычно множественный доступ по чтению (например к кешу) будет быстрее  множественного доступа по записи (нужен мультиплексор).

Картинка при повороте вырезается из картинки бОльшего размера, поэтому ни черных полей, ни масштабирования нет. Поэтому сколько читаем точек, столько и пишем. В моем случае (сейчас) производится только рандомное чтение - дальше считанные данные отправляются сразу в ITU интерфейс, в память уже не попадают.

Аппаратное чтение происходит без участия кэша (cyclone5 или zynq7000), да и весь кадр в кэш наверно не влезет. Аппаратный доступ к кэшу ЕМНИП,  начинается только у ultrascale+. Да и читающий мастер написан для чтения без участия кэша. Хотя я сомневаюсь, что будет сильно лучше, т.к. процессор во время поворота свое молотит, тоже приличные объемы данных ворочает, там весь кэш думаю будет забит. Нов случае с процессором кэш здорово вывозит.

Да, со статикой вариант конечно, решает проблему, но это отдельный корпус, дополнительные габариты и куча занятых ног...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, alexPec said:

Даже если не сразу выводить картинку, а скидывать в память повернутую, а потом выводить - ничего не меняется, т.к.  если читаем по последовательным адресам, тогда записывать повернутую картинку придется по произвольным, так же по одному пикселю. 

Можно сделать внутри FPGA буфер на восемь строк и сохранять во внешней памяти уже повернутые пиксели burst'ами по восемь пикселей за одно обращение к памяти.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

поворот на произвольный угол +-180гр? а то если углы ограничены небольшими градусами может можно обойтись внутренним буфером на несколько строк? и наоборот читать подряд, писать "под углом", но в буфер всего на несколько строк, и выдавать из него строку по заполнении.

ну или даже всё оставить как есть, но сделать промежуточный буфер на несколько строк соответствующих максимальному углу поворота, а не на всю картинку.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только что, blackfin сказал:

Можно сделать внутри FPGA буфер на восемь строк и сохранять во внешней памяти уже повернутые пиксели burst'ами по восемь пикселей за одно обращение к памяти.

Не понял как это. Например, берем (условно, для простоты квадратный экран 500х500) пиксели № (0,0), (1,0),(2,0),(3,0). Их читаем бастом. Поворачиваем их на 90 градусов - они оказываются на позициях (0,499), (0,498), (0,497), (0,496) - это все НЕ последовательные адреса. На 45 градусов, например, повернуть - вообще где попало в памяти после поворота окажутся.

4 минуты назад, _pv сказал:

поворот на произвольный угол +-180гр? а то если углы ограничены небольшими градусами может можно обойтись внутренним буфером на несколько строк? и наоборот читать подряд, писать "под углом", но в буфер всего на несколько строк, и выдавать из него строку по заполнении.

ну или даже всё оставить как есть, но сделать промежуточный буфер на несколько строк соответствующих максимальному углу поворота, а не на всю картинку.

 

Вообще хотелось бы +/- 90 градусов, но даже 30 градусов (меньше даже заморачиваться не стоит) было бы не плохо. Но даже при 30 строка даже в 640 пикс. при повороте займет tg(30)*640 = 369 пикс. по вертикали. Т.е. почти весь кадр 640*480.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 minutes ago, alexPec said:

Не понял как это.

Берем квадратный экран 500х500.

 

Читаем burst'ом во внутреннюю SRAM FPGA из внешней DDR пиксели:

 

1-ая строка: (0,0), (0,1),(0,2),(0,3),...,(0,499);

2-ая строка: (1,0), (1,1),(1,2),(1,3),...,(1,499);

3-я строка: (2,0), (2,1),(2,2),(2,3),...,(2,499);

...

8-ая строка: (7,0), (7,1),(7,2),(7,3),...,(7,499).

 

Пишем burst'ом по 8 beats во внешнюю DDR из внутренней SRAM пиксели:

 

1-ый столбец: (0,0), (1,0),(2,0),(3,0),...,(7,0);

2-ой столбец: (0,1), (1,1),(2,1),(3,1),...,(7,1);

...

459-ый столбец: (0,459), (1,459),(2,459),(3,459),...,(7,459).

 

Повторяем эту операцию для всех 500 строк.

 

Читаем burst'ом из внешней DDR полученные пиксели по строкам и выводим их во внешний порт..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 minutes ago, alexPec said:

Не понял как это. Например, берем (условно, для простоты квадратный экран 500х500) пиксели № (0,0), (1,0),(2,0),(3,0). Их читаем бастом. Поворачиваем их на 90 градусов - они оказываются на позициях (0,499), (0,498), (0,497), (0,496) - это все НЕ последовательные адреса. На 45 градусов, например, повернуть - вообще где попало в памяти после поворота окажутся.

внутреннему буферу на 8 строк при записи наплевать что адреса оказались непоследовательными, а вот прочитали-то вы их бурстом 8 штук последовательно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, туплю что-то.

 

Согласен.

Надо только аппаратно высчитать начало и конец баста ( в смысле адреса). Ну и еще наложится логика маскирования начала записываемого участка и конца, т.к. начало и конец часто не будут совпадать с границами записываемого слова. Но в части оптимизации обращения к ДДР выглядит сильно лучше.

Спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При любом угле - можно уйти от рандомности так:

1 переводим картинку в полярную систему координат с минимальным нужным шагом угла

2 переводим картинку из полярной системы координат начиная с нужного угла.

 

PS: Если исходная картинка статичная - в памяти достаточно иметь результат 1 действия

и совершать над ним только второе...

 

Я так спрайт на экране делал в виде кораблика который поворачивался на тот градус куда корабль повёрнут...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 часов назад, _4afc_ сказал:

При любом угле - можно уйти от рандомности так:

1 переводим картинку в полярную систему координат с минимальным нужным шагом угла

2 переводим картинку из полярной системы координат начиная с нужного угла.

 

PS: Если исходная картинка статичная - в памяти достаточно иметь результат 1 действия

и совершать над ним только второе...

 

Я так спрайт на экране делал в виде кораблика который поворачивался на тот градус куда корабль повёрнут...

не совсем понял мысль. Картинка с матрицы (с камеры) идет в построчно. В память ее лучше всего ложить тоже построчно - бастами. Непонятно как перевод в полярную систему позволит решить проблему рандомного обращения к памяти. Даже если мы ее переведем (запишем по порядку, так сказать, "лучи" из центра экрана к периферии с разными углами), то сама запись в таком формате - это то же рандомные обращения к памяти. Весь кадр меняется каждые 20 мс. Ну а если картинка статичная - то можно и один раз преобразовать, потратить время на рандомную запись.

 

Хотя натолкнули меня на мысль сделать предвычисления по началам/концам бастов  и маскам при дискретных углах и забивать их в таблицу, которой будет пользоваться "вращалка". 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, alexPec said:

не совсем понял мысль. Картинка с матрицы (с камеры) идет в построчно. В память ее лучше всего ложить тоже построчно - бастами. Непонятно как перевод в полярную систему позволит решить проблему рандомного обращения к памяти. Даже если мы ее переведем (запишем по порядку, так сказать, "лучи" из центра экрана к периферии с разными углами), то сама запись в таком формате - это то же рандомные обращения к памяти. Весь кадр меняется каждые 20 мс. Ну а если картинка статичная - то можно и один раз преобразовать, потратить время на рандомную запись.

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

А раз так - проще их оптимизировать по отдельности, по вычислениям.

 

У меня нет опыта решения в лоб вашей задачи, да ещё под ДМА и БУРСТ.  Здесь уже ваш опыт...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С точки зрения памяти запись наиболее проблемное место.

Посмотрите в описании сколько максимально (размер слова) читается/пишется за один запрос памяти, это будет ширина буфера, далее читайте вниз по памяти до заполнения квадрата и потом обратно в память.

 

P.S. расположение картинки может быть как 1D, линейное, так и 2D. По сути также линейное, но размер по ширине ограничивается размером страйда.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

33 minutes ago, lexx said:

С точки зрения памяти запись наиболее проблемное место.

С чего это вдруг?

 

Вот диаграммы чтения и записи burst'ами по 8 слов типовой DDR3 памяти Micron'а:

Read.jpg

Write.jpg

 

Никаких особых проблем ни на чтении, ни на записи не видно..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...