첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
본 블로그는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 블로그 콘텐츠 향상을 위해 쓰여집니다.

728x90
반응형
728x170

TestProject.zip
다운로드

▶ Matrix.cs

namespace TestProject
{
    /// <summary>
    /// 매트릭스
    /// </summary>
    public static class Matrix
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region Laplacian 5X5 - Laplacian5X5

        /// <summary>
        /// Laplacian 5X5
        /// </summary>
        public static double[,] Laplacian5X5
        {
            get
            {
                return new double[,]
                {
                    { -1, -1, -1, -1, -1 },
                    { -1, -1, -1, -1, -1 },
                    { -1, -1, 24, -1, -1 },
                    { -1, -1, -1, -1, -1 },
                    { -1, -1, -1, -1, -1 }
                };
            }
        }

        #endregion
        #region Gaussian 5X5 Type 2 - Gaussian5X5Type2

        /// <summary>
        /// Gaussian 5X5 Type 2
        /// </summary>
        public static double[,] Gaussian5X5Type2
        {
            get
            {
                return new double[,]
                {
                    { 1, 4 , 6 , 4 , 1 },
                    { 4, 16, 24, 16, 4 },
                    { 6, 24, 36, 24, 6 },
                    { 4, 16, 24, 16, 4 },
                    { 1, 4 , 6 , 4 , 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 가우스 5X5 타입 2 라플라시안 5X5 필터 2 적용하기 - ApplyLaplacian5X5OfGaussian5X5Type2Filter(sourceBitmap)

        /// <summary>
        /// 가우스 5X5 타입 2 라플라시안 5X5 필터 2 적용하기
        /// </summary>
        /// <param name="sourceBitmap">소스 비트맵</param>
        /// <returns>비트맵</returns>
        public static Bitmap ApplyLaplacian5X5OfGaussian5X5Type2Filter(Bitmap sourceBitmap)
        {
            Bitmap targetBitmap = ApplyConvolutionFilter
            (
                sourceBitmap,
                Matrix.Gaussian5X5Type2,
                1.0 / 256.0,
                0,
                true
            );
 
            targetBitmap = ApplyConvolutionFilter
            (
                targetBitmap,
                Matrix.Laplacian5X5,
                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.ApplyLaplacian5X5OfGaussian5X5Type2Filter(sourceBitmap);

            this.pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
            this.pictureBox.Image    = targetBitmap;
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)

'C# > WinForm' 카테고리의 다른 글

[C#/WINFORM] Bitmap 클래스 : 이미지 비트 단위 블렌딩하기  (0) 2021.01.13
[C#/WINFORM] Bitmap 클래스 : 이미지 연산하기  (0) 2021.01.12
[C#/WINFORM] Bitmap 클래스 : 키르시 3X3 가장자리 탐지 필터(Kirsch 3X3 Edge Detection Filter) 사용하기  (0) 2021.01.11
[C#/WINFORM] Bitmap 클래스 : 프리윗 3X3 가장자리 탐지 필터(Prewitt 3X3 Edge Detection Filter) 사용하기  (0) 2021.01.11
[C#/WINFORM] Bitmap 클래스 : 소벨 3X3 가장자리 탐지 필터(Sobel 3X3 Edge Detection Filter) 사용하기  (0) 2021.01.11
[C#/WINFORM] Bitmap 클래스 : 가우스 5X5 타입 2 라플라시안 5X5 가장자리 탐지 필터(Laplacian 5X5 Of Gaussian 5X5 Type 2 Edge Detection Filter) 사용하기  (0) 2021.01.11
[C#/WINFORM] Bitmap 클래스 : 가우스 5X5 타입 1 라플라시안 5X5 가장자리 탐지 필터(Laplacian 5X5 Of Gaussian 5X5 Type 1 Edge Detection Filter) 사용하기  (0) 2021.01.11
[C#/WINFORM] Bitmap 클래스 : 가우스 5X5 타입 2 라플라시안 3X3 가장자리 탐지 필터(Laplacian 3X3 Of Gaussian 5X5 Type 2 Edge Detection Filter) 사용하기  (0) 2021.01.11
[C#/WINFORM] Bitmap 클래스 : 가우스 5X5 타입 1 라플라시안 3X3 가장자리 탐지 필터(Laplacian 3X3 Of Gaussian 5X5 Type 1 Edge Detection Filter) 사용하기  (0) 2021.01.11
[C#/WINFORM] Bitmap 클래스 : 가우스 3X3 라플라시안 5X5 가장자리 탐지 필터(Laplacian 5X5 Of Gaussian 3X3 Edge Detection Filter) 사용하기  (0) 2021.01.11
[C#/WINFORM] Bitmap 클래스 : 가우스 3X3 라플라시안 3X3 가장자리 탐지 필터(Laplacian 3X3 Of Gaussian 3X3 Edge Detection Filter) 사용하기  (0) 2021.01.11
Posted by 사용자 icodebroker

댓글을 달아 주세요