Jea*_*rdi 11 c# image-processing
我想优化这段代码:
public void PopulatePixelValueMatrices(GenericImage image,int Width, int Height)
{
for (int x = 0; x < Width; x++)
{
for (int y = 0; y < Height; y++)
{
Byte pixelValue = image.GetPixel(x, y).B;
this.sumOfPixelValues[x, y] += pixelValue;
this.sumOfPixelValuesSquared[x, y] += pixelValue * pixelValue;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这将用于图像处理,我们目前正在运行约200张图像.我们优化了GetPixel值以使用不安全的代码,我们没有使用image.Width或image.Height,因为这些属性增加了我们的运行时成本.
但是,我们仍然处于低速状态.问题是我们的图像是640x480,所以循环的中间被调用大约640x480x200倍.我想问一下是否有办法以某种方式加速它,或者让我相信它的速度足够快.也许一种方法是通过一些快速的Matrix Addition,或者Matrix Addition固有的n ^ 2操作无法加速它?
也许通过不安全的代码进行数组访问可以加快速度,但是我不知道如何去做,以及它是否值得花时间.可能不是.谢谢.
编辑:谢谢你的所有答案.
这是我们正在使用的GetPixel方法:
public Color GetPixel(int x, int y)
{
int offsetFromOrigin = (y * this.stride) + (x * 3);
unsafe
{
return Color.FromArgb(this.imagePtr[offsetFromOrigin + 2], this.imagePtr[offsetFromOrigin + 1], this.imagePtr[offsetFromOrigin]);
}
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 18
尽管使用不安全的代码,很GetPixel可能是这里的瓶颈.您是否考虑过在一次调用中获取图像中所有像素的方法而不是每个像素一次?例如,Bitmap.LockBits可能是你的朋友......
在我的上网本中,一个非常简单的循环迭代640*480*200只需要大约100毫秒 - 所以如果你发现它一切都很慢,你应该再看一下循环内的位.
您可能需要考虑的另一个优化:避免使用多维数组.它们比单维阵列慢得多.
特别是,您可以拥有一个大小的一维数组,Width * Height并保留一个索引:
int index = 0;
for (int x = 0; x < Width; x++)
{
for (int y = 0; y < Height; y++)
{
Byte pixelValue = image.GetPixel(x, y).B;
this.sumOfPixelValues[index] += pixelValue;
this.sumOfPixelValuesSquared[index] += pixelValue * pixelValue;
index++;
}
}
Run Code Online (Sandbox Code Playgroud)
使用相同的简单测试工具,向2-D矩形阵列添加写入时,总循环时间超过200*640*480,最高可达850ms; 使用一维矩形阵列将其恢复到大约340ms - 所以它有点重要,目前你已经有两个每循环迭代.
阅读这篇文章,其中还有一些代码,并提到了GetPixel的缓慢性.
从文章中可以看出这是简单地反转位的代码.这也显示了LockBits的用法.
请务必注意,不安全的代码不允许您远程运行代码.
public static bool Invert(Bitmap b)
{
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
unsafe
{
byte * p = (byte *)(void *)Scan0;
int nOffset = stride - b.Width*3;
int nWidth = b.Width * 3;
for(int y=0;y < b.Height;++y)
{
for(int x=0; x < nWidth; ++x )
{
p[0] = (byte)(255-p[0]);
++p;
}
p += nOffset;
}
}
b.UnlockBits(bmData);
return true;
Run Code Online (Sandbox Code Playgroud)
}