我需要进行直方图拉伸

我有一个BitmapFrames数组,需要进行直方图拉伸。 我知道这与直方图均衡化不同,最终结果是什么…… sorta。 问题是我得到直方图后完全不知道该怎么做。

到目前为止,我的代码为直方图创建了一个数组,所以我知道每个值有多少个像素。 但在那之后我不知道该怎么办。

这是我到目前为止的代码…现在它使直方图然后直方图均衡…这不是我想要的…我只是想了解更多直方图

[Cmdlet(VerbsData.ConvertTo, "HistoStretch")] public class HistoStretchCmdlet : PSCmdlet { private BitmapFrame[] bFrame, outFrame; private BitmapSource src; private double pixelsize; private byte[] pixels, outPixels; private byte MAX_VAL; private int[] histogram; private int cf, start; [Parameter(ValueFromPipeline = true, ValueFromPipelineByPropertyName = true), ValidateNotNullOrEmpty] public BitmapFrame[] Bitmap { get { return bFrame; } set { bFrame = value; } } protected override void ProcessRecord() { base.ProcessRecord(); Console.Write("Applying a histogram stretch to the image...\n\n"); outFrame = new BitmapFrame[bFrame.Length]; for (int c = 0; c < bFrame.Length; c++) { MAX_VAL = (byte)((1 << bFrame[c].Format.BitsPerPixel) - 1); histogram = new int[MAX_VAL + 1]; for (int i = 0; i <= MAX_VAL; i++) { histogram[i] = 0; } pixelsize = bFrame[c].PixelWidth * bFrame[c].PixelHeight; pixels = new byte[(int)pixelsize]; outPixels = new byte[(int)pixelsize]; bFrame[c].CopyPixels(pixels,(int)bFrame[c].Width * (bFrame[c].Format.BitsPerPixel / 8),0); for (int i = 0; i < pixelsize; i++) { histogram[(int)pixels[i]] = histogram[(int)pixels[i]] + 1; } for (int i = 0; i <= MAX_VAL; i++) { Console.Write("{0}: {1}\n", i, histogram[i]); } for (int i = 0; i = 1) { start = i; break; } } for (int i = 0; i < pixelsize; i++) { cf = 0; for (int g = 0; g <= MAX_VAL; g++) { cf += histogram[g]; if (g == pixels[i]) { break; } } outPixels[i] = (byte)(cf * (MAX_VAL / pixelsize)); } src = BitmapSource.Create(bFrame[c].PixelWidth, bFrame[c].PixelHeight, bFrame[c].DpiX, bFrame[c].DpiY, bFrame[c].Format, bFrame[c].Palette, outPixels, (int)(bFrame[c].Width * (bFrame[c].Format.BitsPerPixel / 8))); outFrame[c] = BitmapFrame.Create(src); } WriteObject(outFrame); } } 

根据老师的说法,这就是直方图的样子:

http://sofzh.miximages.com/c%23/

我运行上面的代码……并获得了一个直的黑色图像。 这是我的代码:

 outFrame = new BitmapFrame[bFrame.Length]; for (int c = 0; c < bFrame.Length; c++) { MAX_VAL = (byte)((1 << bFrame[c].Format.BitsPerPixel) - 1); histogram = new int[MAX_VAL + 1]; for (int i = 0; i <= MAX_VAL; i++) { histogram[i] = 0; } pixelsize = bFrame[c].PixelWidth * bFrame[c].PixelHeight; pixels = new byte[(int)pixelsize]; outPixels = new byte[(int)pixelsize]; bFrame[c].CopyPixels(pixels,(int)bFrame[c].Width * (bFrame[c].Format.BitsPerPixel / 8),0); max = pixels[0]; min = pixels[0]; for (int i = 0; i  max) max = pixels[i]; if((int)pixels[i] < min) min = pixels[i]; } dynamic = max - min; for (int i = 0; i < pixelsize; i++) { outPixels[i] = (byte)(((pixels[i] - min) / dynamic) * MAX_VAL); } 

直方图拉伸是像素值的映射 ,例如:

  • 最低值(例如图中的84)变为0
  • 最高值(例如图中的153)变为255(8位图像中)
  • 并且所有中间值都在该范围之间进行插值(参见图示)。

换句话说,直方图拉伸意味着将图像数据的动态(84:153)拉伸到最大可能的动态(0:255)。

这不应该影响直方图峰值的高度,而只影响它们的扩散(图示在这一点上有点误导)。

直方图拉伸http://sofzh.miximages.com/c%23/linstre.gif

图像来源

在实践中,这是您将应用于图像像素的映射(伪代码):

 maxVal = image.maximumValue() # 153 minVal = image.minumumValue() # 84 dynamic = maxVal-minVal for pixel in image.Pixels(): newPixel = ((pixel-minVal)/dynamic)*255 

如果您可以控制相机的光照和/或增益/偏移,您可以根据需要对其进行优化并拉伸直方图。

别忘了考虑漂浮。 所以对dabonz413的回答略有修改:

 maxVal = image.maximumValue() # 153 minVal = image.minumumValue() # 84 dynamic = maxVal-minVal for pixel in image.Pixels(): newPixel = ((float) (pixel-minVal)/dynamic)*255