C#数字图像处理的3种方法

   本文主要通过彩色图象灰度化来介绍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方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
}

  内存法

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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下进行操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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;
}

  3种方法的比较

  比较一下可以得出结论,提取像素法比较简单,但是效率比较低;内存法效率有了很大的提高,但是代码比较复杂;指针法效率比内存法更高一些,但是不安全。综上比较结果内存法比较好,效率即高又能发挥C#安全的优点。

时间: 2024-12-21 21:09:45

C#数字图像处理的3种方法的相关文章

android中查看项目数字证书的两种方法

  方法一:在Eclipse中选择winows -> preferance -> android -> build 方法二:通过在命令行中输入以下命令进行查看: keytool -list -v -alias Ada168855 -keystore D:EclipseWorkspace3GpsTestGpsTest.keystore 方法二如下图所示:

C#数字图像处理的方法

本文主要通过彩色图象灰度化来介绍C#处理数字图像的3种方法,Bitmap类.BitmapData类和 Graphics类是C#处理图像的的3个重要的类. Bitmap只要用于处理由像素数据定义的图像的对象,主要方法和属性如下: GetPixel方法和SetPixel方法,获取和设置一个图像的指定像素的颜色. PixelFormat属性,返回图像的像素格式. Palette属性,获取或折纸图像所使用的颜色调色板. Height属性和Width属性,返回图像的高度和宽度. LockBits方法和Un

excel将文本转换为数字的四种方法

  excel将文本转换为数字的四种方法          方法一,利用函数查错工具,如果数字是文本格式的,在左上角会有一个小三角的东西,点击单元格,选中有个惊叹号样子的小方格,选择"转换为数字"完成批量转换 方法二,四则运算,就是将文本型数字进行加减乘除的运算,比如对C2进行转换,就写公式=C2*1,就可以将文本转成数值了 方法三,进行"减负运算",它其实也就是四则运算,只是写法有些不一样,比如对C2进行转换,就写公式=--C2,通过计算,就可以将文本型数字转换成

JS实现的4种数字千位符格式化方法分享

 这篇文章主要介绍了JS实现的4种数字千位符格式化方法分享,本文给出了4种千分位格式化方法并对它们的性能做了比较,需要的朋友可以参考下     所谓的数字千分位形式,即从个位数起,每三位之间加一个逗号.例如"10,000".针对这个需求,我起初写了这样一个函数: 代码如下: // 方法一 function toThousands(num) { var result = [ ], counter = 0; num = (num || 0).toString().split(''); fo

PHP数字字符串左侧补0、字符串填充和自动补齐的几种方法_php实例

一.数字补0. 如果要自动生成学号,自动生成某某编号,就像这样的形式"d0000009"."d0000027"时,那么就会面临一个问题,怎么把左边用0补齐成这样8位数的编码呢?我想到了两种方法实现这个功能. 方法一: 先构造一个数字10000000,千万,也就是一个1,7个0,然后加上当前的编号(比如是3),那么就得到 10000003,用字符串截取 substr('10000003',1,7)后就得到0000003,最后在与"d"拼接,就得到了

SHELL判断一个字串是否为数字的几种方法

PS:  shell结合C应该是可以写出非常强大的脚本的!加油~~~ Shell中经常需要判断一个参数的类型,用来决定是否将该参数传给后续代码执行. 这里简单介绍两种判断一个字符串是否为数字的方法:   1.使用Linux下相当牛X的计算器bc,当然这里有点大材小用了,不过也不失为一种方法 echo $str | bc 将字串打印出来,通过管道传给计算器bc这个程序,这个程序的基本功能是计算表达式的值,但是特别的是 在输入单个数字,它返回的值仍然是这个数字(单个数字是特殊的表达式),根据这个特性

JS实现至少包含字母、大小写数字、字符的密码等级的两种方法_javascript技巧

本文实例讲述了JS实现至少包含字母.大小写数字.字符的密码等级的两种方法.分享给大家供大家参考.具体如下: 前言 密码,如果设置的太简单,很容易就被攻破,所以很多网站将密码设置的要求设置的挺严格,一般是字母.数字.字符3选2,区分大小写.对于设置得太简单的密码,予以错误提示.或者予以密码等级(低中高)显示,让用户设置高级密码.那如何利用JS实现呢? 实现代码如下: function passwordLevel(password) { var Modes = 0; for (i = 0; i <

基于Hadoop的遥感数字图像处理方法研究

基于Hadoop的遥感数字图像处理方法研究 东北师范大学   周涛 本文基于Hadoop云计算系统,主要利用并行编程框架MapReduce实现遥感数字图像的增强处理以及对增强后图像进行聚类,并与PC串行处理进行比较研究.针对遥感数字图像的整体亮度偏低.目视效果较差的特点,传统的图像增强方法在遥感数字图像上的处理无法达到人眼舒适的目视判读的效果,以及影响后续处理的问题,本文在无损增强方法的基础上进行了改进,使得原始图像的有效图像区域的无效像素点能够参与增强,实验结果表明该方法达到了很好的目视效果.

JS实现的4种数字千位符格式化方法分享_javascript技巧

所谓的数字千分位形式,即从个位数起,每三位之间加一个逗号.例如"10,000".针对这个需求,我起初写了这样一个函数: 复制代码 代码如下: // 方法一 function toThousands(num) {     var result = [ ], counter = 0;     num = (num || 0).toString().split('');     for (var i = num.length - 1; i >= 0; i--) {         co