C# 图像灰度处理

本文代码来自赵春江编著的《c#数字图像处理算法》

图像灰度化

24位彩色图像每个像素用三个字节表示,每个字节对应着R G B 分量的亮度(红黄蓝)

当R G B 分量值不同时,表现为彩色图像,当三个值相同时,表现为灰度图像

第一种转换公式

Gray(i,j) = [R(i,j) + G(i,j) + B(i,j)]/3

适应人的视觉感应的转换公式

Gray(i,j) = 0.299*R(i,j) + 0.587*G(i,j) + 0.114*B(i,j)

//简单的利用C#位图对象处理图片算法

 private void getPixelBtn_Click(object sender, EventArgs e)
        {
            if (curBitmap != null)
            {
                Color curColor;
                int ret;

                //二维图像数组循环
                for (int i = 0; i < curBitmap.Width; i++)
                {
                    for (int j = 0; j < curBitmap.Height; j++)
                    {
                        //获取该点的像素的RGB的颜色值
                        curColor = curBitmap.GetPixel(i, j);
                        //利用公式计算灰度值
                        ret = (int)(curColor.R * 0.229 + curColor.G * 0.587 + curColor.B * 0.114);
                        //设置该点的灰度值,R = G = B = ret
                        curBitmap.SetPixel(i, j, Color.FromArgb(ret, ret, ret));
                    }
                }

                this.Invalidate();
            }
        }

内存法,将图像数据读入内存,存在数组中,在进行灰度化处理,算法速度明显高于前一种,对于图像

处理的软件,读入内存进行处理,无疑是提高处理速度的优先考虑

private void memoryOperateBtn_Click(object sender, EventArgs e)
        {
            if (curBitmap != null)
            {
                //位图矩形
                Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
                //以可读写的方式锁定全部位图像素,将数据输入到内存
                System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect,
                    System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat);
                //得到首地址
                System.IntPtr ptr = bmpData.Scan0;

                //24位Bmp位图字节数
              //int bytes = curBitmap.Width * curBitmap.Height * 3;
                int bytes = bmpData.Stride * bmpData.Height;
                //定义位图数组
                byte[] rgbValues = new byte[bytes];
                //复制被锁定的位图像素值到该数组内
                System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

                //灰度化
                double colorTemp = 0;
                /*

                //由于图像实际大小,并不一定与其实际所占内存大小相等,因为为了提高效率

                //系统要确定每行字节数必须是4的倍数,因此不是4的倍数的图像,将附加一些未用空间

                          //注释掉的代码只适用于,未有未用空间的图像处理

                for (int i = 0; i < rgbValues.Length; i += 3)
                {
                    //利用公式计算灰度值
                    colorTemp = rgbValues[i + 2] * 0.299 + rgbValues[i + 1] * 0.587 + rgbValues[i] * 0.114;
                    //G = R = B
                    rgbValues[i] = rgbValues[i + 1] = rgbValues[i + 2] = (byte)colorTemp;
                   
                }
                */
                for (int i = 0; i < bmpData.Height; i++)
                {
                    for (int j = 0; j < bmpData.Width * 3; j += 3)
                    {
                        //Stride是每行字节数,每一行像素行数乘以行字节数,保证未用空间略去不被处理
                        colorTemp = rgbValues[i * bmpData.Stride + j + 2] * 0.299 +
                            rgbValues[i * bmpData.Stride + j + 1] * 0.587 +
                            rgbValues[i * bmpData.Stride + j] * 0.114;
                        rgbValues[i * bmpData.Stride + j] = rgbValues[i * bmpData.Stride + j + 1] =
                            rgbValues[i * bmpData.Stride + j + 2] = (byte)colorTemp;
                        

                    }
                }
               
                //把数组复制到位图
                System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);

                //解锁位图像素
                curBitmap.UnlockBits(bmpData);

                //对窗口进行重绘,这将导致强制执行paint事件处理程序
                Invalidate();

            }

 指针法,与内存法类似只是,在处理数据时是利用指针来操作

 private void ptrOperateBtn_Click(object sender, EventArgs e)
        {
            if (curBitmap != null)
            {
                //位图矩形
                Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
                //以读写方式锁定全部位图
                System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect,
                    System.Drawing.Imaging.ImageLockMode.ReadWrite,
                    curBitmap.PixelFormat);
                byte temp = 0;
                //启动不安全模式
                unsafe
                {
                    //得到首地址
                    byte* ptr = (byte*)(bmpData.Scan0);//强制类型转换
                    //二维图像循环
                    for (int i = 0; i < bmpData.Height; i++)
                    {
                        for (int j = 0; j < bmpData.Width; j++)
                        {
                            //利用公式进行灰度值计算
                            temp = (byte)(0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0]);
                            //G = R = B
                            ptr[0] = ptr[1] = ptr[2] = temp;
                            //指向下一个像素
                            ptr += 3;
                        }

                        //指向下一行数组的首个字节
                        ptr += bmpData.Stride - bmpData.Width * 3;
                    }
                }

                //解锁位图像素
                curBitmap.UnlockBits(bmpData);
                //对窗口体进行重绘
                Invalidate();
            }
        }

 

 

你可能感兴趣的:(C# 图像灰度处理)