Операции с 2 изображениями (сложение, вычитание и т. Д.) Без использования буфера

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

Первая версия моей программы выглядит так:

                        CPylonImage im1;
CPylonImage im2;

uint32_t width = im2.GetWidth();
uint32_t height = im2.GetHeight();
uint8_t* buffer1 = static_cast<uint8_t*>( im1.GetBuffer());
uint8_t* p1 = buffer1;
uint8_t* buffer2 = static_cast<uint8_t*>( im2.GetBuffer());
uint8_t* p2 = buffer2;
for (uint32_t y = 0; y < height; ++y)
{
for (uint32_t x = 0; x < width; ++x, ++p1)
{
*p2 = (uint8_t)*p1+*p2;
++p2;
}
}
ShowImage( im2, "Mixed image");

Но это было слишком медленно.

Буду очень признателен за любой ответ.

1

Решение

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

Ваше приложение получает width из одного изображения и тому height с другой. Это редко приводит к хорошим вещам.

    uint32_t width = im1.GetWidth();
uint32_t height = im2.GetHeight();

Хорошо, так buffer1 указывает на im1, а также p1 указывает на buffer1, Я думаю, что вам не нужно p1Просто используйте buffer1 вместо.

    uint8_t* buffer1 = static_cast<uint8_t*>( im1.GetBuffer());
uint8_t* p1 = buffer1;

И сейчас buffer2 а также p2 указывает на im1, Какие?! Не должно ли это быть im2??? Вам не нужно p2,

    uint8_t* buffer2 = static_cast<uint8_t*>( im1.GetBuffer());
uint8_t* p2 = buffer2;for (uint32_t y = 0; y < height; ++y)
{

Следующий цикл увеличивается p, которая является переменной, которая не была объявлена. Я полагаю, вы пытались увеличить p1,

        for (uint32_t x = 0; x < width; ++x, ++p)
{
*p2 = (uint8_t)*p1+*p2;
++p2;
}
}

Сейчас показывать не имеет смысла im2 так как это не было изменено кодом.

    ShowImage( im2, "Mixed image");

Еще одна вещь, если im1 а также im2 имеют разные размеры, это может привести к аварии.

Я настоятельно рекомендую вам взглянуть на следующий пост, чтобы узнать, как лучше задавать вопросы и попросить людей помочь вам: Короткий, Автономный, Правильный (Компилируемый), Пример

Существует несколько технологий, которые могут ускорить обработку этих арифметических операций:

  • Если у вас есть процессор Intel: Intel® Threading Building Blocks (Intel® TBB);
  • Если у вас есть процессор Intel: Intel® Integrated Performance Primitives (Intel® IPP);
  • Если у вас есть графический процессор с поддержкой OpenGL, вы можете написать свой собственный GLSL шейдер;
  • Если у вас есть графический процессор с поддержкой DirectX, вы можете написать свой собственный HLSL шейдер;
  • Если у вас есть графический процессор NVIDIA: CUDA ™;
  • Если у вас есть графический процессор NVIDIA / ATI: OpenCL;
  • Ты можешь попробовать собственный, библиотека шаблонов C ++ для линейной алгебры (выполняет оптимизированные операции над матрицами);
  • OpenMP® (спецификация для набора директив компилятора, подпрограмм библиотеки и переменных среды, которые можно использовать для указания высокоуровневого параллелизма в программах на языках Fortran и C / C ++);
  • Наконец, что не менее важно, вы всегда можете написать свой собственный сборка код для выполнения арифметических операций.
3

Другие решения

Прежде чем начать оптимизацию, убедитесь, что ваш вывод правильный!

Выражение

*p2 = (uint8_t)*p1+*p2;

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

const uint16_t a = *p1;
const uint16_t b = *p2;
const uint16_t sum = a+b;
*p2 = static_cast<uint8_t>( sum > 255 ? 255 : sum );

Еще лучше, добавить результаты и разделить на два, таким образом, вы остаетесь в допустимом диапазоне,
только потерять LSB, и это без ответвления.

*p2 = static_cast<uint8_t>( sum >> 1 );

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

  • Используйте компилятор (vc> = 2012, gcc> = 4.7), который поддерживает автоматическую векторизацию, и включите его.
  • Если вы компилируете для Windows 32bit, используйте «/ arch: SSE2»
  • Дайте подсказки компилятора, используя const а также restrict,
  • если вы уверены, что размер окна всегда одинаков, используйте фиксированную ширину и высоту

например

void add( const CPylonImage& im1, CPylonImage& im2 )
{
const int w = 1294; //im1.width();
const int h = 964; //im1.height();

const uint8_t* restrict buffer1 = static_cast<uint8_t*>( im1.getBuffer() );
uint8_t* restrict buffer2 = static_cast<uint8_t*>( im2.getBuffer() );
for( int i = 0; i < w*h; i++ )
{
const uint16_t a = buffer1[i];
const uint16_t b = buffer2[i];
const uint16_t sum = a+b >> 1;
buffer2[i] = static_cast<uint8_t>( sum );
}
}
0

По вопросам рекламы [email protected]