이미지를 이진화시키기 위해서 여러 알고리즘이 사용된다. 그중 이미지 전체에 대해 하나의 임계값으로 이진화시키는 전역 이진화 알고리즘은 간단하고 빠르기 때문에 많이 이용이 된다. 그러나 이미지를 형성할 때 조명 조건이 균일하지 않은 경우에는 전역 이진화는 원하는 결과를 얻기가 힘들다. 이런 경우에는 각각의 픽셀 주위의 그레이 값을 참조하여 임계치를 결정하는 국소적 이진화 방법을 사용한다. 국소적 이진화에서 임계값을 추출하는 간단한 방법은 윈도 내의 평균값을 이용하면 된다. 좀 더 개선된 알고리즘은 평균값(
여기서
국소적인 이진화 알고리즘은 매 픽셀마다 윈도를 잡아서 계산해야 하므로 연산 비용이 많이 든다. 충분한 메모리를 갖춘 시스템의 경우에는 적분 이미지(integral image)를 이용하면 윈도 연산에 소요되는 비용을 대폭 줄일 수 있다..
국소적 이진화 알고리즘에서 윈도 크기와
void make_int_img12(BYTE *gray, int width, int height, *int intimage, int *intsqimg);
void make_int_img12(BYTE *gray, int width, int height, *int intimage, int *intsqimg) {
// first row accumulation;
intimage[0] = gray[0];
for (int x = 1; x < width; ++x) {
int a = gray[x] ;
intimage[x] = intimage[x - 1] + a;
intsqimg[x] = intsqimg[x - 1] + a * a;
}
for (int y = 1, pos = y * width; y < height; ++y) {
int linesum = 0, linesqsum = 0 ;
for (int x = 0; x < width; ++x, ++pos) {
int a = gray[pos];
linesum += a;
linesqsum += a * a;
intimage[pos] = intimage[pos - width] + linesum ;
intsqimg[pos] = intsqimg[pos - width] + linesqsum;
}
}
};
#define integral_image(x, y) (intimage[(y) * width + (x)])
#define integral_sqimg(x, y) (intsqimg[(y) * width + (x)])
//
void adap_binariztion(BYTE *gray, int width, int height,
int w /*window size = 15*/,
double k /*factor = 0.2*/,
BYTE *bimage) {
int whalf = w >> 1; //half of adaptive window;
int diff, sqdiff;
// make integral image && square integral image;
// if image is sufficiently large, use int64 or floating point number;
std::vector<int> intimage(width * height) ;
std::vector<int> intsqimg(width * height) ;
//make integral image and its square integral image;
make_int_img12(gray, width, height, &intimage[0], &intsqimg[0]);
//algorithm main;
for (int j = 0, pos = 0; j < height; j++) {
for (int i = 0; i < width; i++, pos++) {
// clip windows
int xmin = max(0, i - whalf);
int ymin = max(0, j - whalf);
int xmax = min(width - 1, i + whalf);
int ymax = min(height - 1, j + whalf);
int area = (xmax - xmin + 1) * (ymax - ymin + 1);
// calculate window mean and std deviation;
if (!xmin && !ymin) { // origin
diff = integral_image(xmax, ymax);
sqdiff = integral_sqimg(xmax, ymax);
} else if (!xmin && ymin) { // first column
diff = integral_image(xmax, ymax) - integral_image(xmax, ymin - 1);
sqdiff = integral_sqimg(xmax, ymax) - integral_sqimg(xmax, ymin - 1);
} else if (xmin && !ymin){ // first row
diff = integral_image(xmax, ymax) - integral_image(xmin - 1, ymax);
sqdiff = integral_sqimg(xmax, ymax) - integral_sqimg(xmin - 1, ymax);
} else{ // rest of the image
int diagsum = integral_image(xmax, ymax) + integral_image(xmin - 1, ymin - 1);
int idiagsum = integral_image(xmax, ymin - 1) + integral_image(xmin - 1, ymax);
diff = diagsum - idiagsum;
int sqdiagsum = integral_sqimg(xmax, ymax) + integral_sqimg(xmin - 1, ymin - 1);
int sqidiagsum = integral_sqimg(xmax, ymin - 1) + integral_sqimg(xmin - 1, ymax);
sqdiff = sqdiagsum - sqidiagsum;
}
// threshold = window_mean *( 1 + factor * (std_dev/128.-1));
// 128 = max_allowed_std_deviation in the gray image;
double mean = double(diff) / area;
double std = sqrt((sqdiff - double(diff) * diff / area) / (area - 1));
double threshold = mean * (1.0 + k * ((std / 128.0) - 1.));
if (gray[pos] < threshold) bimage[pos] = 0;
else bimage[pos] = 255;
}
}
};

'Image Recognition > Fundamental' 카테고리의 다른 글
Fant's Resampling (0) | 2008.12.17 |
---|---|
Bright Preserving Histogram Equalization with Maximum Entropy (0) | 2008.07.31 |
Histogram Equalization (0) | 2008.06.22 |
FFT2D (0) | 2008.06.10 |
Otsu Algorithm (6) | 2008.05.30 |