[C#/WINFORM] Bitmap 클래스 : 부울 가장자리 탐지 필터(Boolean Edge Detection Filter) 사용하기
C#/WinForm 2021. 1. 10. 13:13728x90
728x170
▶ BooleanFilterType.cs
namespace TestProject
{
/// <summary>
/// 부울 필터 타입
/// </summary>
public enum BooleanFilterType
{
/// <summary>
/// 가장자리 탐지
/// </summary>
EdgeDetection,
/// <summary>
/// 선명화
/// </summary>
Sharpen
}
}
728x90
▶ BitmapHelper.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace TestProject
{
/// <summary>
/// 비트맵 헬퍼
/// </summary>
public static class BitmapHelper
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 가장자리 마스크 리스트
/// </summary>
private static List<string> _edgeMaskList;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Static
#region 생성자 - BitmapHelper()
/// <summary>
/// 생성자
/// </summary>
static BitmapHelper()
{
_edgeMaskList = new List<string>();
_edgeMaskList.Add("011011011");
_edgeMaskList.Add("000111111");
_edgeMaskList.Add("110110110");
_edgeMaskList.Add("111111000");
_edgeMaskList.Add("011011001");
_edgeMaskList.Add("100110110");
_edgeMaskList.Add("111011000");
_edgeMaskList.Add("111110000");
_edgeMaskList.Add("111011001");
_edgeMaskList.Add("100110111");
_edgeMaskList.Add("001011111");
_edgeMaskList.Add("111110100");
_edgeMaskList.Add("000011111");
_edgeMaskList.Add("000110111");
_edgeMaskList.Add("001011011");
_edgeMaskList.Add("001011011");
_edgeMaskList.Add("110110100");
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// 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 부울 가장자리 탐지 필터 적용하기 - ApplyBooleanEdgeDetectionFilter(sourceBitmap, filterType, redFactor, greenFactor, blueFactor, threshold)
/// <summary>
/// 부울 가장자리 탐지 필터 적용하기
/// </summary>
/// <param name="sourceBitmap">소스 비트맵</param>
/// <param name="filterType">필터 타입</param>
/// <param name="redFactor">적색 팩터</param>
/// <param name="greenFactor">녹색 팩터</param>
/// <param name="blueFactor">청색 팩터</param>
/// <param name="threshold">임계치</param>
/// <returns>비트맵</returns>
public static Bitmap ApplyBooleanEdgeDetectionFilter
(
Bitmap sourceBitmap,
BooleanFilterType filterType,
float redFactor = 1.0f,
float greenFactor = 1.0f,
float blueFactor = 1.0f,
byte threshold = 0
)
{
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);
int filterOffset = 1;
int sourceOffset = 0;
int targetOffset = 0;
int matrixMean = 0;
int matrixTotal = 0;
double matrixVariance = 0;
double blueValue = 0;
double greenValue = 0;
double redValue = 0;
string matrixPatern = string.Empty;
for(int offsetY = filterOffset; offsetY < sourceBitmap.Height - filterOffset; offsetY++)
{
for(int offsetX = filterOffset; offsetX < sourceBitmap.Width - filterOffset; offsetX++)
{
targetOffset = offsetY * sourceBitmapData.Stride + offsetX * 4;
matrixMean = 0;
matrixTotal = 0;
matrixVariance = 0;
matrixPatern = string.Empty;
for(int filterY = -filterOffset; filterY <= filterOffset; filterY++)
{
for(int filterX = -filterOffset; filterX <= filterOffset; filterX++)
{
sourceOffset = targetOffset + (filterX * 4) + (filterY * sourceBitmapData.Stride);
matrixMean += sourceByteArray[sourceOffset ];
matrixMean += sourceByteArray[sourceOffset + 1];
matrixMean += sourceByteArray[sourceOffset + 2];
}
}
matrixMean = matrixMean / 9;
for(int filterY = -filterOffset; filterY <= filterOffset; filterY++)
{
for(int filterX = -filterOffset; filterX <= filterOffset; filterX++)
{
sourceOffset = targetOffset + (filterX * 4) + (filterY * sourceBitmapData.Stride);
matrixTotal = sourceByteArray[sourceOffset ];
matrixTotal += sourceByteArray[sourceOffset + 1];
matrixTotal += sourceByteArray[sourceOffset + 2];
matrixPatern += (matrixTotal > matrixMean ? "1" : "0" );
matrixVariance += Math.Pow
(
matrixMean - (sourceByteArray[sourceOffset ] +
sourceByteArray[sourceOffset + 1] +
sourceByteArray[sourceOffset + 2]),
2
);
}
}
matrixVariance = matrixVariance / 9;
if(filterType == BooleanFilterType.Sharpen)
{
blueValue = sourceByteArray[targetOffset ];
greenValue = sourceByteArray[targetOffset + 1];
redValue = sourceByteArray[targetOffset + 2];
if(matrixVariance > threshold)
{
if(_edgeMaskList.Contains(matrixPatern))
{
blueValue = (blueValue * blueFactor );
greenValue = (greenValue * greenFactor);
redValue = (redValue * redFactor );
blueValue = (blueValue > 255 ? 255 : (blueValue < 0 ? 0 : blueValue ));
greenValue = (greenValue > 255 ? 255 : (greenValue < 0 ? 0 : greenValue));
redValue = (redValue > 255 ? 255 : (redValue < 0 ? 0 : redValue ));
}
}
}
else if(matrixVariance > threshold && _edgeMaskList.Contains(matrixPatern))
{
blueValue = 255;
greenValue = 255;
redValue = 255;
}
else
{
blueValue = 0;
greenValue = 0;
redValue = 0;
}
targetByteArray[targetOffset ] = (byte)blueValue;
targetByteArray[targetOffset + 1] = (byte)greenValue;
targetByteArray[targetOffset + 2] = (byte)redValue;
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.ApplyBooleanEdgeDetectionFilter(sourceBitmap, BooleanFilterType.EdgeDetection, 1, 1, 1, 64);
this.pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
this.pictureBox.Image = targetBitmap;
}
#endregion
}
}
728x90
그리드형(광고전용)
'C# > WinForm' 카테고리의 다른 글
[C#/WINFORM] Bitmap 클래스 : 회선 필터(Convolution Filter) 사용하기 (0) | 2021.01.10 |
---|---|
[C#/WINFORM] Bitmap 클래스 : 중앙값 필터(Median Filter) 사용하기 (0) | 2021.01.10 |
[C#/WINFORM] Bitmap 클래스 : 불선명 필터(Unsharp Filter) 사용하기 (0) | 2021.01.10 |
[C#/WINFORM] Bitmap 클래스 : 평균 색상 필터(Average Color Filter) 사용하기 (0) | 2021.01.10 |
[C#/WINFORM] Bitmap 클래스 : 침식/팽창 필터(Erosion/Dilation Filter) 사용하기 (0) | 2021.01.10 |
[C#/WINFORM] Bitmap 클래스 : 2개의 비트맵에서 차이점 찾기 (0) | 2021.01.10 |
[C#/WINFORM] Bitmap 클래스 : 그라디언트 기반 가장자리 탐지 필터(Gradient Based Edge Detection Filter) 사용하기 (0) | 2021.01.10 |
[C#/WINFORM] Bitmap 클래스 : 카툰 필터(Cartoon Filter) 사용하기 (0) | 2021.01.09 |
[C#/WINFORM] Bitmap 클래스 : 스무딩 필터(Smoothing Filter) 사용하기 (0) | 2021.01.09 |
[C#/WINFORM] Bitmap 클래스 : 선명 가장자리 탐지 필터(Sharpen Edge Detection Filter) 사용하기 (0) | 2021.01.09 |