2014-01-14 3 views
0

Я хочу знать, есть ли способ сделать операции над двумя изображениями, не анализируя их по пикселям. Я пытаюсь сделать представление смешивания с двух камер в реальном времени. Постарайтесь, чтобы операции выполнялись со скоростью 10 кадров в секунду как минимум.Операции над 2 изображениями (добавление, вычитание и т. Д.) Без использования буфера

Первая версия моей программы выглядит следующим образом:

     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"); 

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

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

+0

Просьба уточнить .. ваше название говорит «без буфера», но в вашем вопросе упоминается «не пиксель за пикселем» .. они не являются взаимоисключающими? Чего вы действительно хотите? Что значит «без буфера»? Как вы ожидаете вычесть одно изображение из другого, не делая этого для каждого пикселя? – stijn

+2

Вы можете попробовать использовать инструкции SSE для выполнения этого по 4 байта за раз. Но реальные вопросы: вы профилировали, чтобы знать, что узкое место в этом конкретном действии? О каком разрешении мы говорим? – RedX

+0

Я добавил часть своего предыдущего кода, чтобы уточнить. Может быть, я могу добавить буфер для всего изображения. Как я могу это сделать? Разрешение моей камеры составляет 1294 пикселя x 964 пикселя. – CherryCola

ответ

3

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

Ваше приложение извлекает 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 имеют разные размеры, то это может привести к аварии.

я настоятельно рекомендую вам взглянуть на следующий пост, чтобы узнать, как задавать лучшие вопросы и получить людей, чтобы помочь вам: Short, Self Contained, Correct (Compilable), Example

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

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

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

+0

OpenCV - это основа для компьютерного зрения, в которой представлены многие методы обработки изображений, в том числе операции, которые вас интересуют. Чтобы ускорить обработку, OpenCV использует несколько технологий выше. Это стоит проверить, так как это с открытым исходным кодом, и вы можете взглянуть на исходный код. ;) – karlphillip

0

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

Выражение

*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); 

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

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

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

  • Используйте компилятор (vc> = 2012, gcc> = 4.7), который поддерживает автоматическую идентификацию и включает его.
  • При компиляции для Windows 32bit «/ арки: 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); 
    } 
}