Julia と画像処理②〜画像のセグメンテーション(Seed Region Growing とFelzenszwalbアルゴリズム)〜

プログラミング言語「julia」を用いて画像処理を行います.インストールに続き,今回は画像のセグメンテーションのライブラリを用いて,セグメンテーションを行います.

目次

今回はjulia を用いて,画像のセグメンテーションを行います.
julia言語で画像処理を行うパッケージはあるのですが,あまり浸透していないようなので.
julia のインストールなどは以下の記事をご覧ください.

必要なパッケージのインストール

画像処理を行うために,画像を表示するライブラリをインストールします.
jupyter でプロットすることも出来ますが,色々理解を助けるために導入します.

ここでは,Plots というライブラリを導入します.

1. julia の起動

**********~> julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.0.2 (2018-11-08)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia>
install.jl

2. ] を押してPkg へ

(v1.0) pkg>
install.jl

3. パッケージのインストール

(v1.0) pkg> add Plots
(v1.0) pkg> add GR
(v1.0) pkg> add ImageSegmentation
install.jl

セグメンテーションの実装

それでは,セグメンテーションのサンプルプログラムを動かしていきます.
今回は,以下の画像を用いてセグメンテーションをします.

なお,この画像は最後に記載する参考文献のURLから手に入れることができます.

画像の表示

using Images, ImageView

img = load("./horse.jpg")
imshow(img)




画像の表示

セグメンテーションのプログラムを実行

using ImageSegmentation
seeds = [(CartesianIndex(126,81),1), (CartesianIndex(93,255),2), (CartesianIndex(213,97),3)]
segments = seeded_region_growing(img, seeds)
セグメンテーション

3. セグメンテーションした画像を表示します.

imshow(map(i->segment_mean(segments,i), labels_map(segments)));
画像表示

プログラムの解説

セグメンテーションをするとき,プログラムでは,seeds を3点設定しました.このseeds の点をまず見てみましょう.
using Plots
gr()
Plots 関数
そして,horse の画像の上にseeds点をプロットします.
x_arr = zeros(Float64, 3, 1)
y_arr = zeros(Float64, 3, 1)
for j in 1:3
    x_arr[j] = float64(seeds[j][1][1])
    y_arr[j] = float64(seeds[j][1][2])
end
Array
plot(img)
plot!(y_arr, x_arr,color = "red", marker="o", st=:scatter)
plot

このように代表点を設定しています.

なお,ここで用いているアルゴリズムは seeded_region_growing というアルゴリズムです.詳しくは読んでいないですが,指定した点から,領域を拡大していくようにして,同じような画素値の領域を作っていくアルゴリズムです.そのため 分割された領域を同じ領域として認識することができません

この問題点を解決するために,別のアルゴリズムが提案されています.

別のアルゴリズムの適用

今回は「Felzenszwalbアルゴリズム」というのを適用してみます.
このアルゴリズムで必要なパラメータは分割数に対応する「k」です.

Felzenszwalb アルゴリズムに関して詳しく知りたい方はこちら

http://irohalog.hatenablog.com/entry/2014/10/05/213948
segments = felzenszwalb(img, 10)
map(i->segment_mean(segments,i), labels_map(segments))
felzenszwalb

k の変化によってどのように結果が変わるか図示してみましょう.
k_arr = [3,5,10,20,50,100]
P = []
for k_i in 1:length(k_arr)
    k = k_arr[k_i]
    segments = felzenszwalb(img, k)
    p = plot(map(i->segment_mean(segments,i), labels_map(segments)), title = string("k=",k))
    push!(P, p)  
end
plot(P..., layout=(3,2))

図示

参考文献