CHIP KIDD

[C#] 8. GUI를 이용한 영상처리 프로그램 본문

전기전자/C# 시각화프로그래밍

[C#] 8. GUI를 이용한 영상처리 프로그램

쑨야미 2021. 4. 15. 18:33

설계 순서도

계획 => 분석 => 설계 => 구현(코딩) => 유지보수

 

* 분석 중요

설계 구성도 

1. Raw Data 사진파일을 메모리에 로딩시킴

2. In Image를 영상처리 알고리즘 처리하여 Out Image 로저장

3. WinForm을 이용하여 Out Image를 Bitmap에 저장하여 출력/저장한다. 

 

결과

윈폼 설정 단계부터 Code까지

1) 콘솔앱이 아닌 Windows Forms 으로 새 프로젝트 생성

2) 아래와 같이 WinForm 창이 뜬다. 도구상자 왼쪽에 띄워준다. (C#의 장점) ,, MFC로도 하는데 훨씬 복잡하다. 

3) 만들기

menusetup  클릭
메뉴바를 추가하는 칸 

메뉴바를 추가한뒤 더블클릭하면 클릭시 동작하는 함수를 작성하는 코드란이 뜬다. 

 

아래 세개를 위의 그림에 나와있듯이 찾은뒤 더블클릭하면 아래처럼 배열된다.

WinForm 메뉴바의 열기를 더블클릭하면 열기에 해당하는 함수 작성코드란이 뜬다. 여기에 영상처리 알고리즘 코드를 작성한다. 

 

코드를 통해 outImage를 생성하면, Bitmap에 저장을해야 Display에 출력할 수 있는데, 이때, Bitmap을 

'PictureBox'를 통해 생성한다. 주의할점은 속성에서 이름을 설정한뒤 코드 생성시 이름 을 맞춰줘야한다. 

CODE

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO; // IOI
namespace Day03_02_영상처리_Beta2__GUI_
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // 전역 변수
        byte[,] inImage, outImage;
        int inH = 0, inW = 0, outH = 0, outW = 0;
        String fileName;
        Bitmap bitmap;

private void 열기ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.ShowDialog();
            fileName = ofd.FileName;
            // 파일의 크기를 알아내기
            long fSize = new FileInfo(fileName).Length;
            // 중요! 입력메모리의 크기를 알아냄.
            inH = inW = (int)Math.Sqrt((double)fSize);
            // 입력 메모리 확보
            inImage = new byte[inH, inW];
            // 파일 --> 입력 메모리 로딩
            BinaryReader br = new BinaryReader(File.Open(fileName, FileMode.Open));
            for (int i = 0; i < inH; i++)
                for (int k = 0; k < inW; k++)
                    inImage[i, k] = br.ReadByte();
            br.Close();
            // MessageBox.Show(inImage[100, 100].ToString());
            //displayImage();

            equalImage();
        }
    
    

영상을 불러와서 In Image 변수에 값 집어넣기 

 

void displayImage()
        {
            // 비트맵 및 픽처박스 크기 조절
            bitmap = new Bitmap(outH, outW);
            pbox_image.Size = new Size(outH, outW);
            this.Size = new Size(outH+20, outW+90);

            Color pen;// 비트맵에 콕콕 찍을 펜.
            for(int i=0; i<outH; i++)
                for (int k=0; k<outW; k++)
                {
                    byte data = outImage[i, k]; // 한점(=색상)
                    pen = Color.FromArgb(data, data, data); //펜에 잉크 묻힘
                    bitmap.SetPixel(k, i, pen); // 콕! 점찍기.
                   }

            pbox_image.Image = bitmap;
        }

bitmap에 out image 값 저장해서 display 하는부분

 

