C#图形处理系列(一)——最简单第一步:逆反处理、二值处理

在本系列博文中,将介绍几种常见的图形处理算法。上文C#图片处理常见方法性能比较 中以彩色转灰色处理为例探讨了3中方法的性能,因此彩色转灰度处理就不再另做介绍。

  public enum DealType
{
黑白处理,
逆反处理,
平滑处理,
霓虹处理,
浮雕处理,
雾化处理,
锐化处理,
二值处理,
马赛克处理,
油画处理
}

DealType枚举定义了常见的图形处理方法。

  /// <summary>
/// 具有图片处理功能的接口
/// </summary>
public interface IImageProcessable

{
void ProcessBitmap(Bitmap bmp);
unsafe void UnsafeProcessBitmap(Bitmap bmp);
}

IImageProcessable接口提供图形处理接口,所有图形处理类都实现了该接口。

ProcessBitmap(Bitmap bmp) 直接提取像素法处理图形,处理效率较低,适合处 理小图片。

UnsafeProcessBitmap(Bitmap bmp)  提供高效率的图形处理方法,以指针或内存拷贝法处理图形,不安全代码。

 

 public class ImageDealFactory
{
public static IImageProcessable CreateDealImage(DealType dealType)
{
IImageProcessable dealImage = null;
switch (dealType)
{
case DealType.黑白处理:
dealImage = new BlackWhiteImage();
break;
case DealType.霓虹处理:
dealImage = new NeonImage();
break;
case DealType.逆反处理:
dealImage = new RebelliousImage();
break;
case DealType.平滑处理:
dealImage = new SmoothImage();
break;
case DealType.浮雕处理:
dealImage = new ReliefImage();
break;
case DealType.雾化处理:
dealImage = new FogImage();
break;
case DealType.锐化处理:
dealImage = new SharpenImage();
break;
case DealType.二值处理:
dealImage = new TwoValueImage ();
break;
case DealType.马赛克处理:
dealImage = new MosaicImage();
break;
case DealType.油画处理:
dealImage = new OilImage();
break;
}
return dealImage;
}
}

ImageDealFactory 图形处理工厂。

先从最简单的图形处理介绍起,最简单的要算逆反处理、灰度处理

、积木二值处理了。

 

逆反处理

逆反处理的原理很简单,用255减去该像素的RGB作为新的RGB值即可。

g(i,j)=255-f(i,j)

  /// <summary>
/// 逆反处理
/// </summary>
public class RebelliousImage : IImageProcessable

{
public void ProcessBitmap(System.Drawing.Bitmap bmp)
{
int width = bmp.Width;
int height = bmp.Height;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
Color c = bmp.GetPixel(i, j);
int r = 255 - c.R;
int g = 255 - c.G;
int b = 255 - c.B;

bmp.SetPixel(i, j, Color.FromArgb(r, g, b));

}
}
}

#region IImageProcessable 成员


public unsafe void UnsafeProcessBitmap(Bitmap bmp)
{
int width = bmp.Width;
int height = bmp.Height;
Rectangle rect = new Rectangle(0, 0, width, height);
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
byte* ptr = (byte*)(bmpData.Scan0);
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
ptr[0] = (byte)(255 - ptr[0]);//B
ptr[1] = (byte)(255 - ptr[1]);//G
ptr[2] = (byte)(255 - ptr[2]);//R
ptr += 4;

}
ptr += bmpData.Stride - width * 4;
}
bmp.UnlockBits(bmpData);
}

#endregion
}

 

 

逆反处理对黑白分量比较多的图片较明显,故截文字图。

 

二值处理

二值处理,顾名思义,将图片处理后就剩下二值了,0、255就是RGB取值的极限值,图片只剩下黑白二色,从上一篇C#图片处理常见方法性能比较 可知,二值处理为图像灰度彩色变黑白灰度处理的一个子集,只不过值就剩下0和255了,因此处理方法有些类似。进行加权或取平均值后进行极端化,若平均值大于等于128则255,否则0.

 /// <summary>
/// 二值处理
/// </summary>
public class TwoValueImage:IImageProcessable

{
#region IImageProcessable 成员

public void ProcessBitmap(System.Drawing.Bitmap bmp)
{
int width = bmp.Width;
int height = bmp.Height;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
Color c = bmp.GetPixel(i, j);
int iAvg = (c.R + c.G + c.B) / 3;
int iPixel = 0;
if (iAvg >= 128)
{
iPixel = 255;

}
else
{
iPixel = 0;
}

bmp.SetPixel(i, j, Color.FromArgb(iPixel, iPixel, iPixel));


}
}
}

public unsafe void UnsafeProcessBitmap(System.Drawing.Bitmap bmp)
{
int width = bmp.Width;
int height = bmp.Height;
Rectangle rect=new Rectangle(0,0,width,height);
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
// byte* ptr =(byte*)bmpData.Scan0;
//for (int i = 0; i < height; i++)
//{
// for (int j = 0; j < width; j++)
// {
// int avg = (int)((ptr[0] + ptr[1] + ptr[2]) / 3);
// if (avg >= 128)
// {
// avg = 255;
// }
// else
// {
// avg = 0;
// }
// ptr[0] = ptr[1] = ptr[2] = (byte)avg;

// ptr += 4;
// }
// ptr += bmpData.Stride - bmpData.Width * 4;
//}

int byteCounts = bmpData.Stride * height;
byte[] arr = new byte[byteCounts];
IntPtr p = bmpData.Scan0;
Marshal.Copy(p, arr, 0, byteCounts);
for (int i = 0; i < byteCounts; i += 4)
{
int avg = (int)((arr[i] + arr[i + 1] + arr[i + 2]) / 3);
if (avg >= 128)
{
avg = 255;
}
else
{
avg = 0;
}
arr[i] = arr[i + 1] = arr[i + 2] = (byte)avg;
}
Marshal.Copy(arr, 0, p, byteCounts);
bmp.UnlockBits(bmpData);
}

#endregion
}

 

处理效果如上图,有点像毛笔手绘的,如果没有很好的画家,还真说不定一些古装电视剧中的人物画像有可能是用二值法处理的哦。

二值处理法在验证码识别中也经常用到,往往先将验证码进行二值处理,这样验证码的颜色比较单一,处理起来容易些。











posted @ 2012-03-04 16:31 霜天雪舞 阅读(...) 评论(...) 编辑 收藏