Как повысить производительность OpenCV на iPhone?

Я использую AVFoundation для захвата видео вместе с OpenCV для обработки изображений на iPhone. Тем не менее, я рассматриваю возможность использования шейдеров OpenGL для выполнения вычислений (свертывания) на изображении в градациях серого 192x144.

Мой вопрос: имеет ли смысл использовать OpenGL, я имею в виду: не слишком ли медленный рендеринг в IplImage (возможно ли это вообще?)? Или есть способ, который ускорит свертывание?

ИЗМЕНИТЬ

В OpenCV я использую

IplConvKernel* kernel = cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_CROSS, NULL);

с cvMorphologyEx.


person user961912    schedule 05.05.2012    source источник
comment
Если ваше ядро ​​свертки симметрично, то вы можете реализовать разделяемую версию (строки-затем-столбцы), которая требует гораздо меньше вычислений, чем наивная версия. Еще во времена мобильных устройств Pentium 3 я мог выполнять свертки в реальном времени на больших изображениях с помощью этого алгоритма (поддержка небольшого ядра). Может быть, вы могли бы уточнить, какую свертка вы делаете?   -  person sansuiso    schedule 06.05.2012
comment
@sansuiso Я только что обновил вопрос.   -  person user961912    schedule 06.05.2012


Ответы (2)


Даже с использованием векторных операций NEON через что-то вроде инфраструктуры Accelerate (которую OpenCV в настоящее время не использует, если я что-то не упускаю), будет сложно превзойти производительность шейдеров при запуске простых ядер свертки 3x3. Например, я могу запустить ядро ​​обнаружения границ Sobel для кадра видео 640x480 за 2,5 мс на iPhone 4 с использованием шейдеров, чего более чем достаточно для обработки изображений в реальном времени. Кроме того, шейдеры OpenGL ES имеют значительные преимущества при обработке для отображения, поскольку вы можете полностью оставить все на стороне графического процессора и избежать дорогостоящей передачи данных для событий рисования.

Если вам нужен простой способ сделать это, мой фреймворк GPUImage с открытым исходным кодом имеет несколько очень быстрых встроенных сверток. , например обнаружение краев Sobel или ядро ​​повышения резкости изображения, и позволяет довольно легко создавать собственные ядра свертки 3x3. Он включает в себя весь OpenGL ES, поэтому вам не нужно ничего об этом знать (если только вы не хотите писать свои собственные эффекты, но даже в этом случае вам просто нужно немного знать GLSL).

Например, чтобы выполнить только компонент X ядра обнаружения границ Sobel, вы можете настроить фильтр свертки с помощью следующего кода:

GPUImage3x3ConvolutionFilter *filter = [[GPUImage3x3ConvolutionFilter alloc] init];
[filter setConvolutionKernel:(GPUMatrix3x3){
    {-1.0f,  0.0f, 1.0f},
    {-2.0f,  0.0f, 2.0f},
    {-1.0f,  0.0f, 1.0f}
 }];

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

person Brad Larson    schedule 07.05.2012
comment
Спасибо за ответ. Я забыл упомянуть, что в OpenCV я в основном сворачиваю оттенки серого 16x16 ROI. Я пробовал вашу структуру, но кажется, что она предполагает, что изображение RGB (я ошибаюсь?). Вопрос: копирование памяти с CPU на GPU (и обратно) не потребляет (понятия не имею)? - person user961912; 07.05.2012
comment
@user961912 user961912 - Вы можете использовать цветные изображения или изображения в градациях серого. Если вы посмотрите на мой фильтр Собеля, я сначала преобразовываю изображение в оттенки серого с помощью фильтра яркости, а затем выполняю фильтрацию в красном канале этого изображения. Вы можете отключить преобразование в градациях серого, если исходное изображение уже имеет градации серого. - person Brad Larson; 07.05.2012
comment
@ user961912 - Что касается вашего вопроса, если вы посмотрите на то, как работает фреймворк, в iOS 5.0 он направляет данные в OpenGL ES напрямую из AV Foundation, что очень быстро. Если вы хотите сохранить данные изображения, я предоставляю прямой доступ к текстурам OpenGL ES на iOS 5.0, что также быстро. В моих резервных версиях iOS 4.0 используется немного более медленный код, но даже в этом случае время загрузки/выгрузки не замедляет весь процесс настолько, чтобы привести его к тому же уровню, что и обработка на ЦП. - person Brad Larson; 07.05.2012
comment
Я понял, что уже использую OpenGL ES для рендеринга (игры). Поскольку я смотрел на источник GPUImage, он также (на удивление) инициализирует OpenGL. Итак, имеет ли смысл (и эффективно) переписывать исходный код и изменять программы OpenGL (я имею в виду с glUseProgam()) каждый кадр (во-первых, для рендеринга сцены, во-вторых, для свертки изображения)? - person user961912; 09.05.2012
comment
@ user961912 - я не знаю, что вы подразумеваете под этим, а также (на удивление) инициализирует OpenGL. Я настроил общий контекст OpenGL ES в фреймворке для выполнения рендеринга, но как еще я мог бы выполнить рендеринг, который я описываю? Если вы хотите отфильтровать результаты рендеринга вашей игры, вам нужно будет рендерить игровую сцену в FBO с текстурной поддержкой. Оттуда вы можете сделать еще один проход со своим собственным шейдером или передать эту текстуру в GPUImage и позволить ему сделать это. См. мой CubeExample в структуре, чтобы узнать, как вы можете выполнять подобную постобработку на сцене OpenGL ES. - person Brad Larson; 09.05.2012
comment
Я рендерю игру и в фоновом режиме и одновременно захватываю видео с помощью AVFoundation и пытаюсь его свернуть, но я не знаю другого способа выполнить оба действия на GPU, кроме как изменением шейдеров (один для игры, другое для свертки) by glUseProgram(). P.S.: Извините за мой плохой английский. - person user961912; 09.05.2012
comment
@user961912 user961912 - Не волнуйтесь, я понимаю большую часть того, о чем вы спрашиваете, поэтому вы достаточно ясно выражаете свои мысли. Я просто не был уверен в этой фразе в вашем комментарии. Опять же, взгляните на мой пример CubeExample, в котором показано, как захватывать видео с камеры, фильтровать его, передавать его в 3D-сцену OpenGL ES, использовать его в качестве текстуры, а затем брать всю сцену и фильтровать ее. Похоже, что первая часть этого примера — это то, что вы хотите сделать здесь, поэтому вы должны иметь возможность опираться на это. - person Brad Larson; 09.05.2012
comment
Спасибо за терпение ко мне :). Я хочу просто обработать захваченное изображение (т. е. я не хочу, чтобы оно отображалось в OpenGL). Я думал, что это можно сделать с помощью потоков, но поскольку это не лучшая идея (взаимоблокировки и т. д. (... да, я знаю о NSOperation)), теперь я не знаю, что лучше - свернуть 16x16 изображение с помощью OpenGL или с оптимизированным кодом NEON+ASM. - person user961912; 09.05.2012

Мне не удалось найти какой-либо соответствующий материал по этому вопросу, поэтому я думаю, что невозможно точно сказать, будет ли реализация, использующая шейдеры этого алгоритма, иметь лучшую производительность с небольшими изображениями, такими как 192x144.

Поскольку это не сложная реализация, если у вас есть время, я рекомендую вам сделать это и измерить прирост производительности обеих реализаций.

Пожалуйста, сообщите нам о своих выводах, если вы решите пойти по этому пути.

person karlphillip    schedule 06.05.2012