Быстрый/эффективный доступ пикселей в Magick ++
-
26-10-2019 - |
Вопрос
В качестве образовательного упражнения для себя я пишу приложение, которое может в среднем с кучей изображений. Это часто используется в астрофотографии, чтобы уменьшить шум.
Библиотека, которую я использую, является 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