チーム20A1

課題名

可変モザイク処理とFFT

研究者名

Soshiro Abe
Isaya Iwamoto

使用言語

C言語、Java

概要

画像の複数の大きさのモザイク処理と、その変換前後の画像をFFTで周波数成分へ変換した画像を作成した。

モザイク処理

チーム19F1のソースコードを改良してモザイクの大きさが自由に変更できるようにする。

チーム19F1はモザイクの大きさstepを固定していた。
また、モザイクをかけてstep*stepのブロックの大きさが取れない端で,余りの部分を考えて割り算していた。
そのため、ブロックの大きさが均等では無かった。

元の画像
lena.jpeg

19F1の画像
out8.jpeg
そこで、私たちはstepを自由にへんこうできるようにして、その上余りをほかのブロックに分けることで
すべてのブロックの大きさがほとんど同じになるようにした。



私たちの画像

モザイクの大きさ(step)=8
human8.jpg

モザイクの大きさ(step)=50
human50.jpg

モザイクの大きさ(step)=100
human100.jpg

モザイクの大きさ(step)=512
human'.jpg

FFT

チーム15C2が作成したFFTのプログラムを引用して、
元の画像と元画像に私たちがモザイク処理した画像3つの計4つをFFTで変換した。

元の画像を変換したもの
freq_lena.jpg

私たちの画像を変換したもの

モザイクの大きさ(step)=8
freq8.jpg

モザイクの大きさ(step)=50
freq50.jpg

モザイクの大きさ(step)=100
freq100.jpg

モザイクの大きさ(step)=512
freq1000.jpg

この画像は
中央に行くほど高周波、端に行くほど低周波の成分を表し、
青いほどその成分が少なく、赤いほど多いことを表している。

ソースコード

このソースコードはチーム19F1のものを改良したものである。
#include <gd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int string_int(const char *s)
{
  int l = 0, num = 0;
   while (s[l]) {
       num *= 10;
       if (s[l] < '0' | | s[l] > '9') {
           printf("%s is not natural number\n", s);
           exit(-1);
       }
       num += s[l] - '0';
       l++;
   }
   if (num < 1) {
       printf("%d is not natural number\n", num);
       exit(-1);
   }
   return num;
}

int main(const int argc, const char *argv[])
{

  FILE *out, *in;
   gdImagePtr im, im_new;
   int width, height, i, j, color, r, g, b, pixel, l, k, y, c, wid, hei;
   int stepx, stepy, step, lenx, leny, ax, ay, ix, iy;
   if (argv[1] == NULL | | argv[2] == NULL | | !strcmp(argv[1], argv[2])
       | | argc != 4) {
       printf("argument error\n");
       exit(-1);
   }

  if ((in = fopen(argv[1], "r")) == NULL) {
       printf("file open error for %s\n", argv[1]);
       exit(-1);
   }
  if ((out = fopen(argv[2], "wb")) == NULL) {
       printf("file open error for %s\n", argv[2]);
       exit(-1);
   }
   //第三引数で指定されたモザイクサイズを読み取る
   step = string_int(argv[3]);
   im = gdImageCreateFromJpeg(in);

  width = gdImageSX(im);
   height = gdImageSY(im);
   im_new = gdImageCreateTrueColor(width, height);
   lenx = width / step;
   leny = height / step;
   ax = width % step;
   ay = height % step;
   ix = 0;
   iy = 0;
   for (i = 0; i < width;) {
       stepx = step;
       if (ax > 0) {
           stepx += lenx > ix ? (ax / (lenx - ix)) : ax;
           ax -= ax / (lenx - ix);
           ix++;
       }
       ay = height % step;
       iy = 0;
       for (j = 0; j < height;) {
           stepy = step;
           if (ay > 0) {
               stepy += leny > iy ? (ay / (leny - iy)) : ay;
               ay -= ay / (leny - iy);
               iy++;
           }
           r = 0;
           g = 0;
           b = 0;
           for (k = 0; k < stepx; k++) {
               for (l = 0; l < stepy; l++) {
                   pixel = gdImageGetPixel(im, i - 1 + k, j - 1 + l);
                   r = r + gdImageRed(im, pixel);
                   g = g + gdImageGreen(im, pixel);
                   b = b + gdImageBlue(im, pixel);
               }
           }
           r = r / stepx / stepy;
           g = g / stepx / stepy;
           b = b / stepx / stepy;
           if (r < 0)
               r = 0;
           if (g < 0)
               g = 0;
           if (b < 0)
               b = 0;
           if (255 < r)
               r = 255;
           if (255 < g)
               g = 255;
           if (255 < b)
               b = 255;

          //  各画素を求めた色で表示する。表示範囲を超えないようにサイズの確認をする。
           for (k = 0; k < stepx; k++) {
               for (l = 0; l < stepy; l++) {
                   //im の (i,j) における r,g,b の値を取得
                   color = gdImageColorExact(im_new, r, g, b);
                   //im_new の (i,j) におけるピクセル値を color で設定
                   gdImageSetPixel(im_new, i + k, j + l, color);
               }
           }
           j += stepy;
       }
       i += stepx;
   }

  gdImageJpeg(im_new, out, -1);

  fclose(in);
   fclose(out);

  return 0;
}



画像をFFTで変換するソースコードは、チーム15C2のものを引用した。

改良箇所

チーム19F1のものからの改良箇所を挙げていく。


①stepを可変にした。
#defineで定義されていた定数をコマンドライン引数で受け取るようにした。
(string_int関数は文字列をint型に変換する関数)

  #define step 20
    ↓
  step = string_int(argv[3]);



②step*stepのブロックの大きさが取れない端で余りの部分を、
他のブロックに分けることで全体のブロックの大きさがほぼ均一になるようにした。
 生成されるブロックの数と、余るピクセル数を求め、できるだけ差が小さくなるように割り振った。

  lenx = width  / step;
   leny = height / step;
   ax = width  % step;
   ay = height % step;
   ix = 0;
   iy = 0;
   ------------------------------------------------
  stepx = step;
   if (ax > 0) {
       stepx += lenx > ix ? (ax / (lenx - ix)) : ax;
       ax -= ax / (lenx - ix);
       ix++;
   }
   ay = height % step;
   iy = 0;
   -----------------------------------------------
   stepy = step;
   if (ay > 0) {
       stepy += leny > iy ? (ay / (leny - iy)) : ay;
       ay -= ay / (leny - iy);
       iy++;
   }

考察

モザイク画像とFFT処理
モザイク処理を施した画像をFFT処理を行うと, 青色の格子状の模様が現れる.
ここで, 青色はその成分が少ないことを表している.
この格子状の模様は, モザイクを粗くすると模様が細かくなり, 全体的に青色の部分が多くなる.
このことより, モザイクを粗くすると, 周波数の成分が少なくなり,
画像の明暗の変化が少なくなったことが分かる.

モザイクの粗さとFFT画像の模様
モザイクの粗さ(stepの数)とFFTで現れる格子状の模様の数が一致している.
モザイクをかけると画像が周期的な変化がFFT処理後の画像にも反映されている.

単色の画像とFFT処理
究極に粗いモザイクをかけた状態を単色の画像と考えることができる.
上記より, 単色画像をFFTで処理して得られる画像は全て青色であると予想でき,
512 * 512の格子状の画像であるとも捉えることができる.
また, 実際に全て青色の画像を得られた.

  • 最終更新:2020-06-01 15:53:28

このWIKIを編集するにはパスワード入力が必要です

認証パスワード