上の画像に対して閾値(しきいち)処理をして、文字の部分のみ
抽出(抜き出すこと)方法を以下に説明する。他の成書では、二値化処理と称することが多い。
この画像のBMP形式をダウンロードして展開すると、e-img.bmpが
得られる。このデータに対して、閾値処理を行う例を示す。
画像処理において、抽出した文字を白く表示したい。ここでは、256階調のグレースケールで
表現しているので、白はHIGH(255)、黒はLOW(0)である。
文字を抽出するために、(3.2)式を利用する。ここに、抽出したい文字は黒であるから、
設定した閾値より小さい画素値ならば、この値を抽出し、論理的にHIGHと置く。
論理的に考えるならば、HIGHは1でよい。しかし、実際の画像表示に都合がよいよう255を
あてている。
以下に、いろいろな閾値に対する二値化処理結果を示す。
本書では閾値の定め方として、ヒストグラム(histgram)を用いる。
ここでのヒストグラムとは画像の各濃度値の分布をグラフで表したものである。
ここでは、各階調のpixelの頻度をテキスト形式でファイルに出力する関数
を作成し、出力したファイルに対してGnuplotを用いてヒストグラムのグラフ表示する。
(本書のサンプルだとpixel数に合わせて幅を調整せねばならないが、
gnuplotを使えばその考慮は不要である。)
histgram.txtを出力した。このファイルの0〜255の範囲を見るために、 x軸の範囲を少し余分に取るよう、 以下のようにコマンドを入力した。
gnuplot> set xlabel "Brightness" gnuplot> set ylabel "Number of pixels" gnuplot> set xrange[-10:265] gnuplot> plot "histgram.txt" w i
このままだと、谷を見つけにくいので、前後2画素との平均を取る関数を
作成し、これを利用した結果が下のグラフである。
先のものに比べヒストグラムの包絡線が滑らかになり、グラフの山と谷が見やすくなった。
このサンプル画像は白い背景の部分のpixelの方が多いので、
文字と背景の境目は50〜100の谷であろうとみなして、閾値を85に設定した結果が次である。
#include "Params.h"
/*--- threshold --- 閾(しきい)値処理 ----------------------------------------
image_in: 入力画像配列
image_out: 出力画像配列
thresh: 閾値
mode: 閾値処理の方法(1,2)
-----------------------------------------------------------------------------*/
void threshold(unsigned char image_in[Y_SIZE][X_SIZE],
unsigned char image_out[Y_SIZE][X_SIZE], int thresh, int mode)
{
int i,j;
for (i = 0; i < Y_SIZE; i++) {
for ( j = 0; j < X_SIZE; j++) {
switch (mode) {
case 2:
if ((int)image_in[i][j] <= thresh) image_out[i][j] = HIGH;
else image_out[i][j] = LOW;
break;
default:
if ((int)image_in[i][j] >= thresh) image_out[i][j] = HIGH;
else image_out[i][j] = LOW;
break;
}
}
}
}
#include "Params.h"
/*--- histgram --- ヒストグラムを求める処理 -----------------------------------
image_in: 入力画像配列
hist: ヒストグラム
-----------------------------------------------------------------------------*/
void histgram(unsigned char image_in[Y_SIZE][X_SIZE], long hist[256])
{
int i,j,n;
for (n = 0; n < 256; n++) hist[n] = 0;
for (i = 0; i < Y_SIZE; i++) {
for ( j = 0; j < X_SIZE; j++) {
n = image_in[i][j];
hist[n]++;
}
}
}
#include"Params.h" #include<stdio.h> /************************************************************ outputHistgram : 256段階のヒストグラムファイルを出力する関数 ***********************************************************/ void outputHistgram(long histgram[256]){ FILE *filePointer; int c; char fileName[40]; printf("Input histgram text file name: "); scanf("%s",&fileName); //output text file filePointer = fopen(fileName, "w"); if(filePointer != NULL){ for(c=0; c<256; c++){ fprintf(filePointer, "%d\t%d\n",c,histgram[c]); } fclose(filePointer); printf("%s was Outputed.\n", fileName); }else{ printf("Error.\n"); } }
#include "Params.h"
/*--- histsmooth --- ヒストグラムを平滑化する ---------------------------------
hist_in: ヒストグラム 平滑化前
hist_out: ヒストグラム 平滑化後
-----------------------------------------------------------------------------*/
void histsmooth(long hist_in[256], long hist_out[256])
{
int m, n, i;
long sum;
for (n = 0; n < 256; n++) {
sum = 0;
for (m = -2; m <= 2; m++) {
i = n + m;
if (i < 0) i = 0;
if (i > 255) i = 255;
sum = sum + hist_in[i];
}
hist_out[n] = (long)((float)sum / 5.0 + 0.5);
}
}