회색계조 사상은 각 화소의 회색계조를 미리 정의된 변환 함수에 따라 새로운 값으로 바꾸는 점 연산이다.
연산 전후의 화소 값을 각각 라고 하며느 회색계조 변환함수 또는 사상 함수 를 써서
라고 쓸 수 있다.1) 밝기 변환
먼저 회색계조 사상의 예로는 모든 화소에 일정한 값을 더하거나 뺌으로 써 영상의 밝기를 바꾸는 경우가 있다.
만약 이면 영상이 밝아지고 이면 영상은 어두워 진다.
하지만 이처럼 영상에 상수 값을 더하거나 뺴면 전체 영상의 밝기는 조정할 수 있지만, 대비는 바꿀 수 없다.2) 반전 변환
반전변환은 255(gray level최대값)에서 해당 화소의 값을 빼어 만들어 음화를 만들어 내는 과정으로
위의 식을 통해 화소의 값을 반전시켜 음화로 만든다.3) 로그 변환
로그 변환은 는 상수 일 때, 입력영상의 어두운 부분의 대비는 높이고 밝은 부분의 대비는 낮추면서 영상을 전체적으로 밝게 만들어낸다.
4) 지수 변환
로그 변환과는 반대로 지수변환은 밝은 부분의 대비를 높일 때 유용하다.
으로 이때, n의 값을 조절하면, 최소 값을 가질 영역이 어디인지 조절이 가능하게 된다. 반대로
등을 통해 조절하게 되면, n의 값에 따라, 최대 값을 가질 영역이 조절 가능해진다.
이를 적용해 보면
대비가 낮은 영상을 대비가 높은 영상으로 바꿀 때, 이를 막대그래프의 범위가 넓어지고, "막대그래프 신장" 이라고 부르는 데, 명암을 다른 새로운 값으로 바꾸는 사상에는 Matlab에서는
output_image=imadjust(input_image,[a b],[c d])
가 있다.
imadjust
함수는 a보다 작은 값은 모두 c로 변환하고, b보다 큰 화소의 값을 모두 d로 바꾸며, a와 b사이의 값은 선형보간을 통하여, c와 d의 사이의 값으로 변환한다.
해당 함수를 식으로 나타내면
이다.
해당 사진과 같이 대비가 높아지면, histogram의 폭이 넓어지고, 이를 막대그래프 신장이라고 부른다.
반대로 해당 함수를 사용하여 출력영상의 데이터 범위를 입력영상의 범위보다 좁게 설정을 하게 되면, 대비를 낮출 수 있다.
감마 교정도
imadjust
를 사용해서 진행할 수 있다.
관례에 따라 자승 법칙의 지수를 감마라고 하며, 자승 법칙 응답 현상을 교정하는 것을 감마 교정이라고 한다. 감마 교정은 영상 감지기, 모니터, 필름 등에 의한 비선형 응답을 교정하는 데 주로 사용하는데, 식으로 나타내면 다음과 같다.
여기서 와 는 양의 상수이다. 이라면 지수함수 곡선이되고, 출력 영상은 어둡게 된다. 이라면 로그 함수 곡선이 되며, 밝은 출력영상을 얻을 수 있다. 아래는 감마 값에 대한 입력 비와 출력 비이다.
막대 그래프 균등화는 화질을 개선하는 매우 강력한 도구중에 하나로, MATLAB에서는 histeq함수를 써서 수행한다. 저대비인 원래 영상을 막대 그래프 균등화를 써서 좀 더 뚜렷한 영상을 얻을 수 있다.
궁극적인 목적은 모든 회색계조의 발생 빈도를 똑같이 만드는 것으로, 실제 영상에서는 막대그래프를 완전 평탄하게 만들지는 못하고, 회색계조의 분포를 재분포한다. 영상의 막대그래프에 봉우리나 계곡이 존재하다면, 균등화 이후에도 존재할 수 있다. 하지만 좀 더 균일하게 분포한 막대그래프를 받게함으로써 대비를 증가시키고, 전에 볼 수 없었던 세세한 부분까지 볼 수 있도록 한다.
동일한 물체라도 영상 획득에 사용된 카메라나 전반적인 조명 환경의 영향으로 얻어진 사진이 어둡거나 밝게 표현될 수 있다. 많은 경우 사진을 여러번 촬영하여 못 찍혀진 사진의 보정을 수행하려는 경향이 많은데, 이 때 주로 막대그래프 정합을 사용한다.
막대그래프 정합은 보정하려는 영상과 보정을 위해 참조하려는 영상이 주어지면 이들의 누적확률분포를 계산하여 그 값에 해당하는 참조영상의 화소값을 가져와 입력 사진의 화소값을 대체하는 것이다.
img=imread("lena512.bmp");
img=rgb2gray(img);
%% 밝기 조정하기
bri_img=img+40;
dark_img=img-40;
figure
subplot(1,3,1);
imshow(img,[0,255])
title("원본 사진")
subplot(1,3,2);
imshow(bri_img,[0,255])
title("밝아진 사진")
subplot(1,3,3);
imshow(dark_img,[0,255])
title("어두워진 사진")
% 반전 변환
reverse_img=255-1*img;
figure
subplot(1,2,1);
imshow(img,[0,255])
title("원본 사진")
subplot(1,2,2);
imshow(reverse_img,[0,255])
title("반전 사진")
%% 로그 변환
c1=10;
c2=20;
log_img1=zeros(512,512);
for i=1:512
for j=1:512
log_img1(i,j)=round(c1*log2(1+double(img(i,j))));
end
end
log_img2=zeros(512,512);
for i=1:512
for j=1:512
log_img2(i,j)=round(c2*log2(1+double(img(i,j))));
end
end
figure
subplot(1,3,1);
imshow(img,[0,255])
title("원본 사진")
subplot(1,3,2);
imshow(log_img1,[0,255])
title("c=10,n=2")
subplot(1,3,3);
imshow(log_img2,[0,255])
title("c=20,n=2")
% 지수변환
ex_img=zeros(512,512);
for i=1:512
for j=1:512
ex_img(i,j)=round(1/64*double(img(i,j))^2)+10;
end
end
ex_img2=zeros(512,512);
for i=1:512
for j=1:512
ex_img2(i,j)=round(-1/32*double(img(i,j)-128)^2)+255;
end
end
figure
subplot(1,3,1);
imshow(img,[0,255])
title("원본 사진")
subplot(1,3,2);
imshow(ex_img,[0,255])
title("c=1/64,n=0,d=10")
subplot(1,3,3);
imshow(ex_img2,[0,255])
title("c=-1/64,n=128,d=255")
%% 회색계조 사상
histo_img=imadjust(img,[0.2,0.8],[0,1]);
figure
subplot(2,2,1);
imshow(img,[0,255])
title("원본 사진")
subplot(2,2,2);
imhist(img)
title("원본사진 막대그래프")
subplot(2,2,3);
imshow(histo_img,[0,255])
title("imadjust(img,[0.2,0.8],[0,1])")
subplot(2,2,4);
imhist(histo_img)
title("변환 후 막대그래프")
%% 감마 변환
gamma_img1=imadjust(img,[],[],0.5);
gamma_img2=imadjust(img,[],[],2);
figure
subplot(1,3,1);
imshow(img,[0,255])
title("원본 사진")
subplot(1,3,2);
imshow(gamma_img1,[0,255])
title("γ=0.5")
subplot(1,3,3);
imshow(gamma_img2,[0,255])
title("γ=2")
%% 막대그래프 균등화 (Histogram equlization)
histeq_img=histeq(img);
figure
subplot(2,2,1)
imshow(img,[0,255]);
title("원본 사진")
subplot(2,2,2)
imhist(img)
title("원본사진 막대그래프")
subplot(2,2,3);
imshow(histeq_img,[0,255])
title("histogram equalization을 수행한 이미지")
subplot(2,2,4);
imhist(histeq_img)
title("변환 후 막대그래프")
%% 막대그래프 정합(Histogram matching)
ref_img=imread("cameraman.tif");
ref_img=imresize(ref_img,[512,512]);
c1=cumsum(imhist(img));
c1=c1/c1(256);
c2=cumsum(imhist(ref_img));
c2=c2/c2(256);
[match_img, hgram]=imhistmatch(img,ref_img,256);
c3=cumsum(imhist(match_img));
c3=c3/c3(256);
figure
subplot(3,3,1)
imshow(img)
title("입력 영상")
subplot(3,3,2)
imhist(img)
title("입력영상 히스토그램")
subplot(3,3,3)
plot(c1)
axis([0,256,0,1]);
title("입력영상의 누적확률분포")
subplot(3,3,4)
imshow(ref_img)
title("참조영상")
subplot(3,3,5)
imhist(ref_img)
title("참조영상 히스토그램")
subplot(3,3,6)
plot(c2)
axis([0,256,0,1])
title("참조영상 누적확률분포")
subplot(3,3,7)
imshow(match_img)
title("출력 영상")
subplot(3,3,8)
imhist(match_img)
title("출력영상 히스토그램")
subplot(3,3,9)
plot(c3)
axis([0,256,0,1])
title("출력영상 누적확률분포")