※ 주의사항 ※
본 블로그는 수업 내용을 바탕으로 제가 이해한 부분을 정리한 블로그입니다.
본 내용을 참고로만 보시고, 틀린 부분이 있다면 지적 부탁드립니다!
감사합니다😁
안녕하세요!!
오늘은 아래와 같은 내용을 확인해보겠습니다.
디지털 이미지 처리 과정(개요)
이미지 파일 열기
이미지 파일 표시(Display)
C# Window Form (GUI)
새로운 과목이 시작되었습니다!!
지난 약 400여시간동안 PLC와 마이크로프로세서(ATmega 및 Arduino)에 대해 배워보았었습니다.
앞으로는 프로그래밍 과목인 C#에 대해 배워보도록 하겠습니다.
단순히 C# 언어의 기능과 코드만을 배우면 재미도 없고 성취감도 없기 때문에
그레이 스케일 이미지를 가공하고 처리하는 프로그램을 만드것을 목표로 C#에 대해 알아가보도록 하겠습니다!!
1. Digital Gray Scale Image 처리 과정
※ 영상처리 프로그램에 사용되는 Image
- 일반 Color사진이 아닌 Gray Scale(회색조) 사진을 가공하도록 하겠습니다.
(코딩의 난이도 조절을 위해 사진의 가로, 세로 길이가 같고 무채색 계열의 사진 가공)
- 따라서, 본 프로그램에 사용되는 사진의 확장자는 "RAW" 입니다.
※ 영상처리 프로그램 기본 함수 처리 순서
✔ 첫째, 영상처리에 사용할 이미지를 연다
✔ 둘째, 해당 이미지의 폭과 높이를 구해서 2차원 배열의 메모리를 할당한다.(inImage[ , ])
✔ 셋째, 이미지 파일내의 값을 메모리에 옮긴다
✔ 넷재, 출력할 이미지의 크기를 결정한다.
✔ 다섯째, 열때와 동일하게 출력 이미지의 메모리를 할당한다(outImage[ , ])
✔ 여섯째, open한 이미지를 가공하기 위한 알고리즘을 작성하고, 값을 메모리에 옮긴다.
✔ 일곱번째, 출력 이미지 메모리를 display 한다.
- 위의 일곱개의 과정은 영상처리 공통 과정에 속하며 이중에서 여섯번째 과정은 이미지를 가공하고 처리하는 영상처리 알고리즘에 해당된다. 따라서 여섯번째의 과정은 다양한 기능과 항목으로 나뉘어서 기능이 추가될 예정이다.
2. C# Windows Forms
- C# Windows Forms은 간단히 말해서 Widows GUI 프로그래밍을 위한 툴(?) 이라 생각하면 된다!!
2-1. Windows Forms 시작
(1) windows Forms 만들기
(2) 초기화면 및 코드
- windows Forms를 만들고 초기화면이 나오기까지 약간의 대기시간이 필요하다.
- 'Form'은 사용자가 GUI 환경에서 다양한 기능을 추가하기 위한 '도화지' 라고 생각하면 된다.
- 초기화면에서 코딩을 하기 위한 화면으로 넘어가기 위해서는 Form에서 우클릭 후 '코드 보기'를 누르거나 단축키 [Ctrl + Alt + 0]을 누르면 된다.
(3) GUI 기본 구성 항목
- 우측에 있는 도구 상자의 다양한 항목을 Drag & Drop을 통해 Form에 다양한 기능을 추가해 놓은 상태
- 물론 이렇게 구성만 한다고 기능이 동작하는 것이 아닌 해당 항목을 더블클릭하여서 관련 코드를 입력해 주어야 한다.
- 위의 도구상자에서 button을 드래그 앤 드롭 후 더블클릭을 하면 코드화면에 button1_Click() 함수가 추가된다.
※ 만약 더블클릭을 잘못해서 사용하지 않을 항목이 위와같이 코드가 생성되었다면 함부로 코드를 지우면 안된다. (오류 발생) → 그냥 코드가 있는채로 가만히 놔 두던가, GUI에서 해당 항목을 삭제한 후 코드를 삭제해보도록 한다. 만일 후자의 방법으로 해도 오류가 발생하는 경우는 그냥 코드를 놔두는 방향으로 추천한다...
2-2. 이미지 파일을 열기 위한 Windows Form 작성(GUI)
(1) Form1 Name 및 Text, Color 변경
- Form1에서 우클릭 후 속성창에서 Name과 Text, Color 등을 변경한다.
- 중요한 기능을 네이밍하는것은 프로그래밍을 잘하기 위한 중요한 부분중에 하나이기 때문에 사용자나 작업자가 알아보기 쉽고, 이해하기 쉬운 네이밍을 짓는 연습이 필요하다.
✔ Name : MainForm
✔ Text : Gray Scale Image Processing Beta 2
✔ BackColor : GradientlnactiveCaption
(2) MenuStrip, PictureBox 생성 및 속성 변경
- 도구상자에서 MenuStrip을 Drag & Drop 후 아래의 사진과 같이 입력한다.
- 도구상자에서 PictureBox를 드래그 앤 드롭 후 속성창에서 이름을 변경하여 준다.
✔ Name : PB_OutImage
- PictureBox는 openImage와 displayImage를 보여줄 '액자'라고 생각하면 된다.
(3) OpenFileDialog 추가하기
- 어떠한 프로그램에서 파일 - 열기를 누르면 뜨는 창을 우리들은 쉽게 상상할 수 있다.
- 이러한 창을 C#의 Windows Form에선 쉽게 구현할 수 있다.
(옛날에는 이러한 창을 구성할라면 코드가 천줄가량이 필요했다고 한다..)
- 도구상자에서 OpenFileDialog를 드래그 앤 드롭을 한다.
- GUI 환경에선 드래그 앤 드롭까지만 하고 나머지는 코딩을 통해 해결할 예정이다..
3. 이미지 파일 열기(Open) 및 표시(Display) 하기
3-1. 전역 변수 선언
static byte[,] inImage = null, outImage = null;
static int inH, inW, outH, outW;
static string fileName;
static Bitmap paper;
- 사용자 정의 함수부에서 자주 사용될 변수들은 전역변수로 미리 선언해 둔다.
- 본문의 위에 있는 영상처리 프로그램 구성도를 참고해서 inImage, outImage와 넓이와 폭을 나타내는 변수들을 전역변수로 선언하였다.
3-2. OpenImage
// ofd : 파일을 담는 변수, new는 객체지향적인 특성상 붙혀준다.
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.Cancel)
return;
fileName = ofd.FileName;
BinaryReader br = new BinaryReader(File.Open(fileName, FileMode.Open));
// (중요!!) 이미지의 폭과 높이
long fsize = new FileInfo(fileName).Length;
inH = inW = (int)Math.Sqrt(fsize); // RAW 파일은 가로세로 길이가 같다.
// 메모리 할당
inImage = new byte[inH, inW];
// 파일 --> 메모리
for (int i = 0; i < inH; i++)
{
for (int k = 0; k < inW; k++)
{
inImage[i, k] = br.ReadByte();
}
}
br.Close();
equalImage();
// 어떨때는 inImage를 display하고 어떨때는 outImage를 display하면
// 코드가 복잡해지고 버그의 발생이 많아질 우려가 있기 때문에
// openImage와 동일한 Image를 outImage에 display한다.
- GUI에서 드래그 앤 드롭했던 OpenFileDialog를 본 코드에서 객체를 호출하고 생성한다.
- OpenFileDialog 창을 통해 파일을 열게되면 해당 파일 경로는 fileName의 변수에 저장된다.
- RAW 이미지 파일은 가로와 세로의 길이가 같기 때문에 Math 클래스의 Sqrt 매서드를 이용해서 길이를 산출한다.
- 그리고 BinaryReader를 통해 해당 파일의 값(Byte)을 읽어서 inImage에 차곡 차곡 저장한다.
(2중 for문을 통해 inH * inW크기의 Byte 타입의 데이터를 저장한다)
3-3. DisplayImage
// 크기 지정
paper = new Bitmap(outH, outW); // 종이
PB_OutImage.Size = new Size(outH, outW); // 액자
this.Size = new Size(outH + 40, outW + 110); // 벽(윈도우창)
Color pen;
for (int i = 0; i < outH; i++)
{
for (int k = 0; k < outW; k++)
{
byte ink = outImage[i, k];
// 펜에 잉크 묻히기, RGB 3색이 같아야 회색조
pen = Color.FromArgb(ink, ink, ink);
paper.SetPixel(k, i, pen);
}
}
PB_OutImage.Image = paper; // 액자에 종이 걸기
- 이번 프로젝트에서 만들고자 하는 프로그램은 Gray Scale Image Processing이기 때문에 RGB의 색상의 값이 동일한 회색조로 표현될 예정이다. 따라서 FromArgb()의 값은 모두 동일한 변수(ink)로 넣어준다.
3-4. equalmage
// 이미지를 열지 않았으면 영상처리 불가
if (inImage == null) return;
// 중요 !! 출력 영상의 크기를 결정 --> 알고리즘에 따라 다름
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();
- 알고리즘에 따라 출력 이미지의 크기(outH, outW)가 달라진다.
→ 아주 간단한 예로, 확대의 경우는 출력 이미지의 크기가 처음 이미지의 크기보다 더 커지기 때문에 outH와 outW의 값은 위의 코드와는 달라진다.
✔ 앞으로 다양한 영상처리 알고리즘을 작성하고 다양한 이미지 처리 및 가공 기능을 추가할텐데 모두다 위와 같은 형태를 기본으로 하고 조금씩 수정할 예정이다.
4. 결과
- 파일 → 열기 후 RAW 확장자를 가진 이미지 파일을 열면 아래와 같이 이미지가 보여지는것을 알 수 있다.
- 앞으로 파일을 열고 해당 사진을 다양한 기법(화소점 처리, 기하학 처리, 히스토그램 처리, 화소영역 처리)으로 이미지를 가공하고 편집할 예정이다.
댓글