みさご解体新書

二値化

実行例

ソースコード

TypeScript

0.jpg / app.ts

解説/アルゴリズム

画像のピクセル毎に、前もって決めておいた条件をもとにピクセルの色を黒か白どちらかに変換する処理を二値化と呼ぶ。

とはいっても適当な条件で白黒にしても意味がない。

よく使用される条件として挙げられるのは、ピクセルの色が黒に近ければ黒、そうでなければ白にする、というもの。

ここでは、グレースケールに変換してからの判定方法を紹介する。

グレースケールで判定する場合

// しきい値
const threshold = 90;

// グレースケールの値を計算。
const gray = 0.299 * r + 0.587 * g + 0.114 * b;

// グレースケールとしきい値を比較。白か黒どちらに変換するのかを決める。
let value = 255;
if (gray < threshold) {
  value = 0;
}

ピクセルの色を取り出し、RGB の値からグレースケール(明るさ)の値を求める。

その値を見て、前もって決めておいた条件の値より小さければ黒に、でなければ白に変換する。

このような条件の値のことをしきい値(threshold)と呼ぶ。

コード例(GLSL)

attribute vec2 aPosition;
attribute vec2 aTexCoord;
uniform vec2 uResolution;
varying vec2 vTexCoord;

void main() {
  vec2 clipSpace = aPosition / uResolution * 2.0 - 1.0;
  gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
  vTexCoord = aTexCoord;
}
precision mediump float;
const float threshold = 90.0 / 255.0;
uniform sampler2D uImage;
varying vec2 vTexCoord;

void main() {
  vec4 color = texture2D(uImage, vTexCoord);
  float gray = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b;
  if (gray < threshold) {
    gl_FragColor = vec4(0.0);
  }
  else {
    gl_FragColor = vec4(1.0);
  }
}

コード例(p5.js)

import * as p5 from "p5";

new p5((p: p5) => {
  let image: p5.Image;
  // しきい値
  const threshold = 90;

  p.preload = () => {
    image = p.loadImage("./0.jpg");
  };

  p.setup = () => {
    p.createCanvas(p.windowWidth, p.windowHeight);
    p.loadPixels();

    // 画像の全ピクセルを走査
    for (let y = 0; y < image.height; y++) {
      for (let x = 0; x < image.width; x++) {
        // 対象のピクセルを取り出す
        const color = getPixel(x, y);

        // RGBを取り出し、グレースケール(明るさ)を計算
        const r = p.red(color);
        const g = p.green(color);
        const b = p.blue(color);
        const gray = 0.299 * r + 0.587 * g + 0.114 * b;

        // グレースケールの値がしきい値より小さければ黒、そうでなければ白に変換する
        let value = 255;
        if (gray < threshold) {
          value = 0;
        }

        // 白か黒の色をセットする
        setPixel(x, y, [value, value, value]);
      }
    }

    p.updatePixels();
    p.image(image, 0, 0);
  };

  function getPixel(x: number, y: number): number[] {
    const i = (y * image.width + x) * 4;
    return [
      image.pixels[i],
      image.pixels[i + 1],
      image.pixels[i + 2],
      image.pixels[i + 3],
    ];
  }

  function setPixel(x: number, y: number, color: number[]): void {
    const i = (y * image.width + x) * 4;
    image.pixels[i + 0] = color[0];
    image.pixels[i + 1] = color[1];
    image.pixels[i + 2] = color[2];
  }
});

内部で利用しているアルゴリズム

グレースケール