[C#] 濾鏡筆記 – 銳利化
2012-12-05
銳利化開始有點複雜要導入矩陣的觀念,因為他跟之前模糊化一樣
必須和周圍的點一起套入公式進行處理
可以參考這篇:
http://stackoverflow.com/questions/903632/sharpen-on-a-bitmap-using-c-sharp
http://blog.csdn.net/jiangxinyu/article/details/6222322
關於拉普拉絲的矩陣是長這樣
// 建立3x3 矩陣 拉普拉斯
// -1 -1 -1 (0,0) | (1,0) | (2,0)
// -1 +9 -1 (0,1) | (1,1) | (2,1)
// -1 +1 -1 (0,2) | (1,2) | (2,2)
public static Bitmap AdjustLaplaceSharpen(Bitmap src)
{
// 建立3x3 矩陣 拉普拉斯
// -1 -1 -1 (0,0) | (1,0) | (2,0)
// -1 +9 -1 (0,1) | (1,1) | (2,1)
// -1 +1 -1 (0,2) | (1,2) | (2,2)
double[,] filter = new double[3, 3];
filter[0, 0] = filter[0, 1] = filter[0, 2] = filter[1, 0] = filter[1, 2] = filter[2, 0] = filter[2, 1] = filter[2, 2] = -1;
filter[1, 1] = 9;
//矩陣總和
var factor = filter[0, 0] + filter[0, 1] + filter[0, 2] + filter[1, 0] + filter[1, 1] + filter[1, 2] + filter[2, 0] + filter[2, 1] + filter[2, 2];
Bitmap bSrc = (Bitmap)src.Clone();
// 依照 Format24bppRgb 每三個表示一 Pixel 0: 藍 1: 綠 2: 紅
BitmapData bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
// Clone 一份出來做參考值
BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
System.IntPtr Scan0 = bitmapData.Scan0;
System.IntPtr SrcScan0 = bmSrc.Scan0;
unsafe
{
byte* p = (byte*)(void*)Scan0;
byte* pSrc = (byte*)(void*)SrcScan0;
int nOffset = bitmapData.Stride + 6 - src.Width * 3;
int nWidth = src.Width - 2;
int nHeight = src.Height - 2;
int nPixel;
for (int y = 0; y < nHeight; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
nPixel = (int)((((pSrc[2] * filter[0, 0]) + (pSrc[5] * filter[0, 1]) + (pSrc[8] * filter[0, 2]) +
(pSrc[2 + bitmapData.Stride] * filter[1, 0]) + (pSrc[5 + bitmapData.Stride] * filter[1, 1]) + (pSrc[8 + bitmapData.Stride] * filter[1, 2]) +
(pSrc[2 + bitmapData.Stride * 2] * filter[2, 0]) + (pSrc[5 + bitmapData.Stride * 2] * filter[2, 1]) + (pSrc[8 + bitmapData.Stride * 2] * filter[2, 2])) / factor) );
nPixel = Math.Min(Math.Max(nPixel, 0), 255);
p[5 + bitmapData.Stride] = (byte)nPixel;
nPixel = (int)((((pSrc[1] * filter[0, 0]) + (pSrc[4] * filter[0, 1]) + (pSrc[7] * filter[0, 2]) +
(pSrc[1 + bitmapData.Stride] * filter[1, 0]) + (pSrc[4 + bitmapData.Stride] * filter[1, 1]) + (pSrc[7 + bitmapData.Stride] * filter[1, 2]) +
(pSrc[1 + bitmapData.Stride * 2] * filter[2, 0]) + (pSrc[4 + bitmapData.Stride * 2] * filter[2, 1]) + (pSrc[7 + bitmapData.Stride * 2] * filter[2, 2])) / factor));
nPixel = Math.Min(Math.Max(nPixel, 0), 255);
p[4 + bitmapData.Stride] = (byte)nPixel;
nPixel =(int) ((((pSrc[0] * filter[0, 0]) + (pSrc[3] * filter[0, 1]) + (pSrc[6] * filter[0, 2]) +
(pSrc[0 + bitmapData.Stride] * filter[1, 0]) + (pSrc[3 + bitmapData.Stride] * filter[1, 1]) + (pSrc[6 + bitmapData.Stride] * filter[1, 2]) +
(pSrc[0 + bitmapData.Stride * 2] * filter[2, 0]) + (pSrc[3 + bitmapData.Stride * 2] * filter[2, 1]) + (pSrc[6 + bitmapData.Stride * 2] * filter[2, 2])) / factor));
nPixel = Math.Min(Math.Max(nPixel, 0), 255);
p[3 + bitmapData.Stride] = (byte)nPixel;
p += 3;
pSrc += 3;
}
p += nOffset;
pSrc += nOffset;
}
}
src.UnlockBits(bitmapData);
bSrc.UnlockBits(bmSrc);
return src;
}
中間你會覺得很複雜 其實他就是 先拷貝一份 bmpSrc 出來 然後進行參考後 套入矩陣公式 (九宮格點色值*權重)總和平均
所以會有比較複雜的加減值 之後你會發現 透過矩陣方式去做運算 其實後面有很多濾鏡跟模板都是用這方式套用很方便..
結果: