我怎样才能加快这个直方图课程的速度?

这应该计算8位灰度图像的直方图。 使用1024×770测试位图,CreateTime最终在890ms左右。 我怎样才能更快地完成这个(方式,方式)?

编辑:我应该提到,这实际上并没有计算直方图,它只从位图中获取值。 所以我真的应该问,从8位灰度图像中检索所有像素值的最快方法是什么?

public class Histogram { private static int[,] values; public Histogram(Bitmap b) { var sw = Stopwatch.StartNew(); values = new int[b.Width, b.Height]; for (int w = 0; w < b.Width; ++w) { for (int h = 0; h < b.Height; ++h) { values[w, h] = b.GetPixel(w, h).R; } } sw.Stop(); CreateTime = (sw.ElapsedTicks / (double)Stopwatch.Frequency) * 1000; } public double CreateTime { get; set; } } 

基本直方图算法类似于:

 int[] hist = new hist[256]; //at this point dont forget to initialize your vector with 0s. for(int i = 0; i < height; ++i) { for(int j = 0 ; j < widthl ++j) { hist[ image[i,j] ]++; } } 

该算法总结了您拥有的值为0的像素数,具有值= 1的多少像素,依此类推。 基本思想是使用像素值作为您将计算的直方图位置的索引。

我有一个版本的这个算法使用非托管代码为C#编写(这很快)我不知道是否比你更快但随意采取它并测试,这里是代码:

  public void Histogram(double[] histogram, Rectangle roi) { BitmapData data = Util.SetImageToProcess(image, roi); if (image.PixelFormat != PixelFormat.Format8bppIndexed) return; if (histogram.Length < Util.GrayLevels) return; histogram.Initialize(); int width = data.Width; int height = data.Height; int offset = data.Stride - width; unsafe { byte* ptr = (byte*)data.Scan0; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x, ++ptr) histogram[ptr[0]]++; ptr += offset; } } image.UnlockBits(data); } static public BitmapData SetImageToProcess(Bitmap image, Rectangle roi) { if (image != null) return image.LockBits( roi, ImageLockMode.ReadWrite, image.PixelFormat); return null; } 

我希望我能帮助你。

您将需要使用Bitmap.LockBits方法来访问像素数据。 这是该过程的一个很好的参考。 实际上,您将需要使用unsafe代码来迭代位图数据。

这是我基于这个post提出的函数的复制/可管理版本。

不安全的代码期望位图是Format24bppRgb,如果不是,它会将位图转换为该格式并对克隆版本进行操作。

请注意,如果使用索引像素格式(例如Format4bppIndexed)传入位图,则会调用image.Clone()。

需要〜200ms从我的开发机器上的图像9100×2048获取直方图。

  private long[] GetHistogram(Bitmap image) { var histogram = new long[256]; bool imageWasCloned = false; if (image.PixelFormat != PixelFormat.Format24bppRgb) { //the unsafe code expects Format24bppRgb, so convert the image... image = image.Clone(new Rectangle(0, 0, image.Width, image.Height), PixelFormat.Format24bppRgb); imageWasCloned = true; } BitmapData bmd = null; try { bmd = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); const int pixelSize = 3; //pixels are 3 bytes each w/ Format24bppRgb //For info on locking the bitmap bits and finding the //pixels using unsafe code, see http://www.bobpowell.net/lockingbits.htm int height = bmd.Height; int width = bmd.Width; int rowPadding = bmd.Stride - (width * pixelSize); unsafe { byte* pixelPtr = (byte*)bmd.Scan0;//starts on the first row for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { histogram[(pixelPtr[0] + pixelPtr[1] + pixelPtr[2]) / 3]++; pixelPtr += pixelSize;//advance to next pixel in the row } pixelPtr += rowPadding;//advance ptr to the next pixel row by skipping the padding @ the end of each row. } } } finally { if (bmd != null) image.UnlockBits(bmd); if (imageWasCloned) image.Dispose(); } return histogram; }