제 3 장 영역 기반 처리.

Slides:



Advertisements
Similar presentations
2013 년 목 차 용어의 정의 위기경보 수준 국가 생물테러 대응 체계도 반 · 팀별 소방의 임무.
Advertisements

YES C 제 1 장 C 언어의 개요 1/34 제 1 장 C 언어의 개요 문봉근. YES C 제 1 장 C 언어의 개요 2/34 제 1 장 C 언어의 개요 1.1 프로그램과 C 언어의 특징 1.2 C 언어의 프로그램 구성 1.3 비주얼 C++ 통합 환경 들어가기.
프로젝트 보고서 학과 : 임학과 학번 : 성명 : 조성환 Windows 프로그래밍.
Visual C++ Programming Document/View Architecture
Digital Image Processing
안전은 사랑입니다. 산업안전보건법령(밀폐공간작업) 서울지방노동청.
프로그래밍1 및 실습 (C언어) - 3장 기본자료형 (3.6부터 끝까지) -
Vision System Lab, Sang-Hun Han
제 3 장 변수와 자료형.
03장 영상처리를 위한 Visual C++ 디지털 영상 파일 포맷 MFC 응용 프로그램 마법사를 이용한 MFC 프로젝트 작성
Power C++ 제6장 포인터와 문자열.
C++ Espresso 제3장 배열과 포인터.
C++ Espresso 제3장 배열과 포인터.
Lab 10 Guide: 프린터 출력 예제. 한 페이지의 그림 인쇄 (교재 24장, 쪽)
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express.
원정초등학교 5학년1반 48번 윤민정.
제 1 장 영상처리 기초.
위생 노로바이러스 예방수칙 □ 노로바이러스란 노로바이러스는 사람에게 장염을 일으키는 바이러스 그룹입니다.
쉽게 풀어쓴 C언어 Express 제13장 구조체 C Express Slide 1 (of 25)
컬러 LED바 이해하기 목차 재료준비 및 브레드 보드 배선 구성하기 컬러 LED바 이해 및 프로그램 실습 응용 작품 만들기.
제 6 장 영상 워핑과 모핑.
제 7 장 동영상 처리.
4장: 자료형과 수식.
쉽게 풀어쓴 C언어 Express 제4장 변수와 자료형 C Express.
컴퓨터의 기초 제 4강 - 표준 입출력, 함수의 기초 2006년 4월 10일.
처음으로 배우는 C 프로그래밍 제2부 기초 제5장 반복문.
제 9 장 영상압축.
Choi, Namseok Java 기초 (Java의 제어문과 배열) Choi, Namseok
Chapter 1 디지털 영상처리의 개념.
6장 히스토그램 처리 차 례 히스토그램의 개요 히스토그램의 용도 영상 이치화 히스토그램 평활화 히스토그램 스트레칭
MFC Application Frameworks (AFX)
Visual C++ Programming Output and File
조도 센서 김한수.
Visual C++ Programming Output and File
AVR - Chapter 2 황 지 연.
제 5 장 기하학적 처리.
03장 영상처리를 위한 Visual C++ 디지털 영상 파일 포맷
프로그래밍2 및 실습 C언어 기반의 C++ 2.
캡스톤 물리 음성 인식을 통한 무드 등 지금은 6시 55분 조.
제 3 장 상수와 변수
분할 윈도, 다중 뷰… 영상 통신 연구실 권 동 진 발표 일 : 04월 27일.
제 4주 2014년 1학기 강원대학교 컴퓨터학부 담당교수: 정충교
아두이노 프로그래밍 3일차 – Part1 컬러 LED바 활용하기 강사: 김영준 목원대학교 겸임교수
쉽게 풀어쓴 C언어 Express 제4장 변수와 자료형 C Express.
7 영역처리를 이용한 에지 검출 01 에지 검출의 개요 02 에지 검출기 03 1차 미분을 이용한 에지 검출
쉽게 풀어쓴 C언어 Express 제4장 변수와 자료형 C Express.
버퍼 (Buffer).
컴퓨터의 기초 제 2강 - 변수와 자료형 , 연산자 2006년 3월 27일.
CGI (Common Gateway Interface)
제 2장 어휘구조와 자료형 토 큰 리 터 럴 주 석 자 료 형 배 열 형.
컴퓨터 프로그래밍 기초 - 4th : 수식과 연산자 -
Chapter 4 컬러( COLOR ).
[CPA340] Algorithms and Practice Youn-Hee Han
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
지중 공가설비 조사자 안전관리 교육
Lab 9 Guide: 인터넷 프로그래밍 예제 * 일대일 채팅 프로그램 (교재 27장, 쪽)
자바 5.0 프로그래밍.
빛 의 합 성 과 학 1 학년 Ⅱ. 빛 > 2. 빛의 색( 8/8 ) [초기 화면]
포인터와 배열 조 병 규 한 국 교 통 대 학 교 SQ Lab..
제 8장. 클래스의 활용 학기 프로그래밍언어및실습 (C++).
04장 ㅎㅎ 화소점 처리 화소 점 처리의 개념 디지털 영상의 산술연산과 논리연산 디지털 영상의 다양한 화소 점 처리 기법
C언어 프로그래밍의 이해 Ch03. 기본 자료형, 변수와 상수.
반복문의 기능 반복문 반복문 특정 영역을 특정 조건이 만족하는 동안에 반복 실행하기 위한 문장 while문
실습과제 1번 생성된 파일 basic.txt를 프로젝트 폴더에서 메모장으로 열고 내용을 확인
박성진 컴퓨터 프로그래밍 기초 [03] 변수와 자료형 박성진
어서와 C언어는 처음이지 제16장.
argc, argv 의 사용방법 #include <stdio.h>
C.
개정판 누구나 즐기는 C언어 콘서트 제12장 파일 입출력 출처: pixabay.
Ch.11. 이진영상처리를 이용한 영상인식.
Presentation transcript:

