[Bubble://ちずろぐ/別館/]

別館 ではGISに関する情報を掲載しています。

[Bubble://ちずろぐ/別館/KaMap/]

MapserverのAJAX版UI,ka-Mapのデモです。

[Bubble://旧日記/]

旧本館。更新していません。

« 構想中 | トップページ | GRASS GISその2 »

2005年10月 7日 (金)

GRASS GISその1

GRASSは"Geographic Resources Analysis Support System"の略。
最初にお世話になったオープンソースGISソフト。

公式サイトはここ

もともとはラスタ解析用のソフトだが,最近はベクタ解析も充実しつつあるような感じ。
GUIも用意されているが,各機能は全てコマンドプログラムとなっており,やりたいことはコマンドを組み合わせたシェルスクリプトとして書いて自動化するっていうのが本来の使い方。

Unix流のシェルスクリプトや地形解析やGIS関連の知識をある程度持った人じゃないと使いにくい(使いこなせない)と思う。

最初に仕事で使ったのは,マルチバンドリモートセンシングデータの有効活用ネタを探すこと。

一番使ったのは,平成13年にできた土砂災害対策法関連で某県より発注された傾斜区分図作成。
これは,図化機やレーザープロファイラで取得した地形標高値より生成した10mメッシュ地形標高データから,2度以下と30度以上の傾斜のあるエリアを抽出してポリゴン化する作業。

ちなみに土砂災害防止法とは急傾斜地の崩壊(崖崩れ),土石流の発生する可能性のおそれのある区域を指定し,都市計画・宅地建物取引業・建築基準・住宅金融公庫各法と連携して,人的物的被害を最小限に抑えて行こうというもの。
一般の人には今後ハザードマップという形で目にする機会があると思う。

傾斜区分図はエリア指定作業を行うための基本的な資料となるもの。

大体以下の様な感じで,1:2,500レベルの図郭100毎程度の量を自動化してました。
そのまま使っても多分動かないですが。

elevation_all_hosei.dem=min(elevation_all.dem[-1,-1],\
                            elevation_all.dem[0,-1], \
                            elevation_all.dem[1,-1], \
                            elevation_all.dem[-1,0], \
                            elevation_all.dem[0,0],  \
                            elevation_all.dem[1,0],  \
                            elevation_all.dem[-1,1], \
                            elevation_all.dem[0,1],  \
                            elevation_all.dem[1,1])
#傾斜計算
slope_ns_all_hosei=atan((elevation_all_hosei.dem[-1,0]-\
                         elevation_all_hosei.dem[1,0])/20)
slope_ew_all_hosei=atan((elevation_all_hosei.dem[0,-1]-\
                         elevation_all_hosei.dem[0,1])/20)
#絶対値変換
slope_ns_abs_all_hosei=abs(slope_ns_all_hosei)
slope_ew_abs_all_hosei=abs(slope_ew_all_hosei)
#最大勾配
slope_max_all_hosei=max(slope_ns_abs_all_hosei,\
                        slope_ew_abs_all_hosei)
#2度以下エリアの属性値を1にセット
deg2_all_hosei=(slope_max_all_hosei <= 2.0)
#30度以上エリアの属性値を1にセット
deg30_all_hosei=(slope_max_all_hosei >= 30.0)

GRASS」カテゴリの記事

|

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/142859/6291740

この記事へのトラックバック一覧です: GRASS GISその1:

コメント

質問してよろしいですか。
50Mメッシュポリゴンの標高データを持ったシェープファイルがあります。ファイルは2次メッシュごとになっていて、日本全土です。
これをGRASSで読み込んで、ワールドファイル付き陰影図(標高の色分けと影つき)が作れますでしょうか。
画像形式はpngで大きさは50m角がいいです。

やろうとしていることは、いまあなたが公開しているKa-Mapの日本のところだけ切り取ったようなものです。

投稿: Yu-Gotou | 2006年11月25日 (土) 15時51分

こんにちは。
 シェープファイルがPOINTデータであれば,GRASSの読み込みはv.in.ogr,サーフェス作成は(ラスタ化)v.surf.rst あるいは v.surf.bsplineあたりで標高ラスタ作成は可能だと思います。標高ラスタが作成できれば,色の設定・陰影付けも,もちろん可能です。
 PNG出力はr.out.pngで画像のみ可能ですがワールドファイル(.tfw)出力はr.out.tiffで対応しています。
 ご質問の中で50Mメッシュ"ポリゴン"とありますが,これは↓のように50m×50mの"POLYGON"が2次メッシュ内に並んでいるイメージでしょうか?
□□□...□
□□□...□
□□□...□
 上記のv.surf.rstやv.surf.bsplineは点やisoline(等高線)のベクタが前提となっているようなので,ポリゴンデータから地表面ラスタを作成してくれるかはなんともいえません。
 ちなみに,2次メッシュの50m標高データというと,国土地理院の数値地図50mメッシュ(標高)と同様の仕様ですよね?。仮にシェープファイルの大本がそれであれば,r.in.gdal で国土地理院の50mメッシュ標高データを直接読み込むことが可能です。
 国土地理院の50mメッシュ標高1図郭分を処理した画像(200×200pix)を一時的に以下においておきます。
http://bubble.atnifty.com/473027.png
http://bubble.atnifty.com/473027_shaded.png

投稿: bubble | 2006年11月25日 (土) 18時43分

早速のご回答ありがとうございました。
お察しのとおり、50Mメッシュポリゴンは数値地図から作ったものです。数値地図はポイントに標高データを持っているのですが、MapServerでそれに色をつけて表示するとズームインしたときにつぶつぶになってしまって見た目が悪いためポリゴンをタイルにしきつめた状態にして使っています。
http://www2.gtec-ni.com/pmapper/map.phtml
このサイトを見ていただいて、どこかにズームインしたあと、50Mメッシュポリゴンというレイヤをクリックしていただけば様子はわかっていただけると思います。
さらになぜラスタにして貼り付けなかったかというとポイントと同じことで、ズームインインしたときにボロボロになるのがいやだったからです。
この先どうしたいかというと、このレイヤを何割か透過しておいて、上にもう一枚陰影図を貼り付けたいということです。さすがにこちらはラスタにせざるを得ないと考えております。
>r.in.gdal で国土地理院の50mメッシュ標高データを直接読み込むことが可能です
は大変驚きました。当方まだGRASSをインストールさえしていない状況で、これから取り組もうとしています。恐縮ですが、サンプルで見せていただいた画像を作る手続きを教えていただけないでしょうか。

投稿: Yu-Gotou | 2006年11月27日 (月) 08時35分

 リンク先のサイト拝見しました。データ量が充実していますね!。私はSRTM+50m標高+5m標高と取り込んでいく予定ですが,なかなか作業が進んでいません...。

 陰影処理の流れですが,以下のリンクに書いてありますので参考にしてください。
http://bubble.atnifty.com/modules/bwiki/index.php?MEMonGRASS
 上記リンクには書いていないのですが,陰影処理を行う場合には,ファイルを1図郭づつ読み込んで処理を行うとエッジの部分がうまく処理されないので,ある程度周囲の図郭(あるいはデータ全て)も含めてマージした状態としr.regionで処理図郭を移動しながら行った方が良いかもしれません。あと陰影の強弱も傾斜方向だけではなく勾配角度(r.slope.aspectで勾配ラスタも出力可能)で重み付けする等,ある程度の試行錯誤も必要でしょう。この2点は私のka-Mapサイトの修正点でもありますが...。
 ちなみに,GDALの対応フォーマットは以下のページの表に"Japanese DEM (.mem)"という表現で載っています。
http://www.remotesensing.org/gdal/formats_list.html

投稿: bubble | 2006年11月27日 (月) 10時22分

ありがとうございます。ほしい画像(.png)が取り出せるようになりました。
ところで、いったいどのようにしたらバッチ処理で.MEMを加工できるのでしょうか。
なお、当方C言語などのスキルはありません。シェルスクリプトでできたらうれしいのですが。

投稿: Yu-Goto | 2006年12月 4日 (月) 15時02分

こんばんは。
 GRASSのコマンドは,shellの通常のバイナリコマンドやシェルスクリプトと同じものなので,そのままスクリプトとして記述すれば動きますね。
 ただし,GRASSを起動してプロンプトが表示された状態でないとパスが通ってないので注意が必要です。
 先に示したリンクの例をそのままスクリプトにすると↓のような感じでしょうか。(動作チェックはしていません)
=======================
#!/bin/sh

base_file_name=`basename $1 .mem`
# インポート
r.in.gdal input=$1 \
output=$base_file_name
g.region rast=$base_file_name
# 色設定
r.colors map=$base_file_name rules=srtm
# 傾斜方向計算
r.slope.aspect elevation=$base_file_name \
aspect=${base_file_name}_asp
# HIS合成
r.his h_map=$base_file_name \
i_map=${base_file_name}_asp \
r_map=${base_file_name}_R \
g_map=${base_file_name}_G \
b_map=${base_file_name}_B
# RGB合成
r.composite red=${base_file_name}_R \
green=${base_file_name}_G \
blue=${base_file_name}_B \
output=${base_file_name}_shaded
# Tiff(tfw付き)出力
r.out.tiff -t \
input=${base_file_name}_shaded \
output=${base_file_name}_shaded \
compression=packbit
=======================

投稿: bubble | 2006年12月 4日 (月) 18時01分

GRASSのシェルが普通のシェルと同じように使えることが、まったくわかりませんでした。おかげさまで、スクリプトは動かせました。
ところで、このスクリプトで.MEMから.pngを作ると問題点が二つあります。

その1. r.slope.aspectすると200px角の画像の周囲に1pxのすき間ができる。並べたときに境目ができるため、198px角に切らないと使えない。
その2. 標高-9999(海)のところはr.slope.aspectすると黒になってしまう。

もし解決策がお分かりなりましたら、ご教示願います。

画像をアップしておきました。
http://www2.gtec-ni.com/dem/654153_srtm.png
http://www2.gtec-ni.com/dem/654153_asp.png
http://www2.gtec-ni.com/dem/654153_shared.png

投稿: Yu-Goto | 2006年12月 7日 (木) 15時23分

コメントがかなり遅れてしまいました。申し訳ないです><。

問題点は二つとも私のka-Mapの保留事項ですし,
もう解決されたかもしれませんが...。

その1:r.slope.aspectは着目しているセルの周囲(たしか)8近傍を使用して角度や方向を算出しているので,エッジ部のセルは計算がうまくいかないですね。境目を出さないようにするには,あらかじめ隣接する図郭も(ディスク容量が問題なければ全て)読み込んで,r.patchで図郭を一つにマージ。計算は一括 or g.region で図郭を移動しながら行う,という感じになると思います。

その2:数値地図だと海部は-9999の値で認識できますので,r.mapcalcのif文で値を変えることで対応できそうです。
shaded = if(elev==-9999, 変更値, shaded)
という感じでしょうか。
r.mapcalcは与えた式を各セル毎に計算し,新しいデータを作成します。上の式だと標高ラスタデータのセルが-9999なら値を変更それ以外は陰影ラスタの値をそのまま使用するという処理になります。

投稿: bubble | 2006年12月14日 (木) 21時58分

一番外の1ピクセルが白になるのも納得できました。ありがとうございます。
ただ、ずらしながらというのもめんどうそうですね。GRASSのほうで1ピクセル内側と同じ色をつけてくれればいちばんうれしいです。厳密に傾斜を表現しようと思っているわけではないので。

投稿: Yu-Goto | 2006年12月16日 (土) 16時00分

以下のような感じでよさそうですね。
====================================
# 数値地図読み込み
r.in.gdal input=/var/local/gis2/japanese_mem/473001.mem output=473001_elv
# 図郭設定
g.region rast=473001_elv
# 色指定(rules=...でパターンを設定)
r.colors map=473001_elv rules=srtm
# 傾斜方向データ作成
r.slope.aspect elevation=473001_elv aspect=473001_asp_pre
# エッジ部の欠落を一つ内側のセル値で埋める
r.mapcalc "473001_asp_nedge=if(isnull(473001_asp_pre), 473001_asp_pre[1, 0], 473001_asp_pre)"
r.mapcalc "473001_asp_eedge=if(isnull(473001_asp_nedge),473001_asp_nedge[0, -1],473001_asp_nedge)"
r.mapcalc "473001_asp_sedge=if(isnull(473001_asp_eedge),473001_asp_eedge[-1, 0],473001_asp_eedge)"
r.mapcalc "473001_asp_wedge=if(isnull(473001_asp_sedge),473001_asp_sedge[0, 1], 473001_asp_sedge)"
# 海部の値変更(方向角180度で白になる)
r.mapcalc "473001_asp=if(473001_elv<-999, 180, 473001_asp_wedge)"
# rules=aspect でグレースケールに変更
r.colors map=473001_asp rules=aspect
# 陰影用画像処理
r.his h_map=473001_elv i_map=473001_asp r_map=473001_R g_map=473001_G b_map=473001_B
# 作成したRGB画像を合成
r.composite red=473001_R green=473001_G blue=473001_B output=473001_shd
# 画像出力
r.out.tiff -t input=473001_asp output=473001_aps.tif compression=packbit
r.out.tiff -t input=473001_shd output=473001_shd.tif compression=packbit
# 一時ファイル削除
g.remove rast=473001_asp_pre
g.remove rast=473001_asp_nedge
g.remove rast=473001_asp_eedge
g.remove rast=473001_asp_sedge
g.remove rast=473001_asp_wedge
g.remove rast=473001_R
g.remove rast=473001_G
g.remove rast=473001_B
====================================

一括する場合だと...

最初にr.patchで一つにすることを試みたのですが...上限ファイル数が200なので×。これはソースファイルのマクロ(MAXFILES)を書き換えればよさそうですが,とりあえず保留。
あとはr.mapcalcのmax()を使うとか,gdalwarpコマンドやgdal_merge.pyコマンドでモザイクする手もありそうですが...さすがに私も面倒くさくなってきたので...^^;。
隣接するセルで埋める方法が上に上げたスクリプトです。

以下,ポイントとしては...

標高データを読み込んだときのファイル名を数字だけにするとr.mapcalcで数値かデータかが分からないので,_elvをサフィックスとしてつけています。

r.mapcalcでセルのインデックス指定。このエントリでも使ってますが[-1, -1]とう感じで着目しているセルの周囲を相対座標で指定して,北端セルは一つ南のセルの値...という処理で北東南西の順に埋めています。
インデックス指定の詳細は
http://www.sci.osaka-cu.ac.jp/~masumoto/vuniv2000/gis07.html
の[近傍表現]の項に分かり易い説明があります。

ついでに海部に方向角180を与えて,最終的に白になるようにしています。
インポートした段階で標高がメートル単位に置き換わるので(-9999は-999.9),r.mapcalcで "< -999"で判定しています。==だと誤差の関係でうまくいかないので。
これはaspectデータのみをいじった処理なので_elvデータの海部の白と_aspの白~黒の合成ということで,グレースケールに限定されますが...

元の_elvデータの海部に青色を付けたい場合には...
r.hisの直前あたりでelvデータの-999.9自体を-500以上にあげる。(rules=srtmでは-50~-500の範囲で純粋に青系の色)
これはr.colorsのマニュアルとrules=srtmを適用したカラー設定(GRASSのデータディレクトリ以下にcolrとディレクトリがあって,そこに標高データと同名の色設定テキストファイルがあります)
あたりを見るとイメージがつかめると思います。

それでは。

投稿: bubble | 2006年12月18日 (月) 17時30分

追加の余談ですが。

r.colros rules=... で指定するカラーテーブルは,あらかじめGRASS側で設定した値ですが。
この値は GRASS_INSTALL_DIR/etc/colors/ 以下にテキストデータとしてセットされています。
rules=srtm として設定したファイルもここにあります。

このディレクトリに例えば以下のようなファイルを保存します。
ファイル名:japanese_mem
====内容ここから↓====
-1000 0 0 205
0 aqua
0.1 57 151 105
100 117 194 93
200 230 230 128
500 202 158 75
1000 214 187 98
2000 185 154 100
3000 220 220 220
5000 250 250 250
8850 255 255 255
nv white
====↑ここまで====

ファイル名: shade_by_aspect
====内容ここから↓====
0% gray
50% white
100% gray
====↑ここまで====

の2つのファイルを保存すると

r.colors rules=japanese_mem
r.colors rules=shade_by_aspect

という具合に,独自の設定を指定することが出来ます。

ちなみに上記の japanese_mem は
数値地図の-999.9 が青色になる設定

shade_by_aspectは

白~黒の配色を白~灰に変えて若干明るめの標高図とする設定(r.slope.aspectは傾斜勾配データに自動的にrules=aspectを割り当てています)

になります。それぞれ既存のsrtm, aspectファイルと比較すると分かり易いと思います。

特にsrtmは全世界規模の標高色なので最高値が8000mを越えていますが,japanese_memの最高値を3800mあたりに抑える範囲で割り当てをしなおせば,もう少し標高の変化が分かり易くなるかもしれません。

投稿: bubble | 2006年12月18日 (月) 18時32分

おかげさまで4718枚のpngファイルを作れました。GoogleMapの上にオーバーレイしてみました。ただしおそろしくのろのろなので、表示するズーム範囲を限定してあります。
http://www2.gtec-ni.com/openlayers/gmap.html

投稿: Yu-Goto | 2006年12月21日 (木) 10時16分

コメントを書く