数字图像处理 使用C#进行图像处理一

为什么用c#进行处理,c#语言相对简单,可以更好的对图像处理算法进行深入理解。进使用c#语言进行图像处理,主要需要了解下面几个类

一、主要用到的类

Bitmap类

详见:https://docs.microsoft.com/zh-cn/dotnet/api/system.drawing.bitmap?view=dotnet-plat-ext-5.0

主要需要关注LockBits、UnlockBits、GetPixel、SetPixel、Clone等方法;Pixelformat的枚举、Lockmode枚举等

BitmapData类

详见:https://docs.microsoft.com/zh-cn/dotnet/api/system.drawing.imaging.bitmapdata?view=dotnet-plat-ext-5.0

主要需要关注Width、Height、PixelFormat、Scan0、Stride等属性

Graphics类

详见:https://docs.microsoft.com/zh-cn/dotnet/api/system.drawing.graphics?view=dotnet-plat-ext-5.0

Graphics类提供用于将对象绘制到显示设备的方法。 Graphics与特定的设备上下文相关联。

二、彩色图像灰度化

最常用的公式:Gray(i,j)=0.299R(i,j)+0.587×G(i,j)+0.114×B(i,j)

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

三、线形点运算

顾名思义,就是对每个点进行套入统一公式的运算,灰度变换函数:g(x, y)=pf(x,y)+L

其中 f(x,y) 为输入图像在点 (x,y) 的灰度值, g(x,y) 为相应的输出点的灰度值。显然,如果P=1和L=0,g(x,y)就是f(x,y)的复制;如果P<1,输出图像的对比度将增大;如果P>1,则对比度将减少;如果P=1而L≠0,该操作仅使所有像素的灰度值上移或下移,其效果是使整个图像在显示时更暗或更亮;如果P为负值,暗区域将变亮,亮区域将变暗,该操作完成了图像求补。

Rectangle rect = new Rectangle(0, 0, curBitmpap.Width, curBitmpap.Height);
System.Drawing.Imaging.BitmapData bmpData = curBitmpap.LockBits(rect,
    System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmpap.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = curBitmpap.Width * curBitmpap.Height;
byte[] grayValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);

int temp = 0;
//得到斜率,自定义的
double a = -1;
//得到偏移量,自定义的
double b = 255);

for (int i = 0; i<bytes; i++)
{
    //根据公式计算线性点运算
    //加0.5表示四舍五入
    temp = (int) (a* grayValues[i] + b + 0.5);

    //灰度值限制在0~255之间
    //大于255,则为255;小于0则为0
    if (temp>255)
    {
        grayValues[i] = 255;
    }
    else if (temp<0)
    {
        grayValues[i] = 0;
    }
    else
    {
    grayValues[i] = (byte)temp;
    }
}
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
curBitmpap.UnlockBits(bmpData);

四、灰度直方图

灰度直方图是灰度的函数,描述的是图像中具有该灰度级的像素的个数。如果用直角坐标系来表示,则它的横坐标是灰度级,纵坐标是该灰度出现的概率(像素的个数)。

计算各个灰度级所具有的像素个数

//图像数据
private System.Drawing.Bitmap bmpHist;
//灰度等级
private int[] countPixel = new int[256];
//记录最大的灰度级个数
private int maxPixel;

private void calchist()
{
    //锁定8位灰度位图
    Rectangle rect = new Rectangle(0, 0, bmpHist.Width, bmpHist.Height);
    System.Drawing.Imaging.BitmapData bmpData = bmpHist.LockBits(rect,
        System.Drawing.Imaging.ImageLockMode.ReadWrite, bmpHist.PixelFormat);
    IntPtr ptr = bmpData.Scan0;
    int bytes = bmpHist.Width * bmpHist.Height;
    byte[] grayValues = new byte[bytes];
    System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);//灰度值数据存入grayValues中

    byte temp = 0;
    maxPixel = 0;
    //灰度等级数组清零
    Array.Clear(countPixel, 0, 256);
    //计算各个灰度级的像素个数
    for (int i = 0; i < bytes; i++)
    {
        //灰度级
        temp = grayValues[i];
        //计数加1
        countPixel[temp]++;
        if (countPixel[temp] > maxPixel)
        {
            //找到灰度频率最大的像素数,用于绘制直方图
            maxPixel = countPixel[temp];
        }
    }

    //解锁
    System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
    bmpHist.UnlockBits(bmpData);
}

