今回はソーベルフィルタについて紹介します。ソーベルフィルタとはプレヴィットフィルタを改良した空間フィルタの一種です。プレヴィットフィルタでは平滑化フィルタと微分フィルタを組み合わせてノイズの影響を抑えて、輪郭を抽出しました。ソーベルフィルタは平滑化フィルタをかける際に注目画素との距離によって重み付けを変化させたものです。これによって自然に平滑化をすることができます。
#include <stdio.h> #include <stdlib.h> #include <math.h> #define IMAGESIZE 256 #define MAXGRAY 255 #define MINGRAY 0 void zero_image(float image[IMAGESIZE][IMAGESIZE]) { int m,n; for(m = 0; m < IMAGESIZE; m++) for(n = 0; n < IMAGESIZE; n++) image[m][n] = 0.0; } int get_image_stdin(float image[IMAGESIZE][IMAGESIZE]) { int m,n,pixel; for(m = 0; m < IMAGESIZE; m++) for(n = 0; n < IMAGESIZE; n++) { pixel = fgetc(stdin); if (pixel == EOF) { fprintf(stderr,"Find out EOF at the pixel(%d,%d).\n",m,n); return(EXIT_FAILURE); } if (pixel > MAXGRAY) pixel = MAXGRAY; else if (pixel < MINGRAY) pixel = MINGRAY; image[m][n] = (float)pixel; } return(EXIT_SUCCESS); } int put_image_stdout(float image[IMAGESIZE][IMAGESIZE]) { int m,n,pixel,result; for(m = 0; m < IMAGESIZE; m++) for(n = 0; n < IMAGESIZE; n++) { pixel = (int)(image[m][n] + 0.5); if (pixel > MAXGRAY) pixel = MAXGRAY; else if (pixel < MINGRAY) pixel = MINGRAY; result = fputc(pixel, stdout); if (result == EOF) { fprintf(stderr,"Can’t write image data at the pixel(%d,%d).\n",m,n); return(EXIT_FAILURE); } } return(EXIT_SUCCESS); } float limit_pixel(float pixel) { float level; if (pixel > (float)MAXGRAY) level = (float)MAXGRAY; else if (pixel < (float)MINGRAY) level = (float)MINGRAY; else level = pixel; return(level); } void reverse_image(float image[IMAGESIZE][IMAGESIZE]) { int m, n; for(m = 0; m < IMAGESIZE; m++) for(n = 0; n < IMAGESIZE; n++) { image[m][n] = limit_pixel(image[m][n]); image[m][n] = (float)MAXGRAY - image[m][n]; } } int main() { int m, n; float dx, dy; float image[IMAGESIZE][IMAGESIZE], edge[IMAGESIZE][IMAGESIZE]; //zero_image(edge); get_image_stdin(image); for(m = 1; m < IMAGESIZE-1; m++) for(n = 1; n < IMAGESIZE-1; n++) { dx = (float)(image[m+1][n-1] + 2 * image[m+1][n]+image[m+1][n+1]-image[m-1][n-1] - 2 * image[m-1][n]-image[m-1][n+1]); dy = (float)(image[m-1][n+1] + 2 * image[m][n+1]+image[m+1][n+1]-image[m-1][n-1] - 2 * image[m][n-1]-image[m-1][n+1]); edge[m][n] = (int)(sqrt(dx * dx + dy * dy) + 0.5); } //reverse_image(edge); put_image_stdout(edge); }
入力画像
出力画像
コンパイルの方法はgcc median.c -lm
実行方法は./a.out <入力する画像ファイル名.拡張子> 出力する画像ファイル名.拡張子
edge[m][n]=(int)(sqrt(dx * dx + dy * dy) + 0.5);の部分は画像によって変えてください。image[m][n]は入力画像、edge[m][n]は出力画像を示しています。