05 장히스토그램을이용한화소점처리 디지털영상의히스토그램 산술연산을이용한히스토그램에서의이동 히스토그램스트레칭 히스토그램평활화 히스토그램명세화 한빛미디어 ( 주 )
학습목표 5 장. 히스토그램을이용한화소점처리 디지털영상의히스토그램을이해한다. 산술연산으로히스토그램에서명도와명암대비를조정하는방법을이해한다. 히스토그램스트레칭기법의원리와효과를학습한다. 히스토그램평활화의기본원리를익히고, 영상에서보이는효과를알아본다. 히스토그램명세화원리를익히고, 영상에서보이는효과를알아본다. 2
디지털영상의히스토그램 Section 01 디지털영상의히스토그램 관찰한데이터의특징을한눈에알아볼수있도록데이터를막대그래프모양으로나타낸것 디지털영상에대한많은정보를제공함. 3
영상의특성에따른히스토그램 4
RGB 컬러영상의히스토그램 5
Section 02 산술연산을이용한히스토그램이동 덧셈연산 : 명도값을증가시켜밝게, 히스토그램의기둥이오른쪽으로이동 뺄셈연산 : 명도값을감소시켜어둡게, 히스토그램의기둥이왼쪽으로이동 6
Section 02 산술연산을이용한히스토그램이동 ( 계속 ) 곱셈연산 : 명암대비가증가하여히스토그램은기둥의분포범위가넓음. 나눗셈연산 : 명암대비가감소하여히스토그램의분포범위가좁음. 7
Section 03 히스토그램스트레칭 히스토그램스트레칭 (Histogram Stretching) 명암대비를향상시키는연산으로, 낮은명암대비를보이는영상의화질을향상시키는방법 명암대비스트레칭이라고도함. 히스토그램이모든범위의화소값을포함하도록히스토그램의분포를넓힘. 기본명암대비스트레칭과앤드 - 인탐색기법이대표적 8
기본명암대비스트레칭이상적이지못한히스토그램분포중에서명암대비가낮은디지털영상의품질을향상시키는기술특정부분이나가운데에집중된히스토그램을모든영역으로확장시켜서디지털영상이모든범위의화소값을포함하게함기본명암대비스트레칭수행공식 new pixel old pixel low high low 255 old pixel은원영상화소의명도값 new pixel은결과영상화소의명도값 low는히스토그램의최저명도값 high는히스토그램의최고명도값 9
기본명암대비스트레칭 ( 계속 ) 10
앤드-인탐색일정한양의화소를흰색이나검정색으로지정하여히스토그램의분포를좀더균일하게만듦앤드-인탐색수행공식 두개의임계값 (low, high) 사용 11
앤드 - 인탐색 ( 계속 ) 12
[ 실습하기 5-1] 히스토그램스트래칭의프로그램 1 ResourceView 창에서 [Menu]-[IDR_IMAGETYPE] 더블클릭 메뉴추가 2 [MFC ClassWizard] 대화상자를이용해추가된메뉴에서히스토그램스트레칭을실행하는함수추가 3 Doc 클래스에다음프로그램추가 13
[ 실습하기 5-1] 히스토그램스트래칭의프로그램 void CImageProcessingDoc::OnHistoStretch() { int i; unsigned char LOW, HIGH, MAX, MIN; m_re_height = m_height; m_re_width = m_width; m_re_size = m_re_height * m_re_width; LOW = 0; HIGH = 255; MIN = m_inputimage[0]; // 최소값을찾기위한초기값 MAX = m_inputimage[0]; // 최대값을찾기위한초기값 // 입력영상의최소값찾기 for(i=0 ; i<m_size ; i++){ if(m_inputimage[i] < MIN) MIN = m_inputimage[i]; // 입력영상의최대값찾기 for(i=0 ; i<m_size ; i++){ if(m_inputimage[i] > MAX) MAX = m_inputimage[i]; m_outputimage = new unsigned char[m_re_size]; // 히스토그램 stretch for(i=0 ; i<m_size ; i++) m_outputimage[i] = (unsigned char)((m_inputimage[i] - MIN)*HIGH / (MAX-MIN)); 14
[ 실습하기 5-1] 히스토그램스트래칭의프로그램 4 View 클래스에다음프로그램추가 void CImageProcessingView::OnHistoStretch() { CImageProcessingDoc* pdoc = GetDocument(); ASSERT_VALID(pDoc); pdoc->onhistostretch(); Invalidate(TRUE); 15
[ 실습하기 5-1] 히스토그램스트래칭의프로그램 5 프로그램실행결과영상 16
[ 실습하기03장 5-2]. 히스토그램앤드-인스트레칭탐색프로그램 1 ResourceView 창에서 [Menu]-[IDR_IMAGETYPE] 더블클릭 메뉴추가 2 [MFC ClassWizard] 대화상자를이용해추가된메뉴에서앤드 - 인탐색을실행하는함수추가 3 Doc 클래스에다음프로그램추가 17
[ 실습하기 5-2] 앤드 - 인탐색프로그램 void CImageProcessingDoc::OnEndInSearch() { int i; unsigned char LOW, HIGH, MAX, MIN; m_re_height = m_height; m_re_width = m_width; m_re_size = m_re_height * m_re_width; LOW = 0; HIGH = 255; MIN = m_inputimage[0]; MAX = m_inputimage[0]; for(i=0 ; i<m_size ; i++){ if(m_inputimage[i] < MIN) MIN = m_inputimage[i]; for(i=0 ; i<m_size ; i++){ if(m_inputimage[i] > MAX) MAX = m_inputimage[i]; m_outputimage = new unsigned char[m_re_size]; 18
[ 실습하기 5-2] 앤드 - 인탐색프로그램 for(i=0 ; i<m_size ; i++){ // 원본영상의최소값보다작은값은 0 if(m_inputimage[i] <= MIN){ m_outputimage[i] = 0; // 원본영상의최대값보다큰값은 255 else if(m_inputimage[i] >= MAX){ m_outputimage[i] = 255; else m_outputimage[i] = (unsigned char)((m_inputimage[i] - MIN)*HIGH / (MAX-MIN)); 19
[ 실습하기 5-2] 앤드 - 인탐색프로그램 4 View 클래스에다음프로그램추가 void CImageProcessingView::OnEndInSearch() { CImageProcessingDoc* pdoc = GetDocument(); ASSERT_VALID(pDoc); pdoc->onendinsearch(); Invalidate(TRUE); 20
5 프로그램실행결과영상 [ 실습하기 5-2] 앤드 - 인탐색프로그램 21
Section 04. 히스토그램평활화 히스토그램평활화기법 (Histogram Equalized) 어둡게촬영된영상의히스토그램을조절하여명암분포가빈약한영상을균일하게만들어줌. 영상의밝기분포를재분배하여명암대비를최대화 명암대비조정을자동으로수행 각명암의빈도는변경하지않음. 검출특성이좋은영상만출력하지는않지만영상의검출특성을증가시킴 22
히스토그램평활화의 3 단계 1 단계 2 단계 3 단계 명암값 j 의빈도수 hist[j] 를계산해입력영상의히스토그램생성 각명암값 i 에서 0~i 까지의누적빈도수 ( 누적합 ) 를계산 sum[ i] i j 0 hist[ 2 단계에서구한누적빈도수를정규화 ( 정규화누적합 ) j] 1 n[ i] sum[ i] I N max N 은화소의총수, Imax 는최대명도값 3 단계에서얻은정규화된값 n[i] 로입력영상의화소값 i 를변환하면평활화된결과영상생성 23
1 단계 히스토그램평활화 _1 단계 빈도수 hist[j] 에서의히스토그램생성 화소의명도값 0 은 2 개, 1 은 5 개, 2 는 4 개, 3 은 3 개, 4 는 2 개 가장큰명도값이 4 이므로전체적으로왼쪽으로치우침. 24
2 단계누적합 sum[i] 생성 히스토그램평활화 _2 단계 화소의명도 0 번까지의누적합은 2, 1 번까지는 2+5=7, 2 번까지는 2+5+4=11, 3 번까지는 2+5+4+3=14, 4 번까지는 2+5+4+3+2=16 나머지명도값은영상에는없으므로누적합은 16 25
3 단계 n[i]=sum[i]*(1/16)*7 히스토그램평활화 _3 단계 n[0] 은 2*(1/16)*7=0.875, n[1] 은 7*(1/16)*7=3.0625 n[2] 는 11*(1/16)*7=4.8125, n[3] 은 14*(1/16)*7=6.125 n[4] 와 n[5], n[6], n[7] 은 16*(1/16)*7=7 26
히스토그램평활화를적용한영상 27
히스토그램평활화를적용한영상 ( 계속 ) 28
[ 실습하기 5-3] 히스토그램프로그램 1 ResourceView 창에서 [Menu]-[IDR_IMAGETYPE] 더블클릭 메뉴추가 2 [MFC ClassWizard] 대화상자를이용해추가된메뉴에서히스토그램을실행하는함수추가 3 히스토그램에서사용할전역변수를선언. 변수를전역으로선언하여히스토그램과히스토그램평활화에서공유 double m_hist[256]; double m_sum_of_hist[256]; unsigned char m_scale_hist[256]; 29
4 View 클래스에다음프로그램추가 [ 실습하기 5-3] 히스토그램프로그램 void CImageProcessingDoc::OnHistogram() { // 히스토그램의값은 0~255 // 히스토그램의크기값을 MAX=255로정규화하여출력 // 히스트그램의크기 : 256*256 지정 int i, j, value; unsigned char LOW, HIGH; double MAX, MIN, DIF; m_re_height = 256; m_re_width = 256; m_re_size = m_re_height * m_re_width; LOW = 0; HIGH = 255; // 초기화 for(i=0 ; i<256 ; i++) m_hist[i] = LOW; // 빈도수조사 for(i=0 ; i<m_size ; i++){ value = (int)m_inputimage[i]; m_hist[value]++; // 정규화 MAX = m_hist[0]; MIN = m_hist[0]; for(i=0 ; i<256 ; i++){ if(m_hist[i] > MAX) MAX = m_hist[i]; for(i=0 ; i<256 ; i++){ if(m_hist[i] < MIN) MIN = m_hist[i]; 30
[ 실습하기 5-3] 히스토그램프로그램 4DIF View = MAX 클래스에 - MIN; 다음프로그램추가 // 정규화된히스토그램 for(i=0 ; i<256 ; i++) m_scale_hist[i] = (unsigned char)((m_hist[i] - MIN) * HIGH / DIF); // 정규화된히스토그램출력 m_outputimage = new unsigned char [m_re_size + (256*20)]; for(i=0 ; i<m_re_size ; i++) m_outputimage[i] = 255; // 정규화된히스토그램의값은출력배열에검은점 (0) 으로표현 for(i=0 ; i<256 ; i++){ for(j = 0 ; j<m_scale_hist[i] ; j++){ m_outputimage[m_re_width*(m_re_height-j-1) + i] = 0; // 히스토그램을출력하고그아래부분에히스토그램의색을표시 for(i = m_re_height ; i<m_re_height + 5 ; i++){ for(j=0 ; j<256 ; j++){ m_outputimage[m_re_height * i + j] = 255; for(i = m_re_height+5 ; i<m_re_height + 20 ; i++){ for(j=0 ; j<256 ; j++){ m_outputimage[m_re_height * i + j] = j; m_re_height = m_re_height + 20; m_re_size = m_re_height * m_re_width; 31
4 View 클래스에다음프로그램추가 [ 실습하기 5-3] 히스토그램프로그램 void CImageProcessingView::OnHistogram() { CImageProcessingDoc*pDoc = GetDocument(); ASSERT_VALID(pDoc); pdoc->onhistogram(); Invalidate(TRUE); 32
5 프로그램실행결과영상 [ 실습하기 5-3] 히스토그램프로그램 33
[ 실습하기 5-4] 히스토그램평활화프로그램 1 ResourceView 창에서 [Menu]-[IDR_IMAGETYPE] 더블클릭 메뉴추가 2 [MFC ClassWizard] 대화상자를이용해추가된메뉴에서히스토그램평활화를실행하는함수추가 3 Doc 클래스에다음프로그램추가 34
[ 실습하기 5-4] 히스토그램평활화프로그램 void CImageProcessingDoc::OnHistoEqual() { int i, value; unsigned char LOW, HIGH, Temp; double SUM = 0.0; m_re_height = m_height; m_re_width = m_width; m_re_size = m_re_height * m_re_width; LOW = 0; HIGH = 255; // 초기화 for(i=0 ; i<256 ; i++) m_hist[i] = LOW; // 빈도수조사 for(i=0 ; i<m_size ; i++){ value = (int)m_inputimage[i]; m_hist[value]++; // 누적히스토그램생성 for(i=0 ; i<256 ; i++){ SUM += m_hist[i]; m_sum_of_hist[i] = SUM; m_outputimage = new unsigned char[m_re_size]; // 입력영상을평활화된영상으로출력 for(i=0 ; i<m_size ; i++){ Temp = m_inputimage[i]; m_outputimage[i]=(unsigned char)(m_sum_of_ HIST[Temp]*HIGH/m_size); 35
[ 실습하기 5-4] 히스토그램평활화프로그램 4 View 클래스에다음프로그램추가 void CImageProcessingView::OnHistoEqual() { CImageProcessingDoc* pdoc = GetDocument(); ASSERT_VALID(pDoc); pdoc->onhistoequal(); 4 Invalidate(TRUE); View 클래스에다음프로그램추가 36
5 프로그램실행결과영상 [ 실습하기 5-4] 히스토그램평활화프로그램 37
Section 05 히스토그램명세화히스토그램명세화 (Histogram Specification) 특정모양의히스토그램을생성된디지털영상의히스토그램에포함하여영상의일부영역의명암대비 ( 콘트라스트 ) 를개선할수있는데, 이런영상처리기법입력영상의히스토그램을원하는히스토그램으로변환한다고해서히스토그램정합 (Histogram Matching) 기법명암대비를개선하는것은히스토그램평활화와같지만특정부분을향상시키려고원하는히스토그램을이용한정합으로일부영역에서만명암대비를개선한다는점이다름. 기본적으로입력영상을원하는히스토그램으로평활화하고역히스토그램평활화수행 룩업테이블 (lookup table) 을생성하고평활화된원영상을역변환하여원하는히스토그램을얻음. 38
히스토그램명세화개념 39
1 단계 2 단계 3 단계 히스토그램명세화과정 입력디지털영상의히스토그램생성 입력디지털영상의히스토그램을평활화하려고정규화된누적빈도수의함수를구한뒤다음변환식을얻음. q = T(P) P 는원영상의화소값, q 는평활화값 변환식를바탕으로평활화를수행하여균일분포된히스토그램을얻음. 원하는히스토그램의정규화된누적빈도수함수를구하고, 역변환함수가있는변환식을구한뒤평활화수행 v = G(Z) Z 는원하는히스토그램의명도값, v 는평활화값 40
4 단계 5 단계 히스토그램명세화과정 ( 계속 ) 평활화된원하는히스토그램을역평활화하여역변환함수를구함. 여기서역변환함수는실제룩업테이블이됨 Z = G-1(v) 4 단계에서구한역변환함수를이용하여평활화된원영상의히스토그램을원하는히스토그램이있는영상으로만듦. Z = G-1(v) Z = G-1(q) = G-1[T(P)] 최초의입력영상은원하는히스토그램이아니지만평활화되어균일하게분포. 따라서역변환함수는평활화되어균일하게분포된입력영상도원하는히스토그램으로만들어줌. 41
히스토그램명세화 _1 단계 1 단계 히스토그램생성 42
2 단계 입력영상의평활화 히스토그램명세화 _2 단계 43
3 단계 히스토그램명세화 _3 단계 원하는히스토그램을평활화하여분포가균일한히스토그램을만듦. 44
4 단계 히스토그램명세화 _4 단계 평활화된히스토그램을역평활화하는과정 평활화와반대로정규화된누적합이명도값이되고, 명도값은역평활화값이됨. 역평활화값이역함수로서룩업테이블로사용됨. 45
5 단계 히스토그램명세화 _5 단계 역변환함수를이용해입력영상을원하는히스토그램으로만들어줌. 46
히스토그램명세화 _5 단계 ( 계속 ) 47
[ 실습하기 5-5] 히스토그램명세화프로그램 1 ResourceView 창에서 [Menu]-[IDR_IMAGETYPE] 더블클릭 메뉴추가 2 [MFC ClassWizard] 대화상자를이용해추가된메뉴에서히스토그램명세화를실행하는함수추가 3 Doc 클래스에다음프로그램추가 48
[ 실습하기 5-5] 히스토그램명세화프로그램 void CImageProcessingDoc::OnHistoSpec() { int i, value, Dvalue, top, bottom, DADD; unsigned char *m_dtemp, m_sum_of_schist[256], m_table[256]; unsigned char LOW, HIGH, Temp, *m_org_temp; double m_dhist[256], m_sum_of_dhist[256], SUM = 0.0, DSUM = 0.0; double DMAX, DMIN; top = 255; bottom = top - 1; m_re_height = m_height; m_re_width = m_width; m_re_size = m_re_height * m_re_width; m_outputimage = new unsigned char [m_re_size]; m_org_temp = new unsigned char [m_size]; CFile File; CFileDialog OpenDlg(TRUE); 49
[ 실습하기 5-5] 히스토그램명세화프로그램 // 원하는히스토그램이있는영상을입력받음 if(opendlg.domodal() == IDOK){ File.Open(OpenDlg.GetFileName(), CFile::modeRead); if(file.getlength() == (unsigned)m_size){ m_dtemp = new unsigned char[m_size]; File.Read(m_DTEMP, m_size); File.Close(); else{ AfxMessageBox("Image size not matched"); // 같은크기의영상을대상으로함 return; LOW = 0; HIGH = 255; // 초기화 for(i=0 ; i<256 ; i++){ m_hist[i] = LOW; m_dhist[i] = LOW; m_table[i] = LOW; 50
[ 실습하기 5-5] 히스토그램명세화프로그램 // 빈도수조사 for(i=0 ; i<m_size ; i++){ value = (int)m_inputimage[i]; m_hist[value]++; Dvalue = (int)m_dtemp[i]; m_dhist[dvalue]++; // 누적히스토그램조사 for(i=0 ; i<256 ; i++){ SUM += m_hist[i]; m_sum_of_hist[i] = SUM; DSUM += m_dhist[i]; m_sum_of_dhist[i] = DSUM; // 원본영상의평활화 for(i=0 ; i<m_size ; i++){ Temp = m_inputimage[i]; m_org_temp[i]=(unsigned char)(m_sum_of_hist[temp]*high/m_size); // 누적히스토그램에서최소값과최대값지정 DMIN = m_sum_of_dhist[0]; DMAX = m_sum_of_dhist[255]; 51
[ 실습하기 5-5] 히스토그램명세화프로그램 // 원하는영상을평활화 for(i=0 ; i<256 ; i++){ m_sum_of_schist[i]=(unsigned char)((m_sum_of_dhist[i] -DMIN)*HIGH/(DMAX - DMIN)); // 룩업테이블을이용한명세화 for( ; ; ){ for(i=m_sum_of_schist[bottom] ; i <= m_sum_of_schist [top] ; i++){ m_table[i] = top; top = bottom; bottom = bottom - 1; if(bottom < -1) break; for(i=0 ; i<m_size ; i++){ DADD = (int)m_org_temp[i]; m_outputimage[i] = m_table[dadd]; 52
[ 실습하기 5-5] 히스토그램명세화프로그램 4 View 클래스에다음프로그램추가 void CImageProcessingView::OnHistoSpec { CImageProcessingDoc* pdoc = GetDocument(); ASSERT_VALID(pDoc); pdoc->onhistospec Invalidate(TRUE); 53
5 프로그램실행결과영상 [ 실습하기 5-5] 히스토그램명세화프로그램 54
[ 실습하기 5-5] 히스토그램명세화프로그램 55
요약 RGB 컬러영상의히스토그램 각채널에서히스토그램을생성. R, G, B 채널에는채널별로각각히스토그램이있음. 디지털영상에서산술연산 : 히스토그램의기둥을왼쪽, 오른쪽으로이동시키거나기둥의폭을조절함 덧셈연산 : 히스토그램의기둥을오른쪽으로이동시킴. 뺄셈연산 : 히스토그램의기둥을왼쪽으로이동시킴. 곱셈연산 : 수행한영상의히스토그램은기둥의분포가넓음나눗셈연산 : 최대명도값과최소명도값의차이가작아져명암대비가감소하고히스토그램의분포도좁음. 히스토그램스트레칭 명암대비를향상시키는연산으로, 낮은명암대비를보이는영상의품질을향상시키는기법명암대비스트레칭이라고도함. 히스토그램스트레칭을수행한디지털영상은모든범위의화소값을포함하며, 히스토그램은이상적인형태인전구간에걸쳐분포가균일 56
요약 엔드 - 인 (end-in) 탐색기법 히스토그램이전구간에분포하지만특정부분에집중되며, 최저와최고의명도값부근은아주빈약한영상의품질을향상시킬수있음. 일정한양의화소를흰색또는검정색을갖도록지정하여히스토그램의분포를좀더균일하게함 히스토그램평활화기법 명암분포가빈약한영상을분포가균일한영상으로만듦. 즉, 개략적인모습은원영상히스토그램과유사하게하면서명암도의분포를좀더균일화하는작업특정모양의히스토그램을생성된디지털영상의히스토그램에포함하여영상의일부영역의명암대비 ( 콘트라스트 ) 를개선시키는기술 히스토그램명세화과정 기본적으로입력영상을원하는히스토그램으로평활화하고역히스토그램평활화를수행그런뒤룩업테이블 (lookup table) 을생성하고평활화된원영상을역변환하여원하는히스토그램을얻음. 57
Thank you