在本系列博文中,將介紹幾種常見的圖形處理算法。上文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
}

處理效果如上圖,有點像毛筆手繪的,如果沒有很好的畫家,還真說不定一些古裝電視劇中的人物畫像有可能是用二值法處理的哦。
二值處理法在驗證碼識別中也經常用到,往往先將驗證碼進行二值處理,這樣驗證碼的顏色比較單一,處理起來容易些。
