Magick++中的快速/高效像素访问

4
作为自我教育的一部分,我正在编写一个可以平均一堆图像的应用程序。这在天文摄影中经常用于降噪。
我使用的库是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个图像进行平均。函数avg然后将向量作为参数并计算平均值。这个平均值然后用于stackedImage中相应的像素 - 这是结果图像。它可以正常工作,但是我不满意速度。在Core i5机器上需要2分30秒。这些图像是8兆像素和16位TIFF。我知道这是很多数据,但我已经看到其他应用程序更快地完成了这项工作。
我的循环慢还是pixelColor(x,y)是访问图像中像素的一种缓慢方式?有更快的方法吗?
3个回答

4

为什么要使用向量/数组?

为什么不呢?

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对象,您可能会获得更好的性能。请参阅Image的在线Magick ++文档中的“低级图像像素访问”部分
然后内部循环变为:
PixelPacket* pix = cache[i]+row*columns+column;
red+= pix->red;
blue+= pix->blue;
green+= pix->green;

现在,您还删除了每个像素10次PixelColor调用、10个ColorRGB构造函数和30个存取器函数。
注意,这只是理论;我没有测试过任何内容。

1
是的,那是我最初的做法。但你知道,平均是最简单的叠加方法。人们还可以找到中位数(对于拒绝异常像素[如热像素]非常好)或Sigma Clip。有几种这样的方法,我的目标是实现它们全部。正如你所看到的,像中位数这样的方法需要查看整个数据集,我无法像平均值一样即时计算。因此,我确实需要将其存储在某个地方。 - saad
我刚刚实现了你建议的所有内容(除了即时计算平均值的建议),现在它只需要大约30秒就能完成!谢谢!! - saad
很高兴听到这个消息。我还建议如果你还没有使用PixelCache来写入你的“stackedImage”,那么你应该尝试一下。在那里你也可以得到一些节省。如果你采纳了@Benoit的建议,使用普通数组,请不要忘记可以删除.clear()调用或等价物,因为你知道你将在内部循环中覆盖旧项。 - AShelly

1

评论:

  • 为什么要使用向量来存储redbluegreen?因为使用push_back会导致重新分配内存,从而影响性能。你可以只分配三个长度为10的数组。
  • 你可以在循环外声明rgb,以减轻栈的不必要的构造和销毁。
  • Magick++有没有一种方法来对图像进行平均处理?

感谢您的回复。您对前两个因素的看法是正确的,我已经在我的代码中进行了更改。关于第三个因素,正如我所提到的,我正在将其作为教育练习来完成。其次,我打算实现进一步的堆叠方法,例如中位数和Sigma Clipping等 - 我怀疑Magick ++是否支持。 - saad

0

如果有人想要平均图像以减少噪点,但不想进行太多的"教育性练习",可以参考以下方法:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接