はじめに
本記事では、scikit-imageライブラリを使用して日本地図画像を都道府県ごとに分割する方法について解説します。具体的には、Sobelフィルタを用いた輪郭抽出、モルフォロジー演算による前処理、measure.labelによる領域ラベリングなどの技術を組み合わせて、都道府県境界を認識し個別に処理する方法を紹介します。
コード


解説
モジュールのインポート
画像の読み込み
用いる画像は下記サイトから取得しました。


img_cはRGB画像で、これをrgb2gray関数でグレースケール化したものをimageとします。
sobelフィルタの適用
Sobelフィルタを使用して画像の輪郭を抽出します。このフィルタを適用すると、画像は以下のように変化します。

sobelフィルタを適用した画像の2値化
値として0.04より小さい部分をTrueとすると以下のような画像が得られます。

ノイズの除去
2値化像にopening処理を適用することでノイズを除去します。この例では、opening処理を2回連続で適用しました。その結果、以下の画像が得られます。

画像のラベリング
measure.label関数を使用して先ほどの画像(openimg)にラベリングを行います。label2rgb関数によって、各ラベルにcmapsの色を割り当てて可視化します。結果は以下のとおりです。

重心とラベル番号の表示
regionprops(label_image)のcentroid属性を使用すると各ラベル領域の重心座標が得られます。この座標に赤丸とラベル番号を表示すると、下図のようになります。

ラベル領域を切り取って表示
regionprops(label_image).bboxを使用すると、各ラベル領域を囲む四角形の座標が得られます。下の図は、この座標を用いて画像を切り取り、一覧表示したものです。ただし、この表示方法では他の領域も周囲に混ざってしまうため、わかりにくい図になっています。

ラベリングした部分のみを切り取る
im_label = (licrop==region.label)で、ラベル番号が一致する部分のみをTrueとしたbool配列を取得します。この配列をもとのRGB画像と掛け合わせると、bool配列のTrue(値は1)の部分だけが残り、False(値は0)の部分は黒くなります。これにより、ラベリングした部分のみを抽出できます。以下に例を示します。

各都道府県を表示
すべてのラベリングした領域に上記の処理を行うことで各都道府県を分離できます。

まとめ
本記事では、scikit-imageのmorphologyモジュールのopening関数、measure.label関数、filters.sobel関数を使用して、日本地図画像から都道府県の境界を抽出し、各都道府県を異なる領域として識別する方法を解説しました。これらの技術は地図画像だけでなく、様々な画像セグメンテーション問題に応用できる基本的かつ強力な手法です。
参考



コメント