chapter 9 영상신호처리
DESCRIPTION
Chapter 9 영상신호처리. 학습목표. 이번 장에서 다루게 되는 내용은 다음과 같습니다. 이번 장의 학습 목표. 영상신호처리의 개요 공간영역 해석 주파수 영역 해석. 영상신호처리의 개요. 영상 함수 f(x,y) : 공간좌표 (x,y) 에서 f 의 값은 그 점에서 영상의 밝기 혹은 빛의 세기를 의미 좌표계의 원점이 영상의 왼쪽 위에 있고 , 수평 방향으로 x 축 , 수직 아래 방향으로 y 축인 좌표계를 쓰는 함수 f(x,y). 영상신호처리의 개요. - PowerPoint PPT PresentationTRANSCRIPT
Chapter 9
영상신호처리
이번 장에서 다루게 되는 내용은 다음과 같습니다 .
1) 영상신호처리의 개요
2) 공간영역 해석
3) 주파수 영역 해석
이번 장의 학습 목표
학습목표
영상신호처리의 개요
영상 함수 f(x,y) : 공간좌표 (x,y) 에서 f 의 값은 그 점에서 영상의 밝기 혹은 빛의 세기를 의미
좌표계의 원점이 영상의 왼쪽 위에 있고 , 수평 방향으로 x 축 , 수직 아래 방향으로 y 축인 좌표계를 쓰는 함수 f(x,y)
영상신호처리의 개요
영상 함수 f(x,y) 는 표본화와 양자화 과정을 거쳐 수치 데이터 , 또는 디지털 영상으로 바꾸어지며 , 이 과정에 사용되는 장치가 아날로그 디지털 변환기 (ADC) 이며 , 특히 디지털 영상으로 바꾸는데 사용하는 ADC 를 프레임 그래버 (frame grabber) 라 함 .
영상신호처리의 개요
디지털 영상신호처리 : 영상을 카메라나 스캐너 등을 통하여 디지털화 한
후 , 여러 가지 목적에 따라 컴퓨터와 여러가지 알고리즘을 적용하여
처리하는 것
영상처리 분야
영상조작 획득 또는 전송된 영상데이터가 흐린 경우 , 왜곡된 경우 등 수많은 상황에서 원하는
영상을 얻기 위해 조작을 하는 것 .
영상분석 영상조작에 의해 보정된 영상 내부의 특징을 찾아내는 것
영상인식 영상물을 비교하여 다른 영상과 비교 , 분석하며 특징을 찾아 영상을 인식할 수 있도록
하는 분야
영상 통신 등 영상을 전송함에 있어서 어떻게 효율적으로 전송할 것인가를 연구하는 분야
공간영역 해석
일반적으로 영상의 공간영역 해석은 컨볼루션 연산을 통해 수행됨 출력 화소의 값은 이웃 화소들의 가중치의 합으로 계산 , 가중치
행렬은 2 차원 임펄스 응답으로 생각할 수 있음 . 가중치 행렬 =“마스크”라는 용어를 사용
공간영역 해석
마스크는 영상 안에서 일정 부분에 위치시키기 위한 일종의 행렬 모양의 구조체
주로 3x3, 5x5, 16x16 등과 같은 정방 행렬을 많이 사용 .
마스크를 이용한 연산 방법
마스크를 이용한 컨볼루션은 원 영상에 마스크를 겹쳐서 왼쪽부터 오른쪽으로 위에서 아래 방향으로 진행하면서 계산된 값을 (0,0) 자리에 다시 할당함으로서 출력 영상을 얻음 .
연산방법
마스크를 이용한 연산 방법
컨볼루션 마스크의 각 원소의 합은 결과 영상 , 혹은 출력 영상의 전체 밝기에 영향을 미치기 때문에 많은 컨볼루션 마스크의 원소의 합을 1 이 되도록 가중치를 정하고 있다 . 이 경우 출력 영상은 입력 영상과 같은 평균 밝기를 갖게 됨 .
윤곽선 검출에 사용되는 컨볼루션 마스크는 음의 계수를 포함하며 , 모든 원소의 합이 0 이 되는 경우가 있음 . 이 경우 음의 출력 화소값이 나올 수 있다 . 보통 상수값을 출력 화소값에 더하고 , 더해도 음이 되는 경우에는 출력 화소값을 0 으로 놓음 .
영상을 평활화 (smoothing) 하거나 노이즈를 제거하거나 , 윤곽 정보를 추출하는 등의 마스크가 사용
널리 사용되는 마스크의 형태
마스크의 종류
컨볼루션을 이용한 필터링
저주파 영역 : 빛의 세기가 천천히 변하는 영역 그림 9-6 의 (a), (b) 는 저주파 필터
고주파 영역 : 빛의 세기가 갑자기 바뀌는 물체의 경계나 무늬가 세밀한 영역 그림 9-6 의 (a), (b) 를 제외한 나머지는 고주파 필터
실습 9-1
실습 9-2
실습 9-2
실습 9-3
실습 9-3
실습 9-4
실습 9-4
영상 필터링을 위한 FFT
2 차원 퓨리에 변환 퓨리에 변환과 역변환
FFT 의 분해 성질
1
0
1
0
)(2
2
1
0
1
0
)(2
2
),(1
),(
),(1
),(
N
k
N
l
N
jlikj
N
i
N
i
N
jlikj
elkFN
jif
ejifN
lkF
행 FFT 열 FFT 2D FFT
+ =
FFT 의 기본 성질
스크램블링 동작 ( 역순서 비트 )
N=8 인 경우 입력의 순서가 0,4,2,6,1,5,3,7 과 같이 순서가 바뀌어야하는데 이를 스크램블링 동작이라 한다 .
FFT 의 기본 성질
8 점 FFT 를 실행 시 : 입력 수열의 순서가 데이터 수열의 순서와 다름 .
∴ FFT 실행시 원래의 입력 데이터의 순서를 바꾸어 주어야 함 . 즉 데이터 수열이 저장된 이진 비트 주소를 역으로 바꾸어 사용하면
됨 .
역순서 비트 (bit reverse)
FFT 의 기본 성질
나비선도
나비 선도
※ 위상인자를 의 거듭제곱으로 표시 .NW
주파수 영역에서의 필터링
주파수 영역 필터링
영상의 푸리에 변환을 구한다 .
마스크 함수의 푸리에 변환을 구한다 .
두 변환의 원소끼리 곱한다 .
곱의 결과를 역푸리에 변환을 수행한다 .
실습 9-5
실습 9-5
실습 9-6
실습 9-6
버터워스 (Butterworth) 필터를 이용한 영상 필터링
영상에서의 고주파는 값의 변화율이 큰 부분으로 주로 윤곽선 부분이며 저주파는 값의 변화가 적은 영상의 부분을 의미한다 .
주파수 필터링 개념도
Butterworth 저주파 필터
Butterworth 고주파 필터
원영상 필터링 필터링된영상
FFT IFFT
)(),( ,),(
1
1),( 22
2
0
vuvuD
DvuD
vuH n
여기서
)(),( ,
),(1
1),( 22
2
0
vuvuD
vuD
DvuH n
여기서
고속 퓨리에 변환 구현
리소스 편집기를 이용하여 팝업 메뉴를 주파수 해석을 생성후 서브 메뉴에 FFT 를 만듬
고속 퓨리에 변환 구현
만들어진 FFT 서브메뉴에 마우스 오른쪽 버튼을 눌러 클래스 마법사를 실행
<Add Function> 버튼을 눌러 CDSPTestView 클래스에 OnFFT()함수를 추가
고속 퓨리에 변환 구현
생성된 OnFFT() 함수를 다음과 같이 코딩
호출된 TwoD_FFT() 함수를 CDSPTestDoc 클래스에 생성
void CDSPTestView::OnFFT() {
// TODO: Add your command handler code hereCDSPTestDoc* pDoc=GetDocument();
ASSERT_VALID(pDoc); pDoc->TwoD_FFT();Invalidate(FALSE);
}
고속 퓨리에 변환 구현
생성된 TwoD_FFT() 함수를 다음과 같이 코딩한다 .
void CDSPTestDoc::TwoD_FFT(){
int index=0,i=0,j=0,k=0;COMPLEX col_data[256];COMPLEX row_data[256];
for(i=0; i<256; i++){col_data[i].re=0;col_data[i].im=0;row_data[i].re=0;row_data[i].im=0;for(j=0; j<256; j++){
complex_data[k+j].re=m_InImg[i][j];
complex_data[k+j].im=0;}k+=256;
}k=0;
고속 퓨리에 변환 구현
for(int y=0; y<256; y++){index=y*256;for(int x=0; x<256; x++){
row_data[x].re = complex_data[index].re;row_data[x].im = complex_data[index++].im;
}fft(row_data,8,256,1);
index=y*256;for(x=0; x<256; x++){
complex_data[index].re = row_data[x].re;complex_data[index++].im = row_data[x].im;
}}
고속 퓨리에 변환 구현
for(int x=0; x<256; x++){index=x;for(int y=0; y<256; y++){
col_data[y].re = complex_data[index].re;col_data[y].im = complex_data[index].im;index += 256;
}fft(col_data,8,256,1);
index=x;for(y=0; y<256; y++){
complex_data[index].re = col_data[y].re;complex_data[index].im = col_data[y].im;index += 256;
}}
고속 퓨리에 변환 구현
//resultfor(i=0; i<256; i++){
for(j=0; j<256; j++){m_OutImg[i]
[j]=20*log(1+abs(complex_data[k+j].re));if(m_OutImg[i][j]>=170)m_OutImg[i][j]=255;else m_OutImg[i][j]=0;
}k+=256;
}fftview();
} 다큐먼트 클래스의 헤더파일에
#define PI 3.141592Typedef struct {float re, im;} COMPLEX; #include <math.h> 를 추가한다 .
다큐먼트 클래스에 다음의 변수를 추가COMPLEX complex_data[256*256]
고속 퓨리에 변환 구현
TwoD_FFT() 에서 호출한 1 차원 FFT 인 fft() 함수를 생성 및 코딩 .
void CDSPTestDoc::fft(COMPLEX *f, int logN, int numpoints, int dir){
scramble(numpoints,f);butterflies(numpoints,logN,dir,f);
}
고속 퓨리에 변환 구현
scramble(…) 와 butterflies(…) 를 다음과 같이 작성한다 .
void CTestDoc::scramble(int numpoints, COMPLEX *f){
int i,j,m; //loop variabledouble temp; //temporary storage during swapping
j=0;for(i=0;i<numpoints;i++) //numpoint 배열의 element 수{
if(i>j){
//swap realtemp=f[j].re;f[j].re=f[i].re;f[i].re=(float)temp;//swap imagenarytemp=f[j].im;f[j].im=f[i].im;f[i].im=(float)temp;
}m=numpoints>>1;while(( j >= m ) & ( m >= 2 )){
j -=m;m = m >> 1;
}j +=m;
}}
고속 퓨리에 변환 구현
void CTestDoc::butterflies(int numpoints, int logN, int dir, COMPLEX *f)
{double angle; //polar angleCOMPLEX w,wp,temp; //intermediate complex numbersint i,j,k,offset; //loop variablesint N,half_N; //storage for powers of 2double wtemp; //temporary storage for w.re
N=1;for(k=0; k<logN; k++){
half_N=N;N <<= 1;angle = -2.0 * PI / N * dir;wtemp = sin(0.5*angle);//wp.re = (float)sin(0.5*angle);// 변경 .wp.re = (float)(-2.0*wtemp*wtemp);
wp.im = (float)sin(angle);// 변경w.re = 1.0;w.im = 0.0;
고속 퓨리에 변환 구현
for(offset=0; offset<half_N; offset++){
for(i=offset; i<numpoints; i+=N){
j=i+half_N;temp.re = (w.re*f[j].re)-(w.im*f[j].im);temp.im = (w.im*f[j].re)+(w.re*f[j].im);f[j].re = f[i].re-temp.re;f[i].re += temp.re;f[j].im = f[i].im-temp.im;f[i].im += temp.im;
}wtemp = w.re;w.re = (float)(wtemp*wp.re-w.im*wp.im+w.re);// 변경 .w.im = (float)(w.im*wp.re+wtemp*wp.im+w.im);// 변경 .
}}if(dir == -1)
for(i=0;i<numpoints;i++){
f[i].re /= numpoints;f[i].im /= numpoints;
}}
고속 퓨리에 변환 구현
결과 영상의 중심에 저주파 중심으로 부터 먼 부분에는 고주파를 표시하기 위한 함수 fftview() 를 다음과 같이 코딩한다 .
void CDSPTestDoc::fftview(){
unsigned char fftview[256][256];//convertfor(int i=0; i<256; i+=128){
for(int j=0; j<256; j+=128){for(int row=0; row<128; row++){
for(int col=0; col<128; col++){fftview[127-row+i][127-col+j]=m_OutImg[i+row][j+col];
}}
}}
for(int y=0; y<256; y++){for(int x=0; x<256; x++){
m_OutImg[y][x]=fftview[y][x];}
}}
고속 퓨리에 변환 구현
실행결과
고속 퓨리에 역변환 구현
리소스 편집기를 이용하여 팝업 메뉴 주파수 해석 아래에 서브메뉴 IFFT 를 생성 만들어진 IFFT 서브메뉴에 마우스 오른쪽 버튼을 눌러 클래스 마법사를 선택
고속 퓨리에 역변환 구현
<Add Function> 버튼을 눌러 뷰클래스에 OnIFFT() 함수를 추가void CDSPTestView::OnIFFT() {
// TODO: Add your command handler code hereCDSPTestDoc* pDoc=GetDocument(); // 도큐먼트 클래스 참조ASSERT_VALID(pDoc); pDoc->TwoD_IFFT();Invalidate(FALSE);
} 호출된 TwoD_IFFT() 함수를 CDSPTestDoc 클래스에 생성후 코딩
고속 퓨리에 역변환 구현
void CDSPTestDoc::TwoD_IFFT(){
int index=0,i=0,j=0,k=0;COMPLEX col_data[256];COMPLEX row_data[256];
for(i=0; i<256; i++){col_data[i].re=0;col_data[i].im=0;row_data[i].re=0;row_data[i].im=0;
}
for(int y=0; y<256; y++){
index=y*256;for(int x=0; x<256; x++){
row_data[x].re = complex_data[index].re;row_data[x].im = complex_data[index++].im;
}fft(row_data,8,256,-1);
index=y*256;for(x=0; x<256; x++){
complex_data[index].re = row_data[x].re;complex_data[index++].im = row_data[x].im;
}}
고속 퓨리에 역변환 구현for(int x=0; x<256; x++){
index=x;for(int y=0; y<256; y++){
col_data[y].re = complex_data[index].re;col_data[y].im = complex_data[index].im;index += 256;
}fft(col_data,8,256,-1);
index=x;for(y=0; y<256; y++){
complex_data[index].re = col_data[y].re;complex_data[index].im = col_data[y].im;index += 256;
}}
for(i=0; i<256; i++){
for(j=0; j<256; j++){
if(complex_data[k+j].re>=255)m_OutImg[i][j]=255;
else if(complex_data[k+j].re<=0)m_OutImg[i][j]=0;
elsem_OutImg[i][j]=complex_data[k+j].re;
}k+=256;
}}
고속 퓨리에 역변환 구현
실행 결과 : FFT 를 실행하고 IFFT 를 실행하면 원영상이 복원됨을 알수 있음 .