この画像のBMP形式の圧縮ファイルをダウンロードして展開すると、noise.bmpが得られる。
この画像に対して、以下に雑音除去例を示す。
以下に移動平均法によるノイズ除去例を示す。
ここで、テキストに明記されていないが、平均した値は原画像とは別に設けた二次元配列に
格納する。もし、平均値を原画像に直接格納すると、おかしな結果を得る。
移動平均法1回の例。
移動平均法5回の例。
移動平均法は注目画素の注目画素と8近傍の平均値を画素の値とすることにより、
ぼかす処理である。
回数を増すほどに、雑音は見えなくなるが、同時に画像がぼけてしまっているのがわかる。
統計におけるメディアンとは、データを小さい順に並べたとき、 その順の真ん中の値を採用する考え方である。今の場合、3x3画素であるから 9列の真ん中、すなわち5番目に小さい値を採用することになる。 これを用いたメディアンフィルタによるノイズ除去例を示す。
メディアンフィルタ1回の例。
メディアンフィルタ5回の例。
移動平均法と比較して、雑音の値は選択されにくいので、 移動平均より優れた結果が得られた。
3章で用いた2値画像に対して
雑音を追加したものを下の画像に示す。
この画像のBMP形式をダウンロード
この画像に対して膨張、収縮処理を施した例を以下に示す。
膨張、収縮処理例を示す。 左が膨張、右が収縮処理を施した例である。
膨張処理は、注目画素の周囲8近傍に一つでも1(白)があったら、その画素を
1にする処理である。例では、文字の白い領域が広ければ、その中の雑音は無くなる。
しかし、文字領域以外の白領域も広がる。
収縮はその逆で、一つでも0(黒)があったら、
その画素を0にする処理である。その効用は、膨張処理と逆である。
膨張したことにより、文字中の雑音が消えたのがわかる。
しかし、周囲の雑音は除去できず、面積が広がったものもある。
収縮したことにより、背景の雑音が消えたのがわかる。
しかし、文字中の雑音は除去できない。
#include "Params.h"
/*--- smooth --- 移動平均法によるノイズ除去 -----------------------------------
image_in: 入力画像配列
image_out: 出力画像配列
-----------------------------------------------------------------------------*/
void smooth(unsigned char image_in[Y_SIZE][X_SIZE],
unsigned char image_out[Y_SIZE][X_SIZE])
{
int i, j, buf;
for (i = 1; i < Y_SIZE-1; i++) {
for (j = 1; j < X_SIZE-1; j++) {
buf = (int)image_in[i-1][j-1]
+ (int)image_in[i-1][j]
+ (int)image_in[i-1][j+1]
+ (int)image_in[i][j-1]
+ (int)image_in[i][j]
+ (int)image_in[i][j+1]
+ (int)image_in[i+1][j-1]
+ (int)image_in[i+1][j]
+ (int)image_in[i+1][j+1];
image_out[i][j] = buf / 9;
}
}
}
#include "Params.h" int median_value(unsigned char c[9]); /*--- median --- メディアンフィルタによるノイズ除去 --------------------------- image_in: 入力画像配列 image_out: 出力画像配列 -----------------------------------------------------------------------------*/ void median(unsigned char image_in[Y_SIZE][X_SIZE], unsigned char image_out[Y_SIZE][X_SIZE]) { int i, j; unsigned char c[9]; for (i = 1; i < Y_SIZE-1; i++) { for (j = 1; j < X_SIZE-1; j++) { c[0] = image_in[i-1][j-1]; c[1] = image_in[i-1][j]; c[2] = image_in[i-1][j+1]; c[3] = image_in[i][j-1]; c[4] = image_in[i][j]; c[5] = image_in[i][j+1]; c[6] = image_in[i+1][j-1]; c[7] = image_in[i+1][j]; c[8] = image_in[i+1][j+1]; image_out[i][j] = median_value(c); } } } /*--- median_value --- 9つの画素の中央値(メディアン)を求める --------------- c: 画素 -----------------------------------------------------------------------------*/ int median_value(unsigned char c[9]) { int i, j, buf; for (j = 0; j < 8; j++) { for (i = 0; i < 8; i++) { if (c[i+1] < c[i]) { buf = c[i+1]; c[i+1] = c[i]; c[i] = buf; } } } return c[4]; }
#include "Params.h"
/*--- erosion --- 収縮処理 ----------------------------------------------------
image_in: 入力画像配列
image_out: 出力画像配列
-----------------------------------------------------------------------------*/
void erosion(unsigned char image_in[Y_SIZE][X_SIZE],
unsigned char image_out[Y_SIZE][X_SIZE])
{
int i, j;
for (i = 1; i < Y_SIZE-1; i++) {
for (j = 1; j < X_SIZE-1; j++) {
image_out[i][j] = image_in[i][j];
if (image_in[i-1][j-1] == LOW) image_out[i][j] = LOW;
if (image_in[i-1][j ] == LOW) image_out[i][j] = LOW;
if (image_in[i-1][j+1] == LOW) image_out[i][j] = LOW;
if (image_in[i ][j-1] == LOW) image_out[i][j] = LOW;
if (image_in[i ][j+1] == LOW) image_out[i][j] = LOW;
if (image_in[i+1][j-1] == LOW) image_out[i][j] = LOW;
if (image_in[i+1][j ] == LOW) image_out[i][j] = LOW;
if (image_in[i+1][j+1] == LOW) image_out[i][j] = LOW;
}
}
}
#include "Params.h"
/*--- dilation --- 膨張処理 ---------------------------------------------------
image_in: 入力画像配列
image_out: 出力画像配列
-----------------------------------------------------------------------------*/
void dilation(unsigned char image_in[Y_SIZE][X_SIZE],
unsigned char image_out[Y_SIZE][X_SIZE])
{
int i, j;
for (i = 1; i < Y_SIZE-1; i++) {
for (j = 1; j < X_SIZE-1; j++) {
image_out[i][j] = image_in[i][j];
if (image_in[i-1][j-1] == HIGH) image_out[i][j] = HIGH;
if (image_in[i-1][j ] == HIGH) image_out[i][j] = HIGH;
if (image_in[i-1][j+1] == HIGH) image_out[i][j] = HIGH;
if (image_in[i ][j-1] == HIGH) image_out[i][j] = HIGH;
if (image_in[i ][j+1] == HIGH) image_out[i][j] = HIGH;
if (image_in[i+1][j-1] == HIGH) image_out[i][j] = HIGH;
if (image_in[i+1][j ] == HIGH) image_out[i][j] = HIGH;
if (image_in[i+1][j+1] == HIGH) image_out[i][j] = HIGH;
}
}
}