欢迎来到山村网

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

2019-03-02 11:15:17浏览:85 来源:山村网   
核心摘要:  本文主要通过彩色图象灰度化来介绍C#处理数字图像的3种方法,Bitmap类、BitmapData类和Graphics类是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个分量不想同时表现为灰度图像。下面有三种转换公式:

C#数字图像处理的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() asBitmap;
Color pixel;
intret;
for(intx = 0; x < newbitmap.Width; x++)
{
for(inty = 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() asImage;
}

  内存法

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

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() asBitmap;
Rectangle rect = newRectangle(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;
intbytes = newbitmap.Width * newbitmap.Height * 3;
byte[] rgbvalues = newbyte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbvalues, 0, bytes);
doublecolortemp = 0;
for(inti = 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() asImage;
}

  指针法

  这个方法和内存法相似,开始都是通过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() asBitmap;
Rectangle rect = newRectangle(0, 0, newbitmap.Width, newbitmap.Height);
System.Drawing.Imaging.BitmapData bmpdata = newbitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, newbitmap.PixelFormat);
bytetemp;
unsafe
{
byte* ptr = (byte*)(bmpdata.Scan0);
for(intx = 0; x < bmpdata.Width; x++)
{
for(inty = 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() asImage;
}

  3种方法的比较

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

(责任编辑:豆豆)
下一篇:

flex chrome浏览器调试出现空白的解决方法

上一篇:

C#编程中怎么对文件目录进行实时监控

  • 信息二维码

    手机看新闻

  • 分享到
打赏
免责声明
• 
本文仅代表作者个人观点,本站未对其内容进行核实,请读者仅做参考,如若文中涉及有违公德、触犯法律的内容,一经发现,立即删除,作者需自行承担相应责任。涉及到版权或其他问题,请及时联系我们 xfptx@outlook.com