Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Python/Javascriptで読む点群
Search
Taro Matsuzawa aka. btm
November 08, 2020
Programming
5.5k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Python/Javascriptで読む点群
FOSS4G 2020 Japan Online
Taro Matsuzawa aka. btm
November 08, 2020
More Decks by Taro Matsuzawa aka. btm
See All by Taro Matsuzawa aka. btm
OpenLayers ext TypeScript declarationの開発
smellman
0
670
平成生まれのためのUNIX&IT歴 史講座 ~番外編~
smellman
2
610
掛川城の点群データをiTownsで表示しよう
smellman
0
370
そのJavascript、全部TypeScriptにしちゃえ
smellman
1
280
大容量SSDとOpenStreetMap
smellman
0
180
MapLibreとtile.openstretmap.jpで始めるベクトル地図プログラミング
smellman
1
680
国内向けタイルサーバの構築と運用について
smellman
0
1.9k
日本のCommunity向け タイルサーバの現状
smellman
0
2.8k
Pythonで点群を読んでみよう
smellman
1
2.9k
Other Decks in Programming
See All in Programming
[ハンズオン]AIへの指示だけで「五目並べ」を作ってみよう
satoshi256kbyte
1
370
難しいけど、読めた。- OSSの入口に立った話。
sts11142
0
150
Agents on Rails - Rails at Scale 2026
irinanazarova
0
530
Java 27新機能 / Java 27 new features
kishida
2
220
カツオ、ご期待ください
suneo3476
0
170
ソニーのクラウド共通基盤の変遷とAI時代の開発スタイルに合わせた進化 / The Journey of Sony’s Common Cloud Platform and Its Evolution for AI-Native Development
kenjiyoneyama
0
250
UnityでSystem.Net.WebSocketsなWebSocketサーバが動かないのでUnity Monoのコードを覗いてみた / about implementing websocket server with unity mono
drumath2237
1
580
コードレビューのボトルネックを"する側"と"される側"の両面から解消する
yub0n
2
1.6k
Androidだけじゃない、DroidKaigiで広がった私の技術スタック
akkeylab
0
120
【加筆修正版】Laravel のアプリケーションをどこにデプロイするか #phpcon_ehime
akase244
0
150
モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった ? / is-the-business-domain-the-real-complexity
hatsu38
0
460
Apple Intelligence を用いた個人情報誤送信防止、及びユーザーリクエスト体験の改善について
yukiny
0
330
Featured
See All Featured
[RailsConf 2023] Rails as a piece of cake
palkan
59
7.1k
Amusing Abliteration
ianozsvald
1
340
The Curious Case for Waylosing
cassininazir
1
560
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
2
2.9k
A better future with KSS
kneath
240
18k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Speed Design
sergeychernyshev
33
2.2k
A Modern Web Designer's Workflow
chriscoyier
699
190k
GraphQLとの向き合い方2022年版
quramy
50
15k
Rails Girls Zürich Keynote
gr2m
96
14k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
480
Building AI with AI
inesmontani
PRO
1
1.3k
Transcript
FOSS4G 2020 Japan Online 松澤太郎 Python/Javascriptで 読む点群
自己紹介
タイル三兄弟の一味 Twitter: @smellman Georepublic シニアデベロッパ、日本UNIXユーザ会理事、OSGeo日本支部理事、 OpenStreetMap Foundation Japanメンバー React NativeとかRuby
on RailsとかPythonとかやってる地理系プログラマー ブレイクコアクラスタ 自己紹介
A Location Technology Company
None
None
Open Source GISを得意とする会社 東京、神戸、ミュンヘンにオフィスがあります 神戸オフィスはちょっとエモいので神戸に来たら遊びに来るといいよ さまざまな国や地域のエンジニアが参加 お仕事待ってます(^^ Georepublic
弊社社長が政府CIO補佐官に 政府がハックされる事態に 乞うご期待! News
バイナリの読み方は仕様がわかっていれば(比較的)簡単 (比較的)簡単であることさえ知られてないのでは? 簡単なフォーマットから始めればいろいろ応用が効く バイナリが読めれば書けるようにもなる オレオレVector Tileなんかも作れちゃう(俺は作ったことがある) なぜバイナリを読む?
点群とは(さくっと) Pythonで読む https://github.com/smellman/python_lasreader_example Javascriptで読む https://github.com/smellman/javascript_lasreader_example 今日のお題
点群とは
地理で使われるデータの一種 レーザー測量やSfMなどで得られたPoint Data群 Point Cloudという 3Dでの地図表現でよく使われるデータ 最近では自動運転とかSmartうんたらかんたら 点群とは https://tiles.smellman.org/kakegawa/index-itowns.html
las(LASer format)及びlaz(zip圧縮したもの)が有名 lasの仕様書は公開されている https://www.asprs.org/wp-content/uploads/2010/12/LAS_1_4_r13.pdf las1.2〜1.4が一般的に使われている バージョンの違いはヘッダー及び扱えるものの差 フォーマット
Potree 独自のストラクチャを持つもの。専用のコンバータ PotreeConverter を使う。 一時期PotreeConverterが商用ソフトになった(現在はBSDライセンス)。 Cesium or iTown or giro3d
3D Tiles に対応。OSSのコンバータでは entwine か py3dtiles が有名。 点群を表示するWebライブラリ
lasデータは仕様が公開されている 静岡県がlasデータをたくさん公開している Creative Commons License 4.0 バイナリを読むプログラムを書くのに良い題材となる 今回はヘッダーを読むプログラムを見て雰囲気を掴んでほしい 今回の本題
Pythonで読む
Pythonに限らずだいたいのプログラミング言語には標準でバイナリを読むモジュールがある Pythonの場合 struct を利用する https://docs.python.org/ja/3/library/struct.html Pythonで読む
lasの仕様書を手元に置きます import struct をします open(file_path, ‘rb’) でファイルを開きます rb = read
only, binary structで一つずつ読み込んでいきます 読み方
こんな感じのコードになります 先頭を読む import struct f = open(‘your.las’, ‘rb’) file_signature =
b"".join(list(struct.unpack('4c', f.read(1*4)))).decode(‘ascii') print(file_signature) f.close() # 閉じておく
こんな感じのコードになります File Source IDを読む import struct f = open(‘your.las’, ‘rb’)
file_signature = b"".join(list(struct.unpack('4c', f.read(1*4)))).decode(‘ascii') (file_source_id,) = struct.unpack(‘H’, f.read(2)) print(file_source_id) f.close() # 閉じておく tupleで返ってくるので注意
f.read関数はファイルを読む開始位置をずらしていきます 例えば二回f.readを使うと… f.read(4) f.read(3) 開始位置が7へ移動する read関数 read(4) 0 read(3) N
struct.unpackで読んだバイナリをどのようにアサインするかを決める struct.unpack('4c', f.read(1*4)) char[4] struct.unpack('<L', f.read(4)) unsinged long (リトルエンディアン) struct.unpack
Lasのフォーマットのドキュメントを読みながらひたすらstruct.unpackを並べていく 随時printするなりして問題ないかチェックする unit testを書いても良い わりと単純にPythonでは読むことができる 逆を言うとJavascriptはクセがすごい あとは突き合わせをしていく
こんな感じになる def header(self, f): file_signature = b"".join(list(struct.unpack('4c', f.read(1*4)))).decode('ascii') (file_source_id,) =
struct.unpack('H', f.read(2)) (global_encoding,) = struct.unpack('H', f.read(2)) (guid_data1,) = struct.unpack('<L', f.read(4)) (guid_data2,) = struct.unpack('H', f.read(2)) (guid_data3,) = struct.unpack('H', f.read(2)) guid_data4 = struct.unpack('<8B', f.read(1*8)) …
LASのversion minorによってヘッダの大きさが変わる LAS 1.2 -> 227byte LAS 1.3 -> 235byte
LAS 1.4 -> 375byte 必ずversion checkを入れること 読む上で注意点
ヘッダーにOffset to point dataという値があるので、ここに f.seek をして読み始める データそのものの読み方も仕様を読みながら。 実際の値はscale factorとoffsetの組み合わせになるとかもちゃんと仕様に書いてあるの で見逃さないこと。
点群そのものを読む
Javascriptで読む
今回はFile APIとFileReader APIを利用 ブラウザからファイルを読み込む用途を想定 時間があればデモします https://smellman.github.io/javascript_lasreader_example/ Javascriptで読む
FileReader APIにイベントハンドラを作成します blobファイルをsliceしたものをFileReader APIで読みます 次のoffsetを指定してまたsliceしてFileReader APIで読みます 次の(ry 読み方
sliceで読み取る範囲を指定して readAsArrayBufferで読み取る onloadイベントハンドラが読みとっ て、またreadAsArrayBufferを呼び 出して… イベントハンドラがバイナリを読 む責務を追っている 最後はreader.abort()をする ややこしい class
LasReader { constructor(blob) { this.blob = blob } read(callback) { let offset = 0 let reader = new FileReader() let slice = this.blob.slice(offset, 4) reader.onload = (e) => { if (offset == 0) { const file_signature = char_to_string(e.target.result) console.log(`file_signature: ${file_signature}`) offset = 4 slice = self.blob.slice(offset, 6) } else if (offset == 6) { … } else { reader.abort() // call reader.onloaded } reader.readAsArrayBuffer(slice) } reader.onloaded = () => { callback(…) } reader.readAsArrayBuffer(slice) // 開始 } }
こういう構造のケースはPromiseを使うと簡単に書くことができます async/await を使えばPythonっぽく書くこともできます Promiseを使おう
offsetとreaderをthisで参照可能に する onloadのときにresolveを呼ぶ sliceを作るサイズを引数にして、成 功時にoffsetに加算する Promise class LasParser { constructor(blob)
{ this.blob = blob this.offset = 0 this.reader = new FileReader() } readSlice(size) { return new Promise((resolve, reject) => { this.reader.onload = (e) => { this.offset += size resolve(e.target.result) } this.reader.onerror = (e) => { console.log('onerror') reject(e) } const slice = this.blob.slice(this.offset, this.offset + size) this.reader.readAsArrayBuffer(slice) }) }
async/await async read(target, callback) { let result = await this.readSlice(4)
const file_signature = char_to_string(result) result = await this.readSlice(2) const file_source_id = (new DataView(result)).getUint16() result = await this.readSlice(2) const global_encording = (new DataView(result)).getUint16(0, true) result = await this.readSlice(4) const guid_data1 = (new DataView(result)).getUint32(0, true) … const z = new DataView(result) const max_z = z.getFloat64(0, true) const min_z = z.getFloat64(8, true) this.reader.abort() callback(max_x, min_x, max_y, min_y) } await this.readSlice で何バイト読 むか指定 読まれたバイナリの処理の責務が すべてread関数になる 最後はthis.reader.abort()を実行 してcallbackを呼ぶ
DataViewなどの処理をするところが外だしできる Promiseを使わないとイベントハンドラ内なのでthisを使いまくるしかない Promiseを使えば変数はほぼconstで指定できるので安心できる letを使うのは一箇所ぐらい ヘッダ以外にもoffsetをずらせばbodyも簡単に読めるよ! Promiseの良いところ
Pythonではstructを使うと簡単にバイナリが読めるよ JavascriptはクセがあるけどPromise/async/awaitを使えば簡単に読めるよ 今回作ったプログラム(Las 1.2まで) https://github.com/smellman/python_lasreader_example https://github.com/smellman/javascript_lasreader_example まとめ