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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
Lessons from Spec-Driven Development
simas
PRO
0
210
スマートグラスで並列バイブコーディング
hyshu
0
160
エージェンティックRAGにAWSで入門しよう!
har1101
8
1.7k
Semantic Version 単位で戦略を柔軟に変えて、パッケージアップデートを自動化する
daitasu
1
260
Vite+ Unified Toolchain for the Web
naokihaba
0
320
PHPで使える日時の表現と、その知り方 #frontend_phpcon_do
o0h
PRO
0
260
A2UI という光を覗いてみる
satohjohn
1
140
C# and C++ Interoperability - cho-dotnetnew
harukasao
0
260
Go1.27で導入されるジェネリクスメソッドでできること
mackee
0
140
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
270
Honoでのサプライチェーン侵害対策 〜 3つのライブラリに学ぶ
yusukebe
6
1.3k
Lemonade + Foundry Toolkit でお手軽アプリ開発
seosoft
1
360
Featured
See All Featured
The SEO identity crisis: Don't let AI make you average
varn
0
490
Designing for Timeless Needs
cassininazir
1
260
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
How to train your dragon (web standard)
notwaldorf
97
6.7k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.6k
Building AI with AI
inesmontani
PRO
1
1.1k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
290
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
How STYLIGHT went responsive
nonsquared
100
6.2k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
220
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 まとめ