Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Python/Javascriptで読む点群
Search
Taro Matsuzawa aka. btm
November 08, 2020
Programming
5.4k
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
640
平成生まれのためのUNIX&IT歴 史講座 ~番外編~
smellman
2
580
掛川城の点群データをiTownsで表示しよう
smellman
0
360
そのJavascript、全部TypeScriptにしちゃえ
smellman
1
260
大容量SSDとOpenStreetMap
smellman
0
180
MapLibreとtile.openstretmap.jpで始めるベクトル地図プログラミング
smellman
1
660
国内向けタイルサーバの構築と運用について
smellman
0
1.8k
日本のCommunity向け タイルサーバの現状
smellman
0
2.7k
Pythonで点群を読んでみよう
smellman
1
2.9k
Other Decks in Programming
See All in Programming
New "Type" system on PicoRuby
pocke
1
980
JJUG CCC 2026 Spring: JSpecify で実現する Kotlin フレンドリーな Java API 設計
ternbusty
1
180
RTSPクライアントを自作してみた話
simotin13
0
610
Language Server 使ってる? 〜VSCode と Zed の場合〜 / Are you using a Language Server? ~For VS Code and Zed~
handlename
0
790
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
250
技術的負債解消で開発者の未来を開く- AIの力でコード刷新
kmd2kmd
0
110
Lessons from Spec-Driven Development
simas
PRO
0
210
AI 時代のソフトウェア設計の学び方
masuda220
PRO
29
13k
フロントエンドとバックエンドで「1文字」を揃えよう
youkidearitai
PRO
0
710
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
270
Skillsは効率化、Agentsは"自分の拡張"——Builder時代のエージェント編成(CC Night 2026)
wemra
1
140
net-httpのHTTP/2対応について
naruse
0
500
Featured
See All Featured
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
180
Deep Space Network (abreviated)
tonyrice
0
210
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
A Modern Web Designer's Workflow
chriscoyier
698
190k
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
250
The Mindset for Success: Future Career Progression
greggifford
PRO
0
360
KATA
mclloyd
PRO
35
15k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
750
How STYLIGHT went responsive
nonsquared
100
6.2k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
540
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 まとめ