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

728x90
반응형
728x170

TestProject.zip
다운로드

▶ MorphologyType.cs

namespace TestProject
{
    /// <summary>
    /// 형태 타입
    /// </summary>
    public enum MorphologyType
    {
        /// <summary>
        /// 침식
        /// </summary>
        Erosion,

        /// <summary>
        /// 팽창
        /// </summary>
        Dilation
    }
}

 

728x90

 

▶ MorphologyEdgeType.cs

namespace TestProject
{
    /// <summary>
    /// 형태 가장자리 타입
    /// </summary>
    public enum MorphologyEdgeType
    {
        /// <summary>
        /// 해당 무
        /// </summary>
        None,

        /// <summary>
        /// 가장자리 탐지
        /// </summary>
        EdgeDetection,

        /// <summary>
        /// 선명 가장자리 탐지
        /// </summary>
        SharpenEdgeDetection
    }
}

 

300x250

 

▶ 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 침식/팽창 필터 적용하기 - ApplyErosionAndDilationFilter(sourceBitmap, matrixSize, morphType, applyBlue, applyGreen, applyRed, edgeType)

        /// <summary>
        /// 침식/팽창 필터 적용하기
        /// </summary>
        /// <param name="sourceBitmap">소스 비트맵</param>
        /// <param name="matrixSize">매트릭스 크기</param>
        /// <param name="morphType">형태 타입</param>
        /// <param name="applyBlue">청색 채널 적용 여부</param>
        /// <param name="applyGreen">녹색 채널 적용 여부</param>
        /// <param name="applyRed">적색 채널 적용 여부</param>
        /// <param name="edgeType">형태 가장자리 타입</param>
        /// <returns>비트맵</returns>
        public static Bitmap ApplyErosionAndDilationFilter
        (
            Bitmap             sourceBitmap,
            int                matrixSize,
            MorphologyType     morphType,
            bool               applyBlue  = true,
            bool               applyGreen = true,
            bool               applyRed   = true,
            MorphologyEdgeType edgeType   = MorphologyEdgeType.None
        )
        {
            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 = (matrixSize - 1) / 2;
            int sourceOffset = 0;
            int targetOffset = 0;

            int blue  = 0;
            int green = 0;
            int red   = 0;

            byte morphResetValue = 0;

            if(morphType == MorphologyType.Erosion)
            {
                morphResetValue = 255;
            }

            for(int offsetY = filterOffset; offsetY < sourceBitmap.Height - filterOffset; offsetY++)
            {
                for(int offsetX = filterOffset; offsetX < sourceBitmap.Width - filterOffset; offsetX++)
                {
                    targetOffset = offsetY * sourceBitmapData.Stride + offsetX * 4;

                    blue  = morphResetValue;
                    green = morphResetValue;
                    red   = morphResetValue;

                    if(morphType == MorphologyType.Dilation)
                    {
                        for(int filterY = -filterOffset; filterY <= filterOffset; filterY++)
                        {
                            for(int filterX = -filterOffset; filterX <= filterOffset; filterX++)
                            {
                                sourceOffset = targetOffset + (filterX * 4) + (filterY * sourceBitmapData.Stride);

                                if(sourceByteArray[sourceOffset] > blue)
                                {
                                    blue = sourceByteArray[sourceOffset];
                                }

                                if(sourceByteArray[sourceOffset + 1] > green)
                                {
                                    green = sourceByteArray[sourceOffset + 1];
                                }

                                if(sourceByteArray[sourceOffset + 2] > red)
                                {
                                    red = sourceByteArray[sourceOffset + 2];
                                }
                            }
                        }
                    }
                    else if(morphType == MorphologyType.Erosion)
                    {
                        for(int filterY = -filterOffset; filterY <= filterOffset; filterY++)
                        {
                            for(int filterX = -filterOffset; filterX <= filterOffset; filterX++)
                            {
                                sourceOffset = targetOffset + (filterX * 4) + (filterY * sourceBitmapData.Stride);

                                if(sourceByteArray[sourceOffset] < blue)
                                {
                                    blue = sourceByteArray[sourceOffset];
                                }

                                if(sourceByteArray[sourceOffset + 1] < green)
                                {
                                    green = sourceByteArray[sourceOffset + 1];
                                }

                                if(sourceByteArray[sourceOffset + 2] < red)
                                {
                                    red = sourceByteArray[sourceOffset + 2];
                                }
                            }
                        }
                    }

                    if(applyBlue == false )
                    {
                        blue = sourceByteArray[targetOffset];
                    }

                    if(applyGreen == false )
                    {
                        green = sourceByteArray[targetOffset + 1];
                    }

                    if(applyRed == false )
                    {
                        red = sourceByteArray[targetOffset + 2];
                    }

                    if(edgeType == MorphologyEdgeType.EdgeDetection || edgeType == MorphologyEdgeType.SharpenEdgeDetection)
                    {
                        if(morphType == MorphologyType.Dilation)
                        {
                            blue  = blue  - sourceByteArray[targetOffset    ];
                            green = green - sourceByteArray[targetOffset + 1];
                            red   = red   - sourceByteArray[targetOffset + 2];
                        }
                        else if(morphType == MorphologyType.Erosion)
                        {
                            blue  = sourceByteArray[targetOffset    ] - blue;
                            green = sourceByteArray[targetOffset + 1] - green;
                            red   = sourceByteArray[targetOffset + 2] - red;
                        }

                        if(edgeType == MorphologyEdgeType.SharpenEdgeDetection)
                        {
                            blue  += sourceByteArray[targetOffset    ];
                            green += sourceByteArray[targetOffset + 1];
                            red   += sourceByteArray[targetOffset + 2];
                        }
                    }

                    blue  = (blue  > 255 ? 255 : (blue  < 0 ? 0 : blue ));
                    green = (green > 255 ? 255 : (green < 0 ? 0 : green));
                    red   = (red   > 255 ? 255 : (red   < 0 ? 0 : red  ));

                    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
    }
}

 

▶ 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.ApplyErosionAndDilationFilter
            (
                sourceBitmap,
                3,
                MorphologyType.Erosion,
                true,
                true,
                true,
                MorphologyEdgeType.EdgeDetection
            );

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

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

댓글을 달아 주세요