/// 영상처리 알고리즘 ///
       

        void equalImage()
        {
            // 중요! 출력 이미지의 크기. --> 알고리즘에 의존.
            outH = inH;
            outW = inW;
            // 출력 이미지 메모리 할당
            outImage = new byte[outH, outW];
            /// 진짜! 영상처리 알고리즘을 구현
            for (int i = 0; i < inH; i++)
                for (int k = 0; k < inW; k++)
                {
                    outImage[i, k] = inImage[i,k];
                }
            displayImage();
            //MessageBox.Show(outImage[100, 100].ToString());
        }
        void reverseImage()
        {
            // 중요! 출력 이미지의 크기. --> 알고리즘에 의존.
            outH = inH;
            outW = inW;
            // 출력 이미지 메모리 할당
            outImage = new byte[outH, outW];
            /// 진짜! 영상처리 알고리즘을 구현
            for (int i = 0; i < inH; i++)
                for (int k = 0; k < inW; k++)
                {
                    outImage[i, k] = (byte)( 255- inImage[i, k]);
                }
            displayImage();
            //MessageBox.Show(outImage[100, 100].ToString());
        }

        void lightVolumUp()
        {
            // 중요! 출력 이미지의 크기. --> 알고리즘에 의존.
            outH = inH;
            outW = inW;
            // 출력 이미지 메모리 할당
            outImage = new byte[outH, outW];

            // 진짜 영상처리 알고리즘을 구현
            for (int i = 0; i < inH; i++)
                for (int k = 0; k < inW; k++)
                {
                    int pixel = inImage[i, k] + 80;
                    if (pixel > 255)
                        pixel = 255;
                    else if (pixel < 0)
                        pixel = 0;

                    outImage[i, k] = (byte)pixel;
                }
            displayImage();
        }

        void lightVolumDown()
        {
            // 중요! 출력 이미지의 크기. --> 알고리즘에 의존.
            outH = inH;
            outW = inW;
            // 출력 이미지 메모리 할당
            outImage = new byte[outH, outW];

            // 진짜 영상처리 알고리즘을 구현
            for (int i = 0; i < inH; i++)
                for (int k = 0; k < inW; k++)
                {
                    int pixel = inImage[i, k] - 80;
                    if (pixel > 255)
                        pixel = 255;
                    else if (pixel < 0)
                        pixel = 0;

                    outImage[i, k] = (byte)pixel;
                }
            displayImage();
        }

        private void 축소ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            reduceImage();
        }

        void leftrightMirror()
        {
            // 중요! 출력 이미지의 크기. --> 알고리즘에 의존.
            outH = inH;
            outW = inW;
            // 출력 이미지 메모리 할당
            outImage = new byte[outH, outW];

            // 진짜 영상처리 알고리즘을 구현
            for (int i = 0; i < inH; i++)
                for (int k = 0; k < inW; k++)
                {
                    outImage[i, k] = inImage[i,inW- k -1];
                }
        displayImage();
        }

        void updownMirror()
        {
            // 중요! 출력 이미지의 크기. --> 알고리즘에 의존.
            outH = inH;
            outW = inW;
            // 출력 이미지 메모리 할당
            outImage = new byte[outH, outW];

            // 진짜 영상처리 알고리즘을 구현
            for (int i = 0; i < inH; i++)
                for (int k = 0; k < inW; k++)
                {
                    outImage[i, k] = inImage[inH - i - 1, k];
                }
            displayImage();
        }

        void enlargeImage()
        {
            // 중요! 출력 이미지의 크기. --> 알고리즘에 의존.
            outH = 2 * inH;
            outW = 2 * inW;
            // 출력 이미지 메모리 할당
            outImage = new byte[outH, outW];
            int ary_index, ary_outdex;

            for (int i = 0; i < inH; i++)
            {
                ary_outdex = 0;
                ary_index = i * 2;
                for (int k = 0; k < inW; k++)
                {
                    outImage[ary_index, ary_outdex] = inImage[i, k];
                    ary_outdex++;
                    outImage[ary_index, ary_outdex] = inImage[i, k];
                    ary_index++;
                    outImage[ary_index, ary_outdex] = inImage[i, k];
                    ary_outdex--;
                    outImage[ary_index, ary_outdex] = inImage[i, k];
                    ary_index--; ary_outdex++; ary_outdex++;
                }

            }
            displayImage();
        }

        void reduceImage()
        {
            // 중요! 출력 이미지의 크기. --> 알고리즘에 의존.
            outH = inH / 2;
            outW = inW / 2;
            // 출력 이미지 메모리 할당

            outImage = new byte[outH, outW];
            for (int i = 0; i < inH; i++)
            {
                if (i % 2 == 1) continue;

                for (int k = 0; k < inW; k++)
                {
                    if (k % 2 == 1) continue;
                    outImage[i / 2, k / 2] = inImage[i, k];
                }
            }
            displayImage();
        }
        void WtoBImage()
        {
            // 중요! 출력 이미지의 크기. --> 알고리즘에 의존.
            outH = inH;
            outW = inW;
            // 출력 이미지 메모리 할당
            outImage = new byte[outH, outW];
            /// 진짜! 영상처리 알고리즘을 구현
            for (int i = 0; i < inH; i++)
                for (int k = 0; k < inW; k++)
                {
                    int pixel = inImage[i, k];
                    if (pixel < 127)
                        pixel = 0;
                    else if (pixel > 127)
                        pixel = 255;

                    outImage[i, k] = (byte)pixel;
                }

            displayImage();
            //MessageBox.Show(outImage[100, 100].ToString());
        }
    }
}

영상처리 알고리즘 부분

 

 private void 반전영상ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            reverseImage();
        }

        private void 흑백처ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WtoBImage();
        }

        private void 좌우반전ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            leftrightMirror();
        }
        
        private void 원래대로ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            equalImage();
        }

        private void 상하반전ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            updownMirror();
        }


        private void 밝기증가감소ToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void 증가ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            lightVolumUp();
        }

        private void 감소ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            lightVolumDown();
        }

        private void 확대ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            enlargeImage();
        }

메뉴바 클릭시 호출부분