【画像処理】Go言語で二値化処理!【サンプルプログラムあり】

golang

こんにちは!zhackです。

先日、以下の画像処理に関する記事を掲載いたしました。

【画像付き】初歩的な画像処理一覧【解説】
先日、画像がプログラムの中でどのように表現されており、 画像の特徴がどのように表現されているか、について記載しました。 今回は、画像に対しどのような処理が存在するのか、ご紹介したいと思います! 画像処理手法一覧 グレースケール ...

今回は、それを実際にプログラムで再現してみました。
利用したプログラム言語は、現在勉強中のGo言語です!

画像処理業界ではおなじみのLena画像を用いて、
二値化処理について、今回は説明していきます。

前提

実行環境

今回の実行環境は以下の通りです。

  • Debian GNU/Linux8
    ※Dockerコンテナで環境構築
  • プログラム名称:binary.go
  • 入力データ:lena.jpg
  • 実行コマンド
    $ go run プログラム名 < 入力画像のパス > 出力画像のパス 
    今回の場合は
    $ go run binary.go < lena.jpg > binary.jpg
  • Gitにも掲載しています。ご参考まで。

Dockerの環境構築及び、Go言語の開発環境構築については以下の記事に記載しています。

画像付き:Dockerのインストール手順(Windows OS)
zhack(私)が実際に行ったDockerのWindowsOSへのインストール手順です。インストールなしで試してみたい方向けにPlay with Dockerの利用方法も簡単に説明します。
DockerでGo言語開発環境構築
Dockerを使ったGo言語の開発環境構築手順を紹介します!簡単に仮想環境を構築できるDockerに、最近サーバサイドの開発で使われつつあるGo言語の開発環境を構築しました。今回はその手順についてご紹介します。

プログラムのひな型

今回実装したプログラムのひな型を紹介します。

package main

// 必要なライブラリのインストール
import (
    "image"
    "image/color"
    "image/jpeg"
    "os"
)
// メイン関数
func main() {

    // 入力データの読み込み
    img, _ := jpeg.Decode(os.Stdin)

    // 入力データを走査するデータの作成
    bounds := img.Bounds()
  // 出力用の入れ物を作成
    dest := image.NewRGBA(bounds)

  // 画像を1ピクセルずつ走査
    for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
        for x := bounds.Min.X; x < bounds.Max.X; x++ {
            // ピクセルの取得
            curPixel := img.At(x, y)
            // ピクセルから色情報RGBA(16bit)を取得 
            r ,g ,b, a := curPixel.RGBA()
            // 色情報16bitを8bitの形式に変換
            r, g, b, a = r>>8, g>>8, b>>8, a>>8
            
            // (1) 必要な処理
        }
    }

    // 処理結果を画像形式で出力
    err := jpeg.Encode(os.Stdout, dest, nil)
    if err != nil {
        panic("Failed to encode JPEG gradient image.")
    }
}

上記、プログラムにおける“(1) 必要な処理”と書いているところに二値化処理ようのコードが入ります。

一点、Go言語のImageパッケージを用いたときの色情報の取得方法について説明します。

At関数で画素を取得した後、RGBA関数で色情報を取得することができます。
しかし、これで得られる色情報は16bitで表現された色情報になります。

先日の記事では、0~255までの数値で各RGBAの値が表現されていると述べましたが、ここではそうではありません。
そのため、ここで取得した値を確認しても60352だとか、ものすごく大きな値になります。

そこで、8bitの色情報で変換してあげましょう。

今回は簡単に16bitの色情報のうち、下位8bitを落としました。

16bitの色情報を8bit右にシフトし、8bitに変換する。
(例) ()内は10進数表記のときの値
16bitの色情報:1111110000111101 (64573)
                 ↓
 8bitの色情報:0000000011111100 (252)

 

Go言語で二値化処理

プログラム

各ピクセルの値の平均値を算出し、その平均値が閾値以上であれば白、閾値より小さい値の場合は黒としました。

閾値の設定は、ループ外のどこかに配置してください。

// 閾値の設定
threshold := 120
// (1) 必要な処理
// 平均値の計算 
mean := ( r + g + b ) / 3
 
if uint8(mean) >= uint8(threshold) {
  // 閾値以上の為、白をセット
  col := color.RGBA{R: uint8(255), G: uint8(255), B: uint8(255), A: uint8(0)}
  dest.Set(x, y, col)
} else {
  // 閾値より小さいため、黒をセット
  col := color.RGBA{R: uint8(0), G: uint8(0), B: uint8(0), A: uint8(0)}
  dest.Set(x, y, col)
}

出力結果

出力結果はこのような感じです。

閾値が120の場合は、上記のような結果ですが、例えば閾値を50にした場合、ほとんどの画素が閾値以上となるため、白い領域が増えます。

さいごに

先日紹介した二値化処理について、Go言語で実装してみました。

しかしただ単純に二値化処理を行うだけだと、ノイズものっていますね。
また、色の濃淡を知りたいときもあるかもしれません。

今後、この画像処理シリーズはいくつか掲載する予定です。

よろしくお願いいたします。

ではでは!

 

 

コメント

  1. […] 先日画像処理に関する記事を掲載し、これに関して、Go言語で二値化処理したプログラムについて紹介しました。 […]

  2. […] Go言語のImageパッケージを用いたときの色情報の取得方法については、【画像処理】Go言語で二値化処理!【サンプルプログラムあり】をご参考ください。 […]

  3. […] Go言語のImageパッケージを用いたときの色情報の取得方法については、【画像処理】Go言語で二値化処理!【サンプルプログラムあり】をご参考ください。 […]

  4. […] […]

  5. […] […]

タイトルとURLをコピーしました