Question

En tant que excercise éducatif pour moi-même, je vous écris une application qui peut en moyenne un tas d'images. Ceci est souvent utilisé en astrophotographie pour réduire le bruit.

La bibliothèque que je utilise est Magick ++ et je l'ai réussi à écrire en fait la demande. Mais, malheureusement, sa lenteur. Voici le code que je utilise:

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

Les moyennes de code 10 d'images en passant par chaque pixel et en ajoutant l'intensité de pixel de chaque canal en une double vecteur. La fonction avg prend alors le vecteur en tant que paramètre et la moyenne des résultats. Cette moyenne est ensuite utilisée au pixel correspondant stackedImage - qui est l'image résultante. Il fonctionne très bien, mais comme je le disais, je ne suis pas satisfait de la vitesse. Il prend 2 minutes et 30 secondes sur une machine Core i5. Les images sont de 8 mégapixels et 16 bits TIFFs. Je comprends que son beaucoup de données, mais je l'ai vu faire plus rapidement dans d'autres applications.

Est-ce ma boucle lente ou des thats est pixelColor (x, y) d'une façon lente à des pixels d'accès à une image? Y at-il un moyen plus rapide?

Était-ce utile?

La solution

Why use vectors/arrays at all?

Why not

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;

This avoids 36 function calls on vector objects per pixel.

And you may get even better performance by using a PixelCache of the whole image instead of the original Image objects. See the "Low-Level Image Pixel Access" section of the online Magick++ documentation for Image

Then the inner loop becomes

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

Now you have also removed 10 calls to PixelColor, 10 ColorRGB constructors, and 30 accessor functions per pixel.

Note, This is all theory; I haven't tested any of it

Autres conseils

Comments:

  • Why do you use vectors for red, blue and green? Because using push_back can perform reallocations, and bottleneck processing. You could instead allocate just once three arrays of 10 colors.
  • Couldn't you declare rgb outside of the loops in order to relieve stack of unnecessary constructions and destructions?
  • Doesn't Magick++ have a way to average images?

Just in case anyone else wants to average images to reduce noise, and doesn't feel like too much "educational exercise" ;-)

ImageMagick can do averaging of a sequence of images like this:

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

You can also do median filtering and others by changing the word mean in the above command to whatever you want, e.g.:

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

You can get a list of the available operations with:

identify -list evaluate

Output

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top