绘制直方图

private void histForm_Paint(object sender, PaintEventArgs e)
{
    //获取Graphics对象
    Graphics g = e.Graphics;

    //创建一个宽度为1的黑色钢笔
    Pen curPen = new Pen(Brushes.Black, 1);

    //绘制坐标轴
    g.DrawLine(curPen, 50, 240, 320, 240);//横坐标
    g.DrawLine(curPen, 50, 240, 50, 30);//纵坐标

    //绘制并标识坐标刻度
    g.DrawLine(curPen, 100, 240, 100, 242);
    g.DrawLine(curPen, 150, 240, 150, 242);
    g.DrawLine(curPen, 200, 240, 200, 242);
    g.DrawLine(curPen, 250, 240, 250, 242);
    g.DrawLine(curPen, 300, 240, 300, 242);
    g.DrawString("0", new Font("New Timer", 8), Brushes.Black, new PointF(46, 242));
    g.DrawString("50", new Font("New Timer", 8), Brushes.Black, new PointF(92, 242));
    g.DrawString("100", new Font("New Timer", 8), Brushes.Black, new PointF(139, 242));
    g.DrawString("150", new Font("New Timer", 8), Brushes.Black, new PointF(189, 242));
    g.DrawString("200", new Font("New Timer", 8), Brushes.Black, new PointF(239, 242));
    g.DrawString("250", new Font("New Timer", 8), Brushes.Black, new PointF(289, 242));
    g.DrawLine(curPen, 48, 40, 50, 40);
    g.DrawString("0", new Font("New Timer", 8), Brushes.Black, new PointF(34, 234));
    g.DrawString(maxPixel.ToString(), new Font("New Timer", 8), Brushes.Black, new PointF(18, 34));

    //绘制直方图
    double temp = 0;
    for (int i = 0; i < 256; i++)
    {
        //纵坐标长度
        temp = 200.0 * countPixel[i] / maxPixel;
        g.DrawLine(curPen, 50 + i, 240, 50 + i, 240 - (int)temp);
    }
    //释放对象
    curPen.Dispose();
}

五、直方图灰度拉伸

灰度拉伸,也称对比度拉伸,是一种简单的线性点运算。它扩展图像的直方图,使其充满整个灰度等级范围内。

设f(x,y)为输入图像,它的最小灰度级A和最大灰度级B的定义为:A=min[f(x,y) B=max[f(x,y)]

按照公式   g(x, y)=pf(x,y)+L,  把A和B分别线性映射到0和255,因此,最终的图像g(x,y)为:

private void calchist()
{
    //锁定8位灰度位图
    Rectangle rect = new Rectangle(0, 0, bmpHist.Width, bmpHist.Height);
    System.Drawing.Imaging.BitmapData bmpData = bmpHist.LockBits(rect,
        System.Drawing.Imaging.ImageLockMode.ReadWrite, bmpHist.PixelFormat);
    IntPtr ptr = bmpData.Scan0;
    int bytes = bmpHist.Width * bmpHist.Height;
    byte[] grayValues = new byte[bytes];
    System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);//灰度值数据存入grayValues中

    byte a = 255, b=0;
    double p;
    //计算最大和最小灰度
    for (int i = 0; i < bytes; i++)
    {
        if(a>grayValues[i]) a = grayValues[i];
        if(b>grayValues[i]) b = grayValues[i];
    }
    p = 255.0/(b-a);
    
    //灰度拉伸
    for (int i = 0; i < bytes; i++)
    {
        //加0.5照例是为了四舍五入
        grayValues[i] = (byte)(p*(grayValues[i]-a) + 0.5);
    }

    //解锁
    System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
    bmpHist.UnlockBits(bmpData);
}

猜你喜欢

转载自blog.csdn.net/bashendixie5/article/details/109143895