版权声明:此为个人学习与研究成果,若需转载请提前告知。 https://blog.csdn.net/weixin_35811044/article/details/85255465
对比拉伸也就是灰度拉伸,主要是通过改善图像灰度级的动态范围,來改善的图像品质。
如下图:将原灰度集中拉升到均匀提升图像品质。
对比拉伸的本质是使用分段函数进行的线性变换,如下图:输出图像通过牺牲 0 ~ r1 和 r2 ~ L-1 的灰度级,来使s1 ~ s2的灰度级动态范围增加,达到改善图像此区域的的品质。
-
三段线性拉伸的公式:假定要将原图 r1 - r2 的区域拉伸至 s1 - s2 区域。令oldl为原图灰度级,newl为新灰度级。
-
oldl < r1 : newl = oldl / r1 * s1 ;
-
r1 < oldl < r2 : newl = (oldl - r1) / (r2 - r1) * (s2 - s1) + s1 ;
-
oldl > r2 :newl = (oldl - r2) / (255 - r2) * (255 - s2) + s2 ;
-
C#实现:
//灰阶对比拉伸
public Bitmap contrastStreching(Bitmap grayImage, double r1, double r2, double s1, double s2)
{
//用LockBits的方法,效果一致。
//BitmapData grayImageData = grayImage.LockBits(new Rectangle(0, 0, grayImage.Width, grayImage.Height), ImageLockMode.ReadWrite, grayImage.PixelFormat);
//IntPtr intPtr = grayImageData.Scan0;
//int byteSize = grayImageData.Stride * grayImageData.Height;
//byte[] originalBytes = new byte[byteSize];
//Marshal.Copy(intPtr, originalBytes, 0, byteSize);
//double y;
//for (int i = 0; i < originalBytes.Length; i++)
//{
// byte x = originalBytes[i];
// if (x < r1)
// {
// y = (x / r1) * s1;
// }
// else if (x <= r2)
// {
// y = ((x - r1) / (r2 - r1)) * (s2 - s1) + s1;
// }
// else
// {
// y = ((x - r2) / (255 - r2)) * (255 - s2) + s2;
// }
// originalBytes[i] = (byte)Math.Round(y);
//}
//Marshal.Copy(originalBytes, 0, intPtr, byteSize);
//grayImage.UnlockBits(grayImageData);
for (int j = 0; j < grayImage.Height; j++)
{
for (int i = 0; i < grayImage.Width; i++)
{
double y = 0;
byte value = grayImage.GetPixel(i, j).R;
if (value < r1)
{
y = (value / r1) * s1;
}
else if (value <= r2)
{
y = ((value - r1) / (r2 - r1)) * (s2 - s1) + s1;
}
else
{
y = ((value - r2) / (255 - r2)) * (255 - s2) + s2;
}
byte s = (byte)Math.Round(y);
Color newValue = Color.FromArgb(s, s, s);
grayImage.SetPixel(i, j, newValue);
}
}
return grayImage;
}
仅为个人理解,如有不足,请指教。 https://blog.csdn.net/weixin_35811044