Быстрый / эффективный пиксельный доступ в Magick ++ - PullRequest
4 голосов
/ 16 марта 2011

В качестве учебного упражнения для себя я пишу приложение, которое может усреднять кучу изображений.Это часто используется в астрофотографии для уменьшения шума.

Я использую библиотеку Magick ++, и мне действительно удалось написать приложение.Но, к сожалению, это медленно.Вот код, который я использую:

for(row=0;row<rows;row++)
{
    for(column=0;column<columns;column++)
    {
        red.clear(); blue.clear(); green.clear();
        for(i=1;i<10;i++)
        {
            ColorRGB rgb(image[i].pixelColor(column,row));
            red.push_back(rgb.red());
            green.push_back(rgb.green());
            blue.push_back(rgb.blue());
        }
        redVal = avg(red);
        greenVal = avg(green);
        blueVal = avg(blue);
        redVal = redVal*MaxRGB; greenVal = greenVal*MaxRGB; blueVal = blueVal*MaxRGB;
        Color newRGB(redVal,greenVal,blueVal);
        stackedImage.pixelColor(column,row,newRGB);
    }
}

Код усредняет 10 изображений, проходя каждый пиксель и добавляя интенсивность пикселей каждого канала в вектор double .Затем функция avg принимает вектор в качестве параметра и усредняет результат.Это среднее затем используется в соответствующем пикселе в stackedImage - который является результирующим изображением.Работает просто отлично, но как я уже говорил, меня не устраивает скорость.Это занимает 2 минуты и 30 секунд на компьютере с Core i5.Изображения 8-мегапиксельные и 16-битные TIFF.Я понимаю, что это много данных, но я видел, что это делается быстрее в других приложениях.

Это мой цикл, который работает медленно или pixelColor (x, y) медленный способполучить доступ к пикселям на изображении?Есть ли более быстрый способ?

Ответы [ 3 ]

4 голосов
/ 16 марта 2011

Зачем вообще использовать векторы / массивы?

Почему бы не

double red=0.0, blue=0.0, green=0.0;
for(i=1;i<10;i++)
{
   ColorRGB rgb(image[i].pixelColor(column,row));
   red+=rgb.red();
   blue+=rgb.blue();
   green+=rgb.green();
}
red/=10;
blue/=10;
green/=10;

Это позволяет избежать 36 вызовов функций для векторных объектов на пиксель.

И вы можете получить дажелучшая производительность благодаря использованию PixelCache всего изображения вместо исходных Image объектов.См. Раздел «Низкоуровневый доступ к пикселям изображения» в онлайн-документации Magick ++ для Image

Тогда внутренний цикл станет

PixelPacket* pix = cache[i]+row*columns+column;
red+= pix->red;
blue+= pix->blue;
green+= pix->green;

Теперь вы также удалиливызов PixelColor, 10 конструкторов ColorRGB и 30 функций доступа на пиксель.

Примечание. Это все теория;Я не проверял ничего из этого

1 голос
/ 16 марта 2011

Комментарии:

  • Почему вы используете векторы для red, blue и green? Потому что с помощью push_back можно выполнять перераспределения и обработку узких мест. Вместо этого вы можете выделить только три массива из 10 цветов.
  • Не могли бы вы объявить rgb вне циклов, чтобы освободить стек от ненужных конструкций и разрушений?
  • Разве у Magick ++ нет способа усреднять изображения?
0 голосов
/ 03 июня 2016

На всякий случай, если кто-то еще хочет усреднить изображения, чтобы уменьшить шум, и не испытывает особого желания "учебное упражнение" ; -)

ImageMagick может выполнить усреднение последовательностиизображений, подобных этому:

convert image1.tif image2.tif ... image32.tif -evaluate-sequence mean result.tif

Вы также можете выполнить медианную фильтрацию и другие, изменив слово mean в приведенной выше команде на любое другое, например:

convert image1.tif image2.tif ... image32.tif -evaluate-sequence median result.tif

Youможно получить список доступных операций с:

identify -list evaluate

Вывод

Abs
Add
AddModulus
And
Cos
Cosine
Divide
Exp
Exponential
GaussianNoise
ImpulseNoise
LaplacianNoise
LeftShift
Log
Max
Mean
Median
Min
MultiplicativeNoise
Multiply
Or
PoissonNoise
Pow
RightShift
RMS
RootMeanSquare
Set
Sin
Sine
Subtract
Sum
Threshold
ThresholdBlack
ThresholdWhite
UniformNoise
Xor
...