AS3: Как эффективно получить доступ к пиксельным данным?

Я работаю над игрой.

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

Я изучил Pixel Bender, но это кажется полезным только для добавления новых цветов к изображению. На данный момент, даже при низком разрешении (200x200) всего один объект, сканирующий изображение, замедляется до 1-2 кадров/сек.

Я встраиваю изображение и использую его как растровое изображение в качестве дочернего элемента сцены. Ситуация 1-2 FPS использует BitmapData.getPixel() (на каждый пиксель) с предварительным расчетом расстояния.

Мне интересно, есть ли способ сделать это более эффективно... Моей первой мыслью было какое-то пространственное разделение в сочетании с разделением изображения на множество более мелких частей.

Я также чувствую, что Pixel Bender должен как-то помочь, однако у меня мало опыта в этом.

Спасибо за любую помощь. Джонатан


person Jono    schedule 03.06.2010    source источник


Ответы (3)


Назовем пиксели, к которым объекты направляются, «аттракторами», потому что они притягивают объекты.

Вы описываете низкую частоту кадров из-за сканирования аттракторов. Это указывает на то, что вы, возможно, сканируете изображение в каждом кадре. Вы не указываете, является ли отсканированное изображение статичным или изменяется так же часто, как, например, видеовход. Если изображение меняется с каждым кадром, так что вам нужно каким-то образом пересчитывать аттракторы, то вы пытаетесь использовать компьютерное зрение в реальном времени с помощью виртуальной машины ABC, см. ниже.

Если у вас есть неизменное изображение, то самая важная оптимизация, которую вы можете сделать, — это отсканировать изображение только один раз, а затем сохранить сводку (или «запоминание») местоположений аттракторов. В каждом кадре рендеринга вместо сканирования всего изображения можно выполнять поиск в списке или массиве известных аттракторов. Когда пользователь вызывает изменение изображения, вы можете пересчитать его с нуля или постепенно обновлять свои расчеты — по своему усмотрению.

Если вы пытаетесь реализовать компьютерное зрение в реальном времени с помощью ActionScript 3, я предлагаю вам взглянуть на новые vector типы Flash 10.1, а также изучить возможность использования abcsx для написания ассемблерного кода ABC или используйте Adobe's Alchemy для компиляции C в среду выполнения Flash. ABC — это байт-код Flash. Другими словами, пересмотрите использование AS3 для компьютерного зрения в реальном времени.

person Heath Hunnicutt    schedule 03.06.2010

BitmapData имеет метод getPixels (обратите внимание на множественное число). Он возвращает массив байтов всех пикселей , который может выполняться намного быстрее, чем цикл for с вызовом getPixel внутри, вложенным в другой цикл for. К сожалению, bytearrays, как следует из их названия, представляют собой одномерные массивы байтов, поэтому итерация каждого пикселя (4 байта) требует использования цикла for, а не цикла foreach. По умолчанию вы можете получить доступ к цветовому каналу каждого пикселя отдельно, но это похоже на то, что вы хотите (найти пиксели с «высоким красным каналом»), поэтому вам не нужно побитовое и каждое значение пикселя изолировать конкретный канал.

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

person Ponkadoodle    schedule 03.06.2010
comment
Извините, но это явно неправильно. Количество итераций одинаково в обоих случаях, если вы пытаетесь оценить каждый пиксель. Вложенные циклы или нет, не меняет этого факта. Помещение пикселей в ByteArray ничего не даст вам в этом сценарии. На самом деле все еще хуже: вы будете использовать (как минимум) в два раза больше памяти; вы избежите вызова getPixel(), но в конечном итоге вызовете readUnsignedInt() одинаковое количество раз; если вам нужно знать координаты пикселей (весьма вероятно), вы в конечном итоге добавите счетчики для x и y или используете модуль. Во всяком случае, здесь нет никакой выгоды. - person Juan Pablo Califano; 03.06.2010
comment
Использование getPixels() определенно предпочтительнее, чем getPixel(). Накладные расходы на любой вызов метода во Flash огромны, и, поскольку вы можете обращаться к ByteArray как к массивам, также известным как myPixels[index], вы сэкономите себе накладные расходы на вызов метода для каждого пикселя. Также flash выполняет внутреннюю проверку границ для getPixel(), что является еще одним замедлением. - person Quasimondo; 23.06.2010
comment
@Квазимондо. Вы лучше меня разбираетесь в манипулировании изображениями (я слежу за вашим блогом!). Тем не менее, я не уверен, что getPixels лучше, чем getPixels в данных обстоятельствах (т.е. если вы хотите что-то сделать с каждым пикселем). Вызов функции, безусловно, имеет накладные расходы, но Николя Канассе из IIRC продемонстрировал, что доступ к массиву также довольно медленный (не уверен, что это изменилось в новейших проигрывателях). - person Juan Pablo Califano; 22.07.2010
comment
(продолжение) Что касается проверки границ, насколько я понимаю, и Array, и ByteArray проверяются в Actionscript. Наконец, небольшое быстрое тестирование (хотя оно и не могло быть хорошим/репрезентативным тестом) показало незначительную разницу между этими двумя методами (опять же, при обстоятельствах, указанных выше). - person Juan Pablo Califano; 22.07.2010
comment
Когда вы получаете доступ к ByteArray с синтаксисом скобок, он не проверяется, поэтому, когда вы делаете byteArray[ x * 4 + y * width] и используете x или y вне прямоугольника растрового изображения, вы можете столкнуться с ошибкой (или прочитать другой пиксель чем тот, который вы ожидаете из-за обертывания) - person Quasimondo; 22.07.2010

Я бы сказал, что ответ Хита Ханникатта хороший. Если изображение не меняется, просто сохраните все значения цвета в векторе. или byteArray чего угодно и использовать его в качестве таблицы поиска, поэтому вам не нужно вызывать getPixel() каждый кадр.

person dotminic    schedule 15.07.2010