【画像処理】Go言語で輪郭抽出!X方向Y方向微分【サンプルコード付き】

golang

こんにちは!zhackです。

Go言語で画像処理シリーズ第3弾!

今回は、エッジ検出について説明していきます。

先日、フィルタ処理に関する記事を掲載しました。

【画像処理】空間フィルタリングとは?
こんにちは!zhackです。 今回は画像処理でよく使われる空間フィルタリングについて、紹介します! 空間フィルタリングとは? 画像中の注目しているある画像に対して、注目している画素とその周囲の画素から、注目している画素を変換する処...

その中の輪郭抽出である、X方向及びY方向の微分について、実装してみました。

前提

実行環境

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

  • Debian GNU/Linux8
    ※Dockerコンテナで環境構築
  • プログラム名称:edge_x.go, edge_y.go
  • 入力データ:zukei.jpg
  • 実行コマンド
    $ go run プログラム名 < 入力画像のパス > 出力画像のパス 
    今回の場合は
    $ go run edge_x.go < zukei.jpg > zukei_x.jpg
    もしくは
    $ go run edge_y.go < zukei.jpg > zukei_y.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++ {
            // (1) 必要な処理
        }
    }

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

上記、プログラムにおける“(1) 必要な処理”と書いているところにエッジ検出用のコードが入ります。

Go言語のImageパッケージを用いたときの色情報の取得方法については、二値化処理に関する以下の記事に記載していますので、そちらをご参考ください。

【画像処理】Go言語で二値化処理!【サンプルプログラムあり】
こんにちは!zhackです。 先日、以下の画像処理に関する記事を掲載いたしました。 今回は、それを実際にプログラムで再現してみました。 利用したプログラム言語は、現在勉強中のGo言語です! 画像処理業界ではおなじ...

Go言語でX方向、Y方向の微分処理

フィルタの説明

今回扱うフィルタは、このようなフィルタになります。

濃い黄色になっているところが、注目画素です。

X方向の微分について、注目画素とその左側の画素以外には0が入っています。
そのため、処理後の画素に入る数値は、

(処理後の画素に入る値) = (注目画素の値) - (注目画素の左側の画素の値)

になりますね。

Y方向の微分については、以下のようになります。

(処理後の画素に入る値) = (注目画素の値) - (注目画素の上側の画素の値)

では、これを実際にプログラムにしてみましょう。

 

プログラム

上記、(1)必要な処理の部分に以下のコードを入力します。


// 注目画素のRGB値を取得
curPixel := img.At(x, y)
r, g, b, a := curPixel.RGBA()
r, g, b, a = r>>8, g>>8, b>>8, a>>8

// 注目画素の左側の画素のRGB値を取得
curLeftPixel := img.At(x-1, y)
r_l, g_l ,b_l, a_l := curLeftPixel.RGBA()
r_l, g_l, b_l, a_l = r_l>>8, g_l>>8, b_l>>8, a_l>>8

// 画素の計算
rValue := r - r_l
gValue := g - g_l
bValue := b - b_l
aValue := a - a_l

// 0未満の場合は0に、255より大きい場合は255にする 
if rValue < 0{ rValue = 0}
if rValue > 255 { rValue = 255}
if gValue < 0{ gValue = 0}
if gValue > 255 { gValue = 255}
if bValue < 0{ bValue = 0}
if bValue > 255 { bValue = 255}
if aValue < 0{ aValue = 0}
if aValue > 255 { aValue = 255}

// 計算したものを出力画像としてセット
col := color.RGBA{R: uint8(rValue), G: uint8(gValue), B: uint8(bValue), A: uint8(aValue)}
dest.Set(x, y, col)

出力結果

上記のプログラムを実行するとこのようになります。

すこし、ノイズが載っていますが、x方向の微分を行うことができました。

正方形の辺がy方向の辺のみ抽出できていますね。

これは、注目画素とその左側の画素の差をとっている為、x方向の辺上の画素が0になってしまったことが原因です。

Y方向の微分はどのようなプログラムになるのでしょうか。
実際に試してみてください!

さいごに

Go言語で画像処理を行うシリーズ第三弾として、エッジ検出 X方向の微分及びY方向の微分を紹介しました。

結構シンプルな処理で実現できましたが、ノイズがのってしまいました。

いつか、このノイズを取る方法も説明しますね!

ではでは!

コメント

  1. […] 先日、X方向Y方向微分の記事を掲載しましたが、本日は平滑化処理を紹介します! […]

  2. […] 【画像処理】Go言語で輪郭抽出!X方向Y方向微分【サンプルコード付き】こ… […]

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