제 3 장 영역 기반 처리

학습목표 회선의 개념을 설명할 수 있다. 다음 영역기반 처리의 원리를 설명하고 프로그램을 작성할 수 있다 영상 흐리게 하기 선명화 경계선 검출 잡음제거 컬러 영상 처리 이중포인터를 설명하고 프로그램에서 활용할 수 있다 프로그램에서 PGM, PPM 파일을 활용할 수 있다 2019-02-18

영역 기반 처리 입력 화소와 그 주위 화소를 이용하여 출력 화소값을 결정 회선(convolution) 기법을 널리 이용 영역 기반 처리 예 흐리게 하기, 선명하게 하기, 경계선 검출, 잡음 제거 2019-02-18

회선 출력 픽셀 값 입력 픽셀과 그 주위 픽셀 값에 회선 마스크의 값을 곱하여 합한 값 2019-02-18

회선 수행 방법 좌측 상단의 픽셀부터 한 픽셀 씩 차례로 수행 먼저 우측 방향으로 진행 한 줄이 끝나면 아래 줄로 이동 2019-02-18

회선 마스크의 특성 회선 마스크의 크기는 홀수를 사용 많은 회선 마스크들은 계수들의 합이 1 이됨 주위 픽셀 값을 각 방향에 대칭적으로 고려해야 하므로 3 x 3, 5 x 5, 7 x 7 등의 크기 사용 많은 회선 마스크들은 계수들의 합이 1 이됨 회선된 영상은 원영상과 같은 평균 밝기 값을 가짐 경계선 검출등 일부 회선 마스크에서는 음수의 계수를 포함하고 계수 합이 0 이됨 음의 화소값들이 생성될 수 있으므로 전형적으로 생성된 화소값에 일정한 상수(최대밝기/2 와 같은)가 더해짐 2019-02-18

영상의 경계처리 0 삽입 윈도우가 영상과 중첩되는 첫 위치에서 회선이 시작 원영상의 크기를 조정 윈도우의 빈 셀들의 계수를 0으로 가정함 윈도우가 영상과 중첩되는 첫 위치에서 회선이 시작 마스크가 3X3일 때에 (0,0) 대신 (1,1)에서 시작 원영상의 크기를 조정 영상의 경계부분의 화소들을 복사 영상을 둘러쌈 2019-02-18

