欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

c#数字图像处理的3种方法示例分享

程序员文章站 2024-02-24 12:45:28
本文主要通过彩色图象灰度化来介绍c#处理数字图像的3种方法,bitmap类、bitmapdata类和graphics类是c#处理图像的的3个重要的类。 bitmap只要用...

本文主要通过彩色图象灰度化来介绍c#处理数字图像的3种方法,bitmap类、bitmapdata类和graphics类是c#处理图像的的3个重要的类。

bitmap只要用于处理由像素数据定义的图像的对象,主要方法和属性如下:

getpixel方法和setpixel方法,获取和设置一个图像的指定像素的颜色。

pixelformat属性,返回图像的像素格式。

palette属性,获取或折纸图像所使用的颜色调色板。

height属性和width属性,返回图像的高度和宽度。

lockbits方法和unlockbits方法,分别锁定和解锁系统内存中的位图像素。

bitmapdata对象指定了位图的属性:

height属性,被锁定位图的高度。

width属性,被锁定位图的宽度。

pixelformat属性,数据的实际像素格式。

scan0属性,被锁定数组的首字节地址。

stride属性,步幅,也称扫描宽度。

彩色图象灰度化

24位彩色图象每个像素用3个字节表示,每个字节对应着r、g、b分量的亮度(红、绿、蓝)。当3个分量不想同时表现为灰度图像。下面有三种转换公式:

gray(i,j)为转换后的灰度图像在(i,j)点出的灰度值。由于人眼对颜色的感应不同,有了下面的转换公式:

观察发现绿色所占比重最大,所以转换时直接使用g值作为转换结果:

图像处理的3种方法分别是:提取像素法、内存法和指针法,它们各自有各自的特点。

提取像素法

使用的是gdi+中的bitmap.getpixel和bitmap.setpixel方法。

复制代码 代码如下:

if (bitmap != null)
{
    newbitmap = bitmap.clone() as bitmap;
    color pixel;
    int ret;
    for (int x = 0; x < newbitmap.width; x++)
    {
        for (int y = 0; y < newbitmap.height; y++)
        {
            pixel = newbitmap.getpixel(x, y);
            ret = (int)(pixel.r * 0.299 + pixel.g * 0.587 + pixel.b * 0.114);
            newbitmap.setpixel(x, y, color.fromargb(ret, ret, ret));
        }
    }
    picturebox1.image = newbitmap.clone() as image;
}

内存法

内存法是把图像数据直接复制到内存中,这样程序的运行速度就能大大提高了。

复制代码 代码如下:

if (bitmap != null)
{
    newbitmap = bitmap.clone() as bitmap;
    rectangle rect = new rectangle(0, 0, newbitmap.width, newbitmap.height);
    system.drawing.imaging.bitmapdata bmpdata = newbitmap.lockbits(rect, system.drawing.imaging.imagelockmode.readwrite, newbitmap.pixelformat);
    intptr ptr = bmpdata.scan0;

    int bytes = newbitmap.width * newbitmap.height * 3;
    byte[] rgbvalues = new byte[bytes];

    system.runtime.interopservices.marshal.copy(ptr, rgbvalues, 0, bytes);

    double colortemp = 0;
    for (int i = 0; i < rgbvalues.length; i += 3)
    {
        colortemp = rgbvalues[i + 2] * 0.299 + rgbvalues[i + 1] * 0.587 + rgbvalues[i] * 0.114;
        rgbvalues[i] = rgbvalues[i + 1] = rgbvalues[i + 2] = (byte)colortemp;
    }

    system.runtime.interopservices.marshal.copy(rgbvalues, 0, ptr, bytes);

    newbitmap.unlockbits(bmpdata);
    picturebox1.image = newbitmap.clone() as image;
}

指针法

这个方法和内存法相似,开始都是通过lockbits方法来获取位图的首地址,这个方法更简洁,直接用指针进行位图操作。所以对内存的操作需要在unsafe下进行操作。

复制代码 代码如下:

if (bitmap != null)
{
    newbitmap = bitmap.clone() as bitmap;
    rectangle rect = new rectangle(0, 0, newbitmap.width, newbitmap.height);
    system.drawing.imaging.bitmapdata bmpdata = newbitmap.lockbits(rect, system.drawing.imaging.imagelockmode.readwrite, newbitmap.pixelformat);
    byte temp;

    unsafe
    {
        byte* ptr = (byte*)(bmpdata.scan0);

        for (int x = 0; x < bmpdata.width; x++)
        {
            for (int y = 0; y < bmpdata.height; y++)
            {
                temp = (byte)(0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0]);
                ptr[0] = ptr[1] = ptr[2] = temp;
                ptr += 3;
            }
            ptr += bmpdata.stride - bmpdata.width * 3;
        }
    }

    newbitmap.unlockbits(bmpdata);
    picturebox1.image = newbitmap.clone() as image;
}