[C#/WINFORM] Bitmap 클래스 : 가우스 3X3 라플라시안 3X3 가장자리 탐지 필터(Laplacian 3X3 Of Gaussian 3X3 Edge Detection Filter) 사용하기
C#/WinForm 2021. 1. 11. 20:25728x90
728x170
▶ Matrix.cs
namespace TestProject
{
/// <summary>
/// 매트릭스
/// </summary>
public static class Matrix
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region Laplacian 3X3 - Laplacian3X3
/// <summary>
/// Laplacian 3X3
/// </summary>
public static double[,] Laplacian3X3
{
get
{
return new double[,]
{
{ -1, -1, -1 },
{ -1, 8, -1 },
{ -1, -1, -1 }
};
}
}
#endregion
#region Gaussian 3X3 - Gaussian3X3
/// <summary>
/// Gaussian 3X3
/// </summary>
public static double[,] Gaussian3X3
{
get
{
return new double[,]
{
{ 1, 2, 1 },
{ 2, 4, 2 },
{ 1, 2, 1 }
};
}
}
#endregion
}
}
728x90
▶ BitmapHelper.cs
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace TestProject
{
/// <summary>
/// 비트맵 헬퍼
/// </summary>
public static class BitmapHelper
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 비트맵 로드하기 - LoadBitmap(filePath)
/// <summary>
/// 비트맵 로드하기
/// </summary>
/// <param name="filePath">파일 경로</param>
/// <returns>비트맵</returns>
public static Bitmap LoadBitmap(string filePath)
{
using(Bitmap bitmap = new Bitmap(filePath))
{
return new Bitmap(bitmap);
}
}
#endregion
#region 가우스 3X3 라플라시안 3X3 필터 적용하기 - ApplyLaplacian3X3OfGaussian3X3Filter(sourceBitmap)
/// <summary>
/// 가우스 3X3 라플라시안 3X3 필터 적용하기
/// </summary>
/// <param name="sourceBitmap">소스 비트맵</param>
/// <returns>비트맵</returns>
public static Bitmap ApplyLaplacian3X3OfGaussian3X3Filter(Bitmap sourceBitmap)
{
Bitmap targetBitmap = ApplyConvolutionFilter
(
sourceBitmap,
Matrix.Gaussian3X3,
1.0 / 16.0,
0,
true
);
targetBitmap = ApplyConvolutionFilter
(
targetBitmap,
Matrix.Laplacian3X3,
1.0,
0,
false
);
return targetBitmap;
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Private
#region 회선 필터 적용하기 - ApplyConvolutionFilter(sourceBitmap, filterArray, factor, bias, grayscale)
/// <summary>
/// 회선 필터 적용하기
/// </summary>
/// <param name="sourceBitmap">소스 비트맵</param>
/// <param name="filterArray">필터 배열</param>
/// <param name="factor">팩터</param>
/// <param name="bias">바이어스</param>
/// <param name="grayscale">회색조 여부</param>
/// <returns>비트맵</returns>
private static Bitmap ApplyConvolutionFilter
(
Bitmap sourceBitmap,
double[,] filterArray,
double factor = 1,
int bias = 0,
bool grayscale = false
)
{
BitmapData sourceBitmapData = sourceBitmap.LockBits
(
new Rectangle (0, 0, sourceBitmap.Width, sourceBitmap.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb
);
byte[] sourceByteArray = new byte[sourceBitmapData.Stride * sourceBitmapData.Height];
byte[] targetByteArray = new byte[sourceBitmapData.Stride * sourceBitmapData.Height];
Marshal.Copy(sourceBitmapData.Scan0, sourceByteArray, 0, sourceByteArray.Length);
sourceBitmap.UnlockBits(sourceBitmapData);
if(grayscale == true)
{
float rgb = 0;
for(int k = 0; k < sourceByteArray.Length; k += 4)
{
rgb = sourceByteArray[k ] * 0.11f;
rgb += sourceByteArray[k + 1] * 0.59f;
rgb += sourceByteArray[k + 2] * 0.3f;
sourceByteArray[k ] = (byte )rgb;
sourceByteArray[k + 1] = sourceByteArray[k];
sourceByteArray[k + 2] = sourceByteArray[k];
sourceByteArray[k + 3] = 255;
}
}
double blue = 0.0;
double green = 0.0;
double red = 0.0;
int filterWidth = filterArray.GetLength(1);
int filterHeight = filterArray.GetLength(0);
int filterOffset = (filterWidth-1) / 2;
int sourceOffset = 0;
int targetOffset = 0;
for(int offsetY = filterOffset; offsetY < sourceBitmap.Height - filterOffset; offsetY++)
{
for(int offsetX = filterOffset; offsetX < sourceBitmap.Width - filterOffset; offsetX++)
{
blue = 0;
green = 0;
red = 0;
targetOffset = offsetY * sourceBitmapData.Stride + offsetX * 4;
for(int filterY = -filterOffset; filterY <= filterOffset; filterY++)
{
for(int filterX = -filterOffset; filterX <= filterOffset; filterX++)
{
sourceOffset = targetOffset + (filterX * 4) + (filterY * sourceBitmapData.Stride);
blue += (double)(sourceByteArray[sourceOffset ]) *
filterArray[filterY + filterOffset, filterX + filterOffset];
green += (double)(sourceByteArray[sourceOffset + 1]) *
filterArray[filterY + filterOffset, filterX + filterOffset];
red += (double)(sourceByteArray[sourceOffset + 2]) *
filterArray[filterY + filterOffset, filterX + filterOffset];
}
}
blue = factor * blue + bias;
green = factor * green + bias;
red = factor * red + bias;
if(blue > 255)
{
blue = 255;
}
else if(blue < 0)
{
blue = 0;
}
if(green > 255)
{
green = 255;
}
else if(green < 0)
{
green = 0;
}
if(red > 255)
{
red = 255;
}
else if(red < 0)
{
red = 0;
}
targetByteArray[targetOffset ] = (byte)blue;
targetByteArray[targetOffset + 1] = (byte)green;
targetByteArray[targetOffset + 2] = (byte)red;
targetByteArray[targetOffset + 3] = 255;
}
}
Bitmap targetBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);
BitmapData targetBitmapData = targetBitmap.LockBits
(
new Rectangle (0, 0, targetBitmap.Width, targetBitmap.Height),
ImageLockMode .WriteOnly,
PixelFormat.Format32bppArgb
);
Marshal.Copy(targetByteArray, 0, targetBitmapData.Scan0, targetByteArray.Length);
targetBitmap.UnlockBits(targetBitmapData);
return targetBitmap;
}
#endregion
}
}
300x250
▶ MainForm.cs
using System.Drawing;
using System.Windows.Forms;
namespace TestProject
{
/// <summary>
/// 메인 폼
/// </summary>
public partial class MainForm : Form
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
Bitmap sourceBitmap = BitmapHelper.LoadBitmap("IMAGE\\sample.jpg");
Bitmap targetBitmap = BitmapHelper.ApplyLaplacian3X3OfGaussian3X3Filter(sourceBitmap);
this.pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
this.pictureBox.Image = targetBitmap;
}
#endregion
}
}
728x90
그리드형(광고전용)