Вопрос

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

Библиотека, которую я использую, является 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 изображений, проходя через каждый пиксель и добавляя интенсивность пикселей каждого канала в двойной вектор. Функция ав Затем принимает вектор в качестве параметра и усредняет результат. Это среднее затем используется в соответствующем пикселе в Stackedimage - которое является результирующим изображением. Это работает просто отлично, но, как я уже упоминал, я не доволен скоростью. Это занимает 2 минуты и 30 секунд на машине Core i5. Изображения 8 мегапиксель и 16 -битные Tiffs. Я понимаю, что это много данных, но я видел, как это делалось быстрее в других приложениях.

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

Это было полезно?

Решение

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

Почему бы и нет

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 объекты. См. Раздел «Pixel Pixel Pixel» на низком уровне онлайн -магика ++ документация для изображения

Тогда внутренняя петля становится

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

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

Обратите внимание, это все теория; Я ничего не проверил из этого

Другие советы

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

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

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

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

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

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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top