スポンサーリンク

大津の二値化で画像を2値化 JavaScript + canvas 【画像処理】

スポンサーリンク
JavaScript
スポンサーリンク

スポンサーリンク

概要

大津の二値化で画像を2値化するサンプルコード

画像を2値化する JavaScript + canvas 【画像処理】
概要JavaScriptで画像を2値化するサンプルコードの紹介。デモ実行すると以下のような画像が生成されます。サンプルソースグレースケールに変換された画像の各画素の値が閾値未満であれば0、閾値以上であれば255に変換します...

↑のサンプルコードでは閾値を128として決め打ちで2値化していますが、画像のヒストグラムの分散から適切な閾値を求める方法(判別分析法)の1つです。

ここでは、そのサンプルコードとデモを紹介しています。

デモ

画像処理100本ノックJS
画像処理100本ノックJS : 画像処理100本ノックにJavaSCriptで挑戦してみました。

実行するとこのような画像が生成されます。

サンプルソース

大津の2値化クラス

/**
 * 大津の2値化
 */
class ImageProc{
  /**
   * メイン
   * @param {Object} canvas 
   * @param {Object} image 
   */
  main(canvas, image) {
    const grayscale = (r, g, b) => 0.2126 * r + 0.7152 * g + 0.0722 * b
    let ctx = canvas.getContext("2d");
    ctx.drawImage(image, 0, 0, image.width, image.height)
    let src = ctx.getImageData(0, 0, image.width, image.height)
    let dst = ctx.createImageData(image.width, image.height)

    let t = this.threshold(src)

    for (let i = 0; i < dst.data.length; i += 4) {
      let v = grayscale(src.data[i], src.data[i + 1], src.data[i + 2])
      if (v < t) {
        dst.data[i] = dst.data[i + 1] = dst.data[i + 2] = 0
      } else {
        dst.data[i] = dst.data[i + 1] = dst.data[i + 2] = 255
      }
      dst.data[i + 3] = 255
    }
    ctx.putImageData(dst, 0, 0)
  }
  /**
   * 大津の2値化
   * @param {ImageData} src
   */
  threshold(src) {
    const grayscale = (r, g, b) => 0.2126 * r + 0.7152 * g + 0.0722 * b
    let histgram = Array(256).fill(0)
    let t = 0
    let max = 0

    for (let i = 0; i < src.data.length; i += 4) {
      let g = ~~grayscale(src.data[i], src.data[i + 1], src.data[i + 2])
      histgram[g]++
    }

    for (let i = 0; i < 256; i++) {
      let w1 = 0
      let w2 = 0
      let sum1 = 0
      let sum2 = 0
      let m1 = 0
      let m2 = 0
      for (let j = 0; j <= i; ++j) {
        w1 += histgram[j]
        sum1 += j * histgram[j]
      }
      for (let j = i + 1; j < 256; ++j) {
        w2 += histgram[j]
        sum2 += j * histgram[j]
      }
      if (w1) {
        m1 = sum1 / w1
      }
      if (w2) {
        m2 = sum2 / w2
      }
      let tmp = (w1 * w2 * (m1 - m2) * (m1 - m2))
      if (tmp > max) {
        max = tmp
        t = i
      }
    }
    return t
  }
}

メイン

const canvas = document.getElementById("canvas")
let image = new Image()
image.crossOrigin = "Anonymous";
image.src = "path/to/image.png"

image.onload = function() {
  canvas.width = image.width
  canvas.height = image.height
  let ip = new ImageProc()
  ip.main(canvas, image)
}

HTML


GitHubに上がっているものを流用しています。

s-yoshiki/Gasyori100knockJS
画像処理100本ノックをJSで解いてみる. Contribute to s-yoshiki/Gasyori100knockJS development by creating an account on GitHub.

大津の2値化

ここら辺の説明を参考にしました。

画像のしきい値処理 — OpenCV-Python Tutorials 1 documentation
大津の二値化ってなんだ…ってなった. - Qiita
# はじめに OpenCVを利用して二値化を行う際, 「とりあえず`cv2.THRESH_OTSU`やっとけばええやろ, ぽいー」って感じでテキトーに二値化してました. 「とりあえずいい感じに動く」って認識だったので, きちんと(?)...
【画像処理】大津の二値化処理の原理・特徴・計算式
この記事では、画像処理における大津の手法(判別分析法)を用いた二値化処理の原理や計算式についてまとめました。
タイトルとURLをコピーしました