히스토그램 처리
입력되는 화소의 히스토그램을 분석하여 처리하는 알고리즘
ex) 스트래칭, 엔드-인, 평활화
디지털 히스토그램
관찰한 데이터의 특징을 한눈에 알아볼 수 있도록 데이터를 막대그래프 모양으로 나타낸 것
<히스토 스트래칭>
-낮은 명암 대비를 가진 영상의 화질을 향상
-특정 부분이나 가운데에 집중된 히스토그램을 모든 영역으로 확장
이미 히스토그램이 고르게 분포되어 있으면 스트레칭을 적용해도 큰 품질 향상이 없음
function stretchImage() { // 히스토그램 스트래칭 알고리즘
// (중요!) 출력 이미지의 크기가 결정 ---> 알고리즘에 의존...
outH = inH;
outW = inW;
// 출력 영상의 2차원 메모리 할당
outImage = new Array(outH);
for(let i=0; i<outH; i++)
outImage[i] = new Array(outW);
// **** 진짜 영상처리 알고리즘 *****
// 공식 : out = (in-LOW) / (HIGH - LOW) * 255.0
// let LOW = 255, HIGH =0; // 255보다는 작겠지, 0보다 작은게 없으면 버그
let LOW = inImage[0][0], HIGH = inImage[0][0];
for (let i=0; i<inH; i++)
for (let k=0; k<inW; k++) {
if (LOW > inImage[i][k])
LOW = inImage[i][k];
if (HIGH < inImage[i][k])
HIGH = inImage[i][k];
}
for (let i=0; i<inH; i++) {
for (let k=0; k<inW; k++) {
let out = (inImage[i][k] - LOW) / (HIGH - LOW) * 255.0;
if (out < 0.0)
out = 0;
else if (out > 255.0)
out = 255;
else
out = parseInt(out);
outImage[i][k] = out;
}
}
// ******************************
displayImage();
}
<엔드-인>
-일정한 양의 화소를 흰색(0)이나 검정색(255)으로 지정하여 히스토그램의 분포를 좀더 균일하게 만들어 준다
function endInImage() { // 엔드-인 탐색 알고리즘
// (중요!) 출력 이미지의 크기가 결정 ---> 알고리즘에 의존...
outH = inH;
outW = inW;
// 출력 영상의 2차원 메모리 할당
outImage = new Array(outH);
for(let i=0; i<outH; i++)
outImage[i] = new Array(outW);
// **** 진짜 영상처리 알고리즘 *****
// 공식 : out = (in-LOW) / (HIGH - LOW) * 255.0
// let LOW = 255, HIGH =0; // 255보다는 작겠지, 0보다 작은게 없으면 버그
let LOW = inImage[0][0], HIGH = inImage[0][0];
for (let i=0; i<inH; i++)
for (let k=0; k<inW; k++) {
if (LOW > inImage[i][k])
LOW = inImage[i][k];
if (HIGH < inImage[i][k])
HIGH = inImage[i][k];
}
LOW += 50;
HIGH -= 50;
for (let i=0; i<inH; i++) {
for (let k=0; k<inW; k++) {
let out = (inImage[i][k] - LOW) / (HIGH - LOW) * 255.0;
if (out < 0.0)
out = 0;
else if (out > 255.0)
out = 255;
else
out = parseInt(out);
outImage[i][k] = out;
}
}
// ******************************
displayImage();
}
<평활화>
-입력 이미지를 출력 이미지에 저장할 때 출력 이미지에 누적 히스토그램을 정규화 하여 픽셀의 분포를 균일하게 조정
-각 명암의 빈도는 변경하지 않음
// 1단계 : 히스토그램 생성
histo[inImage[i][k]] ++;
// 2단계 : 누적히스토그램 생성
for (let i=0; i<256; i++) {
sumValue += histo[i];
sumHisto[i] = sumValue;
}
for(let i=0; i<256; i++) {
let normal = sumHisto[i] * (1.0 / (inH * inW)) * 255.0;
normalHisto[i] = normal;
function equalizeImage() { // 히스토그램 평활화 알고리즘
// 어둡게 찍힌 영상에 효과적
// (중요!) 출력 이미지의 크기가 결정 ---> 알고리즘에 의존...
outH = inH;
outW = inW;
// 출력 영상의 2차원 메모리 할당
outImage = new Array(outH);
for(let i=0; i<outH; i++)
outImage[i] = new Array(outW);
// **** 진짜 영상처리 알고리즘 *****
// 1단계 : 히스토그램 생성
let histo = new Array(256);
// 초기화
for(let i=0; i<256; i++)
histo[i] =0;
// 카운트
for (let i=0; i<inH; i++)
for (let k=0; k<inW; k++)
histo[inImage[i][k]] ++;
// 2단계 : 누적히스토그램 생성
let sumHisto = new Array(256);
// 초기화
for(let i=0; i<256; i++)
sumHisto[i] =0;
// 계산
let sumValue = 0;
for (let i=0; i<256; i++) {
sumValue += histo[i];
sumHisto[i] = sumValue;
}
// 3단계 : 정규화된 누적 히스토그램 생성
// 공식 : normal = sum * (1.0 / (inH*inW) ) * 255;
let normalHisto = new Array(256);
// 초기화
for(let i=0; i<256; i++)
normalHisto[i] =0.0;
// 계산
for(let i=0; i<256; i++) {
let normal = sumHisto[i] * (1.0 / (inH * inW)) * 255.0;
normalHisto[i] = normal;
}
// 영상 처리
for (let i=0; i<inH; i++) {
for (let k=0; k<inW; k++) {
outImage[i][k] = parseInt(normalHisto[inImage[i][k]]);
}
}
// ******************************
displayImage();
}