영상 흐리게하기 입력 픽셀 값을 주위 픽셀 값들과의 평균 값으로 변환하는 다음과 같은 회선 마스크를 널리 사용 평균 마스크 2019-02-18

영상 흐리게 하기 예 3X3 마스크 적용 5X5 마스크적용 입력영상 2019-02-18

영상의 선명화 선명한 영상 생성을 위한 회선 마스크 -1 5 -1 9 마스크 1 마스크 2 2019-02-18

선명화 적용 예 입력 영상 마스크 1 적용 마스크 2 적용 2019-02-18

선명화 적용 예 10 20 30 40 10 40 20 50 80 2019-02-18

선명화 적용 예 2019-02-18

경계선 검출 경계선 입력 영상에 대한 많은 정보 포함 물체를 식별하고 물체의 위치, 모양, 크기 등을 인지하는 데 큰 역할 영상의 밝기가 낮은 값에서 높은 값으로 또는 높은 값에서 낮은 값으로 변하는 지점에 존재 2019-02-18

미분 연산자 2019-02-18

경계선 검출 회선 마스크 미분 연산을 회선 마스크로 표현 가능 수평 경계선 수직 경계선 Prewitt Roberts Sobel 수평 경계선과 수직 경계선을 개별적으로 검출 수평 경계선 수직 경계선 Prewitt Roberts Sobel 2019-02-18

경계선 크기 계산 픽셀 I(x,y)가 경계선일 가능성의 크기 : 수평 경계선 검출용 회선 마스크 적용 결과 값 : 수직 경계선 검출용 회선 마스크 적용 결과 값 2019-02-18

경계선 검출 결과 입력영상 Sobel Prewitt Roberts 2019-02-18

잡음 제거 잡음 가우시안 잡음 임펄스 잡음 정규 분포를 갖는 잡음 영상의 픽셀 값으로부터 불규칙적으로 벗어나지만 뚜렷하게 벗어나지 않는 잡음 임펄스 잡음 영상의 픽셀 값과는 뚜렷하게 다른 픽셀 값에 의한 잡음 0, 255와 같은 뚜렷하게 잘못된 밝기 값을 갖는 화소 2019-02-18

잡음 예 가우시안 잡음 임펄스 잡음 2019-02-18

잡음 제거 평균 마스크 가우시안 노이즈를 줄이는데 효과적 임펄스 노이즈에는 비효과적 영상의 대비를 약화시킴 2019-02-18

잡음 제거 적용 예 평균 마스크를 이용한 잡음 제거 결과 가우시안 잡음 제거 결과 임펄스 잡음 제거 결과 2019-02-18

잡음 제거 중간값 필터링 임펄스 잡음을 제거하기위한 효과적인 방법 경계선을 보존 또는 강화 출력 영상 픽셀값의 정렬 13 15 16 17 18 20 22 255 입력 영상 필터 윈도우 15 16 17 13 255 18 20 22 2019-02-18

잡음 제거 적용 예 중간값 필터링을 이용한 잡음 제거 결과 가우시안 잡음 제거 결과 임펄스 잡음 제거 결과 2019-02-18

컬러 영상에서의 회선 RGB 컬러 모델에서의 회선 입력 컬러 영상 빨강색 성분 초록색 성분 파랑색 성분 + + 회선 수행 출력 컬러 영상 빨강색 성분 초록색 성분 파랑색 성분 + + 2019-02-18

컬러 영상에서의 회선 HSI 컬러 모델에서의 회선 색상 입력 변환된 결과 명도 영상 명도 영상 회선 수행 RGB 컬러 채도 RGB 컬러 HSI 컬러 2019-02-18

컬러 영상에서의 경계선 검출 RGB 컬러 모델 사용 HSI 컬러 모델 R,G,B 각각에 대하여 회선 수행 RGB 모델을 HSI 모델로 변환한 다음에 명도값 (I) 에 대해서만 회선 적용 2019-02-18

임의의 크기 영상 처리를 위한 기억 장소 할당 프로그램의 유용성 향상을 위해 임의의 크기 처리 필요 임의의 크기 영상을 위해 PGM과 PPM 파일 사용 2019-02-18

영상 저장을 위한 변수 선언 임의의 영상을 저장하기 위한 기억 장소 크기가 미리 정해져 있지 않으므로 배열 사용이 불가능 크기가 미리 정해져 있지 않으므로 배열 사용이 불가능 기억 장소를 프로그램 실행 중에 동적으로 할당 변수는 포인터로 선언 2019-02-18

영상 저장을 위한 포인터 선언 방법 단일 포인터를 이용한 방법 일차원 배열처럼 사용 변수 선언 및 기억 장소 할당이 단순 영상의 픽셀 값을 사용하는 데에는 불편 2019-02-18

단일 포인터를 이용한 방법 영상을 저장할 변수 필요 영상의 크기를 저장할 변수 필요 흑백 영상과 컬러 영상을 구분하기 위한 변수 필요 unsigned char *inputImg; // 입력 영상의 기억 장소에 대한 포인터 변수 unsigned char *resultImg; // 출력 영상의 기억 장소에 대한 포인터 변수 int imageWidth; // 영상의 가로 크기 int imageHeight; // 영상의 세로 크기 int depth; // 1 = 흑백 영상, 3 = 컬러 영상 2019-02-18

inputImg = (unsigned char *) malloc(imageWidth * imageHeight * depth); 단일 포인터를 이용한 방법 기억 장소 할당 inputImg = (unsigned char *) malloc(imageWidth * imageHeight * depth); resultImg = (unsigned char *) malloc(imageWidth * imageHeight * depth); 입력 픽셀값 저장 장소 I(0,0) inputImg[0] I(0,1) inputImg[1] ... I(0,imageWidth-1) inputImg[imageWidth-1] I(1,0) inputImg[imageWidth] I(1,1) inputImg[imageWidth+1] I(y,x) inputImg[y * imageWidth + x] I(imageHeight-1, imageWidth-1) inputImg[imageHeight * imageWidth - 1] 흑백 영상 2019-02-18

단일 포인터를 이용한 방법 임의의 크기의 흑백 영상에 대한 산술 덧셈 for (y = 0; y < imageHeight; y++) for (x = 0; x < imageWidth; x++) { value = inputImg[y * imageWidth + x] + 100; if (value > 255) value = 255; resultImg[y * imageWidth + x] = value; } 2019-02-18

단일 포인터를 이용한 방법 단일 루프를 이용한 방법(흑백영상) for (k = 0; k < imageWidth * imageHeight; k++) { value = inputImg[k] + 100; if (value > 255) value = 255; resultImg[k] = value; } 2019-02-18

이중 포인터를 이용한 방법 이중 포인터를 이용한 방법 이차원 배열처럼 사용 변수 선언과 기억 장소 할당이 어려움 영상의 픽셀 값 사용이 편리 2019-02-18

이중 포인터를 이용한 방법 영상 저장을 위한 변수 선언 기억 장소 할당 unsigned char **inputImg; // 입력 영상의 기억 장소에 대한 포인터 변수 unsigned char **resultImg; // 출력 영상의 기억 장소에 대한 포인터 변수 inputImg = (unsigned char **) malloc(imageHeight * sizeof(unsigned char *)); resultImg = (unsigned char **) malloc(imageHeight * sizeof(unsigned char *)); for (i = 0; i < imageHeight; i++) { inputImg[i] = (unsigned char *) malloc(imageWidth * depth); resultImg[i] = (unsigned char *) malloc(imageWidth * depth); } 2019-02-18

이중 포인터를 이용한 방법 2019-02-18

이중 포인터를 이용한 방법 흑백 영상의 산술 덧셈 이차원 배열을 이용한 방법과 동일 for (y = 0; y < imageHeight; y++) for (x = 0; x < imageWidth; x++) { value = inputImg[y][x] + 100; if (value > 255) value = 255; resultImg[y][x] = value; } 2019-02-18

PGM과 PPM 파일 형식 읽기 실습

PGM과 PPM 파일 형식 읽기 영상 저장을 위한 변수 선언 수정 -- 수정전 unsigned char inputImg[256][256]; unsigned char inputImg2[256][256]; unsigned char resultImg[256][256]; -- 수정후 unsigned char **inputImg; // 입력 영상의 기억 장소에 대한 포인터 변수 unsigned char **inputImg2; // 입력 영상의 기억 장소에 대한 포인터 변수 unsigned char **resultImg; // 출력 영상의 기억 장소에 대한 포인터 변수 int imageWidth; // 영상의 가로 크기 int imageHeight; // 영상의 세로 크기 int depth; // 1 = 흑백 영상, 3 = 컬러 영상 2019-02-18

PGM과 PPM 파일 형식 읽기 입력 영상 저장을 위한 포인터 변수 초기화 기억 장소를 할당했는지의 여부 확인을 위해 사용 CImageProDoc::CImageProDoc(void) { // TODO: add one-time construction code here inputImg = NULL; inputImg2 = NULL; resultImg = NULL; } 2019-02-18

PGM과 PPM 파일 형식 읽기 Serialize() 함수 수정 void CImageProDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) } else LoadImageFile(ar); 2019-02-18

PGM과 PPM 파일 형식 읽기 LoadImageFile() 함수를 CImageProDoc 클래스에 추가 반환 형식: void 함수 이름: LoadImageFile 매개변수 형식 : CArchive& 매개변수 이름 : ar 매개변수 이름과 형식을 입력한 다음 추가 버튼 선택 2019-02-18

PGM과 PPM 파일 형식 읽기 추가된 매개변수가 매개변수목록에 나타남 2019-02-18

PGM과 PPM 파일 형식 읽기 LoadImageFile() 함수의 내용을 편집 void CImageProDoc::LoadImageFile(CArchive &ar) { int i, maxValue; CString type, buf; CFile *fp = ar.GetFile(); CString fname = fp->GetFilePath(); // 파일의 헤더 읽기 if (strcmp(strrchr(fname, '.'), ".ppm") == 0 || strcmp(strrchr(fname, '.'), ".PPM") == 0 || strcmp(strrchr(fname, '.'), ".PGM") == 0 || strcmp(strrchr(fname, '.'), ".pgm") == 0 ) ar.ReadString(type, 15); 2019-02-18

PGM과 PPM 파일 형식 읽기 do { ar.ReadString(buf, 255); } while (buf[0] == '#'); sscanf_s(buf, "%d %d", &imageWidth, &imageHeight); sscanf_s(buf, "%d", &maxValue); if (strcmp(type, "P5") == 0) depth = 1; else depth = 3; } 2019-02-18

PGM과 PPM 파일 형식 읽기 else if (strcmp(strrchr(fname, '.'), ".raw") == 0 || { if (fp->GetLength() != 256 * 256) { AfxMessageBox("256x256 크기의 파일만 사용가능합니다."); return; } imageWidth = 256; imageHeight = 256; depth = 1; 2019-02-18

PGM과 PPM 파일 형식 읽기 // 기억장소 할당 inputImg = (unsigned char **) malloc(imageHeight * sizeof(unsigned char *)); resultImg = (unsigned char **) malloc(imageHeight * sizeof(unsigned char *)); for (i = 0; i < imageHeight; i++) { inputImg[i] = (unsigned char *) malloc(imageWidth * depth); resultImg[i] = (unsigned char *) malloc(imageWidth * depth); } // 영상 데이터 읽기 for (i = 0; i < imageHeight; i++) ar.Read(inputImg[i], imageWidth*depth); 2019-02-18

PGM과 PPM 파일 형식 읽기 OnDraw() 함수 수정 void CImageProView::OnDraw(CDC* pDC) { CImageProDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (pDoc->inputImg == NULL) return; // 입력 영상이 읽히지 않았으면 종료 if (pDoc->depth == 1) { // 흑백 영상 출력 for(int y=0; y < pDoc->imageHeight; y++) // 입력 영상 출력 for(int x=0; x < pDoc->imageWidth; x++) pDC->SetPixel(x, y, RGB(pDoc->inputImg[y][x], pDoc->inputImg[y][x], pDoc->inputImg[y][x])); 2019-02-18

PGM과 PPM 파일 형식 읽기 if (viewMode == THREE_IMAGES) { for(int y=0; y< pDoc->imageHeight; y++) // 두번째 입력 영상 출력 for(int x=0; x< pDoc->imageWidth; x++) pDC->SetPixel(x+pDoc->imageWidth+30,y, RGB(pDoc->inputImg2[y][x], pDoc->inputImg2[y][x], pDoc->inputImg2[y][x])); for(int y=0; y< pDoc->imageHeight; y++) // 결과 영상 출력 pDC->SetPixel(x+pDoc->imageWidth*2+60,y, RGB(pDoc->resultImg[y][x], pDoc->resultImg[y][x], pDoc->resultImg[y][x])); } 2019-02-18

PGM과 PPM 파일 형식 읽기 else { for(int y=0; y< pDoc->imageHeight; y++) // 결과 영상 출력 for(int x=0; x< pDoc->imageWidth; x++) pDC->SetPixel(x+pDoc->imageWidth+30,y, RGB(pDoc->resultImg[y][x], pDoc->resultImg[y][x], pDoc->resultImg[y][x])); } else if (pDoc->depth == 3) { // 컬러 영상 출력 for(int y=0; y < pDoc->imageHeight; y++) // 입력 영상 출력 for(int x=0; x < pDoc->imageWidth; x++) pDC->SetPixel(x, y, RGB(pDoc->inputImg[y][3*x], pDoc->inputImg[y][3*x+1], pDoc->inputImg[y][3*x+2])); 2019-02-18

PGM과 PPM 파일 형식 읽기 if (viewMode == THREE_IMAGES) { for(int y=0; y< pDoc->imageHeight; y++) // 두번째 입력 영상 출력 for(int x=0; x< pDoc->imageWidth; x++) pDC->SetPixel(x+pDoc->imageWidth+30,y, RGB(pDoc->inputImg2[y][3*x], pDoc->inputImg2[y][3*x+1], pDoc->inputImg2[y][3*x+2])); for(int y=0; y< pDoc->imageHeight; y++) // 결과 영상 출력 pDC->SetPixel(x+pDoc->imageWidth*2+60,y, RGB(pDoc->resultImg[y][3*x], pDoc->resultImg[y][3*x+1], pDoc->resultImg[y][3*x+2])); } 2019-02-18

PGM과 PPM 파일 형식 읽기 else { for(int y=0; y< pDoc->imageHeight; y++) // 결과 영상 출력 for(int x=0; x< pDoc->imageWidth; x++) pDC->SetPixel(x+pDoc->imageWidth+30,y, RGB(pDoc->resultImg[y][3*x], pDoc->resultImg[y][3*x+1], pDoc->resultImg[y][3*x+2])); } 2019-02-18

PGM과 PPM 파일 형식 읽기 프로그램을 컴파일하고 실행한 다음에 “로켓발사.pgm" 파일 열기 실행 2019-02-18

임의의 크기 영상에 대한 픽셀 단위 처리 실습

산술 덧셈 연산 수정 OnPixelAdd() 함수 수정 입력 영상을 읽어 들였는 지 검사할 필요가 있음 void CImageProView::OnPixelAdd(void) { CImageProDoc* pDoc; // 문장 1 : pDoc 변수 선언 pDoc = GetDocument(); // 문장 2 : 문서 객체에 대한 포인터 획득 ASSERT_VALID(pDoc); // 문장 3 : pDoc 변수의 오류 검증 if (pDoc->inputImg == NULL) return; // 추가된 문장: 입력 영상이 있는지 검사 pDoc->PixelAdd(); // 문장 4 : 문서 객체의 PointAdd() 함수 호출 viewMode = TWO_IMAGES; // 문장 5 : 연산의 종류 설정 Invalidate(FALSE); // 문장 6 : 화면을 다시 그림 } 2019-02-18

산술 덧셈 연산 수정 PixelAdd() 함수 수정 영상의 크기 수정 void CImageProDoc::PixelAdd(void) { int value=0; for(int y=0; y < imageHeight; y++) for(int x=0; x < imageWidth * depth; x++) { value = inputImg[y][x]+100; if(value > 255) resultImg[y][x] = 255; else resultImg[y][x]=value; } 2019-02-18

산술 덧셈 연산 수정 “로켓발사.pgm” 파일을 열어서 산술 덧셈 연산 실행 2019-02-18

두영상의 산술 덧셈 수정 두 영상을 읽어들이는 함수 LoadTwoImages() 함수 수정 void CImageProDoc::LoadTwoImages(void) { CFile file; CFileDialog dlg(TRUE); AfxMessageBox("Select the First Image"); if(dlg.DoModal()==IDOK) { file.Open(dlg.GetPathName(), CFile::modeRead); CArchive ar(&file, CArchive::load); LoadImageFile(ar); file.Close(); } 2019-02-18

두영상의 산술 덧셈 수정 AfxMessageBox("Select the Second Image"); if(dlg.DoModal()==IDOK) { file.Open(dlg.GetPathName(), CFile::modeRead); CArchive ar(&file, CArchive::load); LoadSecondImageFile(ar); file.Close(); } 2019-02-18

두영상의 산술 덧셈 수정 CImageProDoc 클래스에 LoadSecondImageFile() 함수 추가 - 반환 형식: void 함수 이름: LoadSecondImageFile 매개변수형식 : CArchive& 매개변수이름 : ar 2019-02-18

두영상의 산술 덧셈 수정 LoadSecondImageFile() 함수을 다음과 같이 편집 void CImageProDoc::LoadSecondImageFile(CArchive &ar) { int i, maxValue; CString type, buf; CFile *fp = ar.GetFile(); CString fname = fp->GetFilePath(); // 파일의 헤더 읽기 if (strcmp(strrchr(fname, '.'), ".ppm") == 0 || strcmp(strrchr(fname, '.'), ".PPM") == 0 || strcmp(strrchr(fname, '.'), ".PGM") == 0 || strcmp(strrchr(fname, '.'), ".pgm") == 0 ) ar.ReadString(type, 15); 2019-02-18

두영상의 산술 덧셈 수정 do { ar.ReadString(buf, 255); } while (buf[0] == '#'); sscanf_s(buf, "%d %d", &imageWidth, &imageHeight); sscanf_s(buf, "%d", &maxValue); if (strcmp(type, "P5") == 0) depth = 1; else depth = 3; } else if (strcmp(strrchr(fname, '.'), ".raw") == 0 || strcmp(strrchr(fname, '.'), ".RAW") == 0 ) { if (fp->GetLength() != 256 * 256) { AfxMessageBox("256x256 크기의 파일만 사용가능합니다."); return; 2019-02-18

두영상의 산술 덧셈 수정 imageWidth = 256; imageHeight = 256; depth = 1; } // 기억장소 할당 inputImg2 = (unsigned char **) malloc(imageHeight * sizeof(unsigned char *)); for (i = 0; i < imageHeight; i++) { inputImg2[i] = (unsigned char *) malloc(imageWidth * depth); // 영상 데이터 읽기 for (i = 0; i < imageHeight; i++) ar.Read(inputImg2[i], imageWidth*depth); 2019-02-18

두영상의 산술 덧셈 수정 PixelTwoImageAdd() 함수의 내용을 다음과 같이 수정 void CImageProDoc::PixelTwoImageAdd(void) { int value = 0; LoadTwoImages(); for(int y=0; y<imageHeight; y++) for(int x=0; x < imageWidth * depth; x++) { value = inputImg[y][x] + inputImg2[y][x]; if (value > 255) resultImg[y][x] = 255; else resultImg[y][x] = value; } 2019-02-18

두영상의 산술 덧셈 수정 “모나리자.pgm" 파일과 "모나리자-mask.pgm" 파일을 이용하여 두 영상의 산술 덧셈 연산을 수행하여 그림과 같은 결과가 나타나는지 확인 2019-02-18

영상의 선명화 실습

영상의 선명화 메뉴 막대에 [영역 처리] 메뉴 추가 부메뉴 추가 이름 : 선명화 ID : ID_REGION_SHARPENING 2019-02-18

영상의 선명화 메뉴에 대한 이벤트 처리기를 OnRegionSharpening() 함수로 추가하고 다음과 같이 편집 void CImageProView::OnRegionSharpening() { CImageProDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (pDoc->inputImg == NULL) return; pDoc->RegionSharpening(); viewMode = TWO_IMAGES; Invalidate(FALSE); } 2019-02-18

영상의 선명화 CImageProDoc 클래스에 RegionSharpening() 함수 추가 반환 형식: void 2019-02-18

영상의 선명화 RegionSharpening() 함수의 내용을 다음과 같이 편집 void CImageProDoc::RegionSharpening(void) { float kernel[3][3] = {{0, -1, 0}, {-1, 5, -1}, {0, -1, 0}}; Convolve(inputImg, resultImg, imageWidth, imageHeight, kernel, 0, depth); } 2019-02-18

영상의 선명화 CImageProDoc 클래스에 Convolve() 함수 추가 반환 형식: void 함수 이름: Convolve 매개변수 번호 매개 변수 형식 매개 변수 이름 1 unsigned char ** inputImg 2 resultImg 3 int cols 4 rows 5 float [][3] mask 6 bias 7 depth 2019-02-18

영상의 선명화 Convolve() 함수 편집 void CImageProDoc::Convolve(unsigned char **inputImg, unsigned char **resultImg, int cols, int rows, float mask[][3], int bias, int depth) { int i, j, x, y; int red, green, blue; int sum; unsigned char **tmpImg; // 기억장소 할당 tmpImg = (unsigned char **) malloc((imageHeight + 2)* sizeof(unsigned char *)); for (i = 0; i < imageHeight + 2; i++) tmpImg[i] = (unsigned char *) malloc((imageWidth + 2) * depth); 2019-02-18

영상의 선명화 // 0-삽입을 위해 0으로 초기화 for (y = 0; y < imageHeight + 2; y++) for (x = 0; x < (imageWidth + 2) * depth; x++) tmpImg[y][x] = 0; // 영상 복사 for (y = 1; y < imageHeight + 1; y++) for (x = 1; x < imageWidth + 1; x++) if (depth == 1) tmpImg[y][x] = inputImg[y-1][x-1]; else if (depth == 3) { tmpImg[y][3*x] = inputImg[y-1][3*(x-1)]; tmpImg[y][3*x+1] = inputImg[y-1][3*(x-1)+1]; tmpImg[y][3*x+2] = inputImg[y-1][3*(x-1)+2]; } 2019-02-18

영상의 선명화 for (y=0; y < imageHeight; y++) for (x=0; x < imageWidth; x++) { if (depth == 1) { sum=0; for (i=0; i<3; i++) for (j=0; j<3; j++) sum += (int) (tmpImg[y+i][x+j] * mask[i][j]) ; sum = sum + bias; if (sum > 255) sum=255; if (sum < 0) sum = 0; resultImg[y][x] = (unsigned char) sum; } 2019-02-18

영상의 선명화 else if (depth == 3) { red = 0; green = 0; blue = 0; for (i=0; i<3; i++) for (j=0; j<3; j++) { red += (int) (tmpImg[y+i][3*(x+j)] * mask[i][j]); green += (int) (tmpImg[y+i][3*(x+j)+1] * mask[i][j]); blue += (int) (tmpImg[y+i][3*(x+j)+2] * mask[i][j]); } red = red + bias; green = green + bias; blue = blue + bias; 2019-02-18

영상의 선명화 if (red > 255) red = 255; if (red < 0) red = 0; if (green > 255) green = 255; if (green < 0) green = 0; if (blue > 255) blue = 255; if (blue < 0) blue = 0; resultImg[y][3*x] = (unsigned char) red; resultImg[y][3*x+1] = (unsigned char) green; resultImg[y][3*x+2] = (unsigned char) blue; } // 기억장소 반환 for (i = 0; i < imageHeight + 2; i++) free(tmpImg[i]); free(tmpImg); 2019-02-18

영상의 선명화 프로그램을 컴파일하고 실행해보자. “모나리자.pgm" 파일을 열은 다음에 [선명화] 메뉴를 선택 2019-02-18