Pregunta

Como un ejercicio educativo para mí, estoy escribiendo una aplicación que puede promediar un montón de imágenes. Esto a menudo se usa en astrofotografía para reducir el ruido.

La biblioteca que estoy usando es Magick ++ y he logrado escribir la aplicación. Pero, desafortunadamente, es lento. Este es el código que estoy usando:

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

El código promedia 10 imágenes revisando cada píxel y agregando la intensidad de píxeles de cada canal en un doble vector. La función aviso Luego toma el vector como parámetro y promedia el resultado. Este promedio se usa luego en el píxel correspondiente en Trayedimage - cuál es la imagen resultante. Funciona bien, pero como mencioné, no estoy contento con la velocidad. Toma 2 minutos y 30 segundos en una máquina Core i5. Las imágenes son tiffs de 8 megapíxeles y 16 bits. Entiendo que son muchos datos, pero lo he visto más rápido en otras aplicaciones.

¿Es mi bucle lento o es PixelColor (X, Y) ¿Una forma lenta de acceder a los píxeles en una imagen? ¿Hay una manera mas rápida?

¿Fue útil?

Solución

¿Por qué usar vectores/matrices?

Por que no

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;

Esto evita 36 llamadas de función en objetos vectoriales por píxel.

Y puede obtener un rendimiento aún mejor utilizando un PixelCache de toda la imagen en lugar del original Image objetos. Consulte la sección "Acceso de píxel de imagen de bajo nivel" del Magick en línea ++ Documentación para la imagen

Entonces el bucle interno se convierte en

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

Ahora también ha eliminado 10 llamadas a PixelColor, 10 constructores COLORGB y 30 funciones de accesorios por píxel.

Tenga en cuenta que esta es toda la teoría; No he probado nada de eso

Otros consejos

Comentarios:

  • ¿Por qué usas vectores para red, blue y green? Porque usar push_back Puede realizar reasignaciones y procesamiento de cuellos de botella. En su lugar, podría asignar solo una vez tres matrices de 10 colores.
  • ¿No podrías declarar rgb ¿Fuera de los bucles para aliviar la pila de construcciones y destrucciones innecesarias?
  • ¿No tiene magia ++ una forma de promedio de imágenes?

En caso de que alguien más quiera promedio de imágenes para reducir el ruido, y no se siente demasiado "Ejercicio educativo" ;-)

ImageMagick puede hacer un promedio de una secuencia de imágenes como esta:

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

También puede hacer un filtrado mediano y otros cambiando la palabra mean En el comando anterior a lo que quieras, por ejemplo:

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

Puede obtener una lista de las operaciones disponibles con:

identify -list evaluate

Producción

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top