图像处理(Image Processing) ---------- 对比拉伸 (Contrast Stretching)(C#实现)

版权声明:此为个人学习与研究成果,若需转载请提前告知。 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

猜你喜欢

转载自blog.csdn.net/weixin_35811044/article/details/85255465