Ответ 1
Я много работал с Android и оптимизацией (я написал приложение для обработки видео, которое обрабатывает фрейм в 4 мс), поэтому я надеюсь, что дам вам некоторые подходящие ответы.
Между интерфейсом C и C++ в OpenCV нет большой разницы. Часть кода написана на C и имеет обертку C++, а также некоторую прокрутку. Любые существенные различия между ними (как измеряется Shervin Emami) - это либо регрессии, либо исправления ошибок, либо улучшения качества. Вы должны придерживаться последней версии OpenCV.
Почему бы не переписать?
Вы потратите много времени, которое вы могли бы использовать намного лучше. Интерфейс C громоздкий, и вероятность появления ошибок или утечек памяти высока. На мой взгляд, вы должны избегать этого.
Советы по оптимизации
A. Включите оптимизацию.
Оптимизация компилятора и отсутствие утверждений отладки могут существенно повлиять на ваше время работы.
B. Профилируйте свое приложение.
Сделайте это сначала на своем компьютере, так как это намного проще. Используйте визуальный студийный профилировщик, чтобы определить медленные части. Оптимизируйте их. Никогда не оптимизируйте, потому что вы думаете, что это медленно, а потому, что вы его измеряете. Начните с самой медленной функции, оптимизируйте ее как можно больше, а затем возьмите вторую медленнее. Измерьте свои изменения, чтобы убедиться, что они действительно быстрее.
C. Сосредоточьтесь на алгоритмах.
Более быстрый алгоритм может повысить производительность на порядки (100x). Трюк C++ даст вам, возможно, повышение производительности в 2 раза.
Классические методы:
-
Измените размер ваших видеокадров меньше. Часто вы можете извлечь информацию из изображения 200x300px, а не 1024x768. Площадь первого в 10 раз меньше.
-
Используйте более простые операции вместо сложных. Используйте целые числа вместо float. И никогда не используйте
double
в матрице или циклеfor
который выполняется тысячи раз. -
Сделайте как можно меньше вычислений. Вы можете отслеживать объект только в определенной области изображения, а не обрабатывать его для всех фреймов? Можете ли вы сделать грубое/приблизительное обнаружение на очень маленьком изображении, а затем уточнить его на ROI в полном кадре?
D. Используйте C, где это важно
В цикле может быть смысл использовать стиль C вместо C++. Указатель на матрицу данных или массив с плавающей точкой намного быстрее, чем mat.at или std :: vector <>. Часто узким местом является вложенный цикл. Сфокусируйтесь на этом. Не имеет смысла заменять вектор <> по всему месту и спагеттизировать код.
E. Избегайте скрытых расходов
Некоторые функции OpenCV преобразуют данные в двойные, обрабатывают их, а затем конвертируют обратно в формат ввода. Остерегайтесь их, они убивают производительность на мобильных устройствах. Примеры: деформирование, масштабирование, преобразование типов. Кроме того, преобразования цветового пространства, как известно, ленивы. Предпочитает полутоновое сечение, полученное непосредственно из нативного YUV.
F. Использование векторизации
Процессоры ARM реализуют векторизацию с помощью технологии NEON. Научитесь использовать его. Это мощно!
Небольшой пример:
float* a, *b, *c;
// init a and b to 1000001 elements
for(int i=0;i<1000001;i++)
c[i] = a[i]*b[i];
можно переписать следующим образом. Это более многословно, но намного быстрее.
float* a, *b, *c;
// init a and b to 1000001 elements
float32x4_t _a, _b, _c;
int i;
for(i=0;i<1000001;i+=4)
{
a_ = vld1q_f32( &a[i] ); // load 4 floats from a in a NEON register
b_ = vld1q_f32( &b[i] );
c_ = vmulq_f32(a_, b_); // perform 4 float multiplies in parrallel
vst1q_f32( &c[i], c_); // store the four results in c
}
// the vector size is not always multiple of 4 or 8 or 16.
// Process the remaining elements
for(;i<1000001;i++)
c[i] = a[i]*b[i];
Пуристы говорят, что вы должны писать на ассемблере, но для обычного программиста это немного сложно. У меня были хорошие результаты с использованием gcc intrinsics, как в приведенном выше примере.
Еще один способ начать с нуля - сконфигурировать кодированный SSE-оптимизированный код в OpenCV в NEON. SSE является эквивалентом NEON в процессорах Intel, и многие функции OpenCV используют его, как здесь. Это код фильтрации изображений для uchar-матриц (обычный формат изображения). Вы должны слепо преобразовывать инструкции один за другим, но примите это как пример для начала.
Вы можете больше узнать о NEON в этом блоге и следующих сообщениях.
G. Обратите внимание на захват изображения.
Это может быть удивительно медленным на мобильном устройстве. Оптимизация - это специфическое устройство и ОС.