Tutorial python lengkap untuk membuat sistem AI pembelajaran yang diawasi untuk segmentasi semantik data cloud titik LiDAR 3D yang tidak terstruktur

Memiliki keterampilan dan pengetahuan untuk menyerang setiap aspek pemrosesan point cloud membuka banyak ide dan pintu pengembangan. πŸ€– Ini seperti kotak peralatan untuk kreativitas penelitian 3D dan ketangkasan pengembangan. Dan pada intinya, terdapat ruang Kecerdasan Buatan luar biasa yang menargetkan pemahaman pemandangan 3D. 🏑

Hal ini sangat relevan karena pentingnya untuk banyak aplikasi, seperti mobil self-driving, robot otonom, pemetaan 3D, realitas virtual, dan Metaverse. Dan jika Anda ahli otomasi seperti saya, sulit menahan godaan untuk mencari cara baru untuk menjawab tantangan ini!

Tutorial ini bertujuan memberi Anda apa yang saya anggap sebagai landasan penting untuk melakukan hal itu: pengetahuan dan keterampilan kode untuk mengembangkan sistem Segmentasi Semantik Cloud Titik 3D.

Namun sebenarnya, bagaimana kita menerapkan segmentasi semantik? Dan seberapa menantangkah Pembelajaran Mesin 3D?

Izinkan saya menyajikan 201 kursus praktis yang jelas dan mendalam yang berfokus pada Pembelajaran Mesin 3D. Dalam tutorial ini, saya akan membahas secara tepat apa itu Pembelajaran Mesin 3D dan bagaimana kita dapat memanfaatkan kode python yang efisien untuk menghasilkan prediksi semantik untuk point cloud 3D yang tidak terstruktur.

Table of Contents
3D Scene Perception
βœ”οΈ 3D Sensors
βœ”οΈ 3D Scene Understanding
βœ”οΈ Classification
Semantics Addition Methods for 3D data
βœ”οΈ 3D Object Detection
βœ”οΈ 3D Semantic Segmentation
βœ”οΈ 3D Instance Segmentation
3D Predictions with Supervised learning
3D Python Workflow
βœ”οΈ Step 1: Definition and Data Curation
βœ”οΈ Step 2. Environment Set-up
βœ”οΈ Step 3. 3D Feature Engineering
βœ”οΈ Step 4. 3D Machine Learning
βœ”οΈ Step 5. Performance Analysis
Conclusion

Mari kita selami! 🀿

Persepsi Pemandangan 3D: Kata Pengantar AI

Mengenali objek 3D di LiDAR (yang merupakan singkatan dari Light Detection and Ranging) merupakan tantangan besar karena sifat kompleks dari data yang ditangkap 3D. Awan titik mentah yang diperoleh melalui teknik pemindaian 3D tidak terstruktur, tidak dimurnikan, tidak teratur, dan rentan terhadap pengambilan sampel yang tidak teratur sehingga membuat tugas pemahaman Pemandangan 3D menjadi menantang. Jadi apa yang harus kita lakukan? Apakah itu layak dilakukan? Ha, itu yang kami suka! Tantangan nyata!πŸ˜‰

πŸ‘€ Sensor 3D

Mari kita mulai dengan masukan ke sistem kita. Sensor 3D (LiDAR, Fotogrametri, SAR, RADAR, dan Kamera Penginderaan Kedalaman) pada dasarnya akan mendeskripsikan suatu pemandangan melalui banyak titik 3D di ruang angkasa. Ini kemudian dapat menampung informasi berguna dan memungkinkan sistem pembelajaran mesin yang menggunakan masukan ini (misalnya mobil dan robot otonom) untuk beroperasi di dunia nyata dan menciptakan pengalaman Metaverse yang lebih baik. Oke, jadi kita punya masukan dasar dari informasi sensorik, selanjutnya apa?

πŸ•οΈ Pemahaman Pemandangan 3D

Anda dapat menebaknya: Pemahaman adegan. Ini menggambarkan proses yang mempersepsikan, menganalisis, dan menguraikan interpretasi pemandangan 3D yang diamati melalui satu atau lebih sensor ini (Pemandangan bahkan bisa dinamis!). Pada dasarnya, prosedur ini terutama terdiri dari mencocokkan informasi sinyal dari sensor yang mengamati Pemandangan dengan β€œmodel” yang kami gunakan untuk memahami Pemandangan. Bergantung pada seberapa halus keajaibannya πŸ§™β€β™‚οΈ, model akan memungkinkan β€œpemahaman pemandangan” yang relevan. Pada tampilan tingkat rendah, teknik mengekstraksi dan menambahkan semantik dari data masukan yang mengkarakterisasi sebuah adegan. Apakah teknik ini punya nama?

🦘/πŸˆβ€β¬› Klasifikasi

Nah, apa yang secara klasik kita bahas dalam kerangka Pemahaman Pemandangan 3D adalah tugas Klasifikasi. Tujuan utama dari langkah ini adalah untuk memahami data masukan dan menafsirkan bagian-bagian berbeda dari data sensor. Misalnya, kita memiliki point cloud dari pemandangan luar ruangan, seperti jalan raya, yang dikumpulkan oleh robot otonom atau mobil. Tujuan dari Klasifikasi adalah untuk mengetahui bagian-bagian penyusun utama Pemandangan, sehingga mengetahui bagian mana dari titik awan ini yang merupakan jalan, bagian mana yang merupakan bangunan, atau di mana manusia. Dalam pengertian ini, ini adalah kategori keseluruhan yang bertujuan untuk mengekstraksi makna semantik tertentu dari data sensor kami. Dan dari sana, kami ingin menambahkan semantik pada rincian yang berbeda. πŸ‘‡

Metode Penambahan Semantik Klasik untuk data 3D

Seperti yang Anda lihat di bawah, menambahkan semantik ke adegan 3D dapat dilakukan melalui berbagai strategi. Ini belum tentu merupakan desain independen, dan kita sering kali dapat mengandalkan perakitan hybrid bila diperlukan.

Izinkan saya menjelaskan dengan lebih banyak tekstur masing-masing teknik ini.

πŸ“¦ Deteksi Objek 3D

Yang pertama akan mencakup teknik deteksi objek 3D. Ini adalah komponen penting untuk banyak aplikasi. Pada dasarnya, ini memungkinkan sistem untuk menangkap ukuran, orientasi, dan posisi objek di dunia. Hasilnya, kita dapat menggunakan deteksi 3D ini dalam skenario dunia nyata seperti Aplikasi Augmented Reality, mobil self-driving, atau robot yang melihat dunia melalui isyarat spasial/visual terbatas. Kubus 3D bagus yang berisi objek berbeda. Namun bagaimana jika kita ingin memperhalus kontur objek?

🏘️ Segmentasi Semantik 3D

Nah disinilah kita akan mengatasi masalah tersebut dengan teknik Segmentasi Semantik. Ini adalah salah satu tugas paling menantang yang memberikan label semantik ke setiap unit dasar (yaitu, setiap titik di awan titik) yang dimiliki oleh objek yang diteliti. Pada dasarnya, segmentasi semantik 3D bertujuan untuk menggambarkan objek yang ada dalam sebuah adegan dengan lebih baik. Deteksi Kotak Batas 3D pada steroid jika Anda mau. Oleh karena itu, ini berarti memiliki informasi semantik per poin. Kita bisa masuk jauh ke sana. Namun masih ada batasannya: kita tidak bisa secara langsung menangani objek berbeda per kategori (kelas) yang kita serang. Apakah kita juga mempunyai teknik untuk melakukan hal ini?

🏠 Segmentasi Instance 3D

Ya! Dan ini disebut segmentasi instans 3D. Ia memiliki penerapan yang lebih luas, mulai dari persepsi 3D dalam sistem otonom hingga rekonstruksi 3D dalam pemetaan dan kembaran digital. Misalnya, kita dapat membayangkan robot inventaris yang dapat mengidentifikasi kursi, mampu menghitung berapa jumlah kursi, lalu memindahkannya dengan memegang kaki keempatnya. Untuk mencapai tujuan ini memerlukan pembedaan label semantik yang berbeda serta contoh berbeda dengan label semantik yang sama. Saya akan memenuhi syarat segmentasi Instance sebagai langkah Segmentasi Semantik di Mega-Steroïds 😁.

Sekarang setelah Anda memiliki pemahaman dasar dan taksonomi metode saat ini untuk keluaran yang berbeda, pertanyaannya tetap: Strategi mana yang harus kita ikuti untuk memasukkan prediksi semantik? πŸ€”

Prediksi 3D dengan Pembelajaran yang Diawasi

Jika Anda masih di sana, maka Anda telah melewati charabia 3D mumble bumble, dan siap untuk memahami misi dengan uni-hornnya.πŸ¦„ Kami ingin mengekstrak informasi semantik dan memasukkannya ke dalam data 3D kami dalam bentuk awan titik. Untuk melakukan hal tersebut, kami akan memperdalam satu strategi yang membantu kami memperoleh informasi tersebut dari sensor. Kami akan fokus pada satu kelompok algoritma, metode pembelajaran yang diawasi β€” dibandingkan dengan metode tanpa pengawasan yang ditunjukkan di bawah.



Dengan metode pembelajaran yang diawasi, kami pada dasarnya menunjukkan contoh-contoh terklasifikasi tertentu ke sistem dari masa lalu. Artinya, kita perlu memberi label pada contoh-contoh ini. Dan untuk ini, Anda memiliki tutorial berikut:



Kemudian, kami menggunakan label untuk setiap elemen yang dipertimbangkan dalam Adegan agar dapat memprediksi label tentang data masa depan. Dengan demikian tujuannya adalah untuk dapat menyimpulkan data yang belum terlihat, seperti ilustrasi di bawah ini.

Namun bagaimana kita dapat menilai seberapa baik performa model yang dilatih? Apakah analisis visual cukup (apakah ini pertanyaan sebenarnya? πŸ™ƒ)

Analisis visual – sebut saja analisis kualitatif – hanyalah salah satu bagian dari jawabannya. Blok besar lainnya dilakukan melalui analisis kuantitatif yang dievaluasi menggunakan berbagai metrik yang akan menyoroti kinerja spesifik metode kami. Ini akan membantu kita mengkarakterisasi seberapa baik sistem klasifikasi tertentu bekerja dan memberi kita alat untuk memilih di antara berbagai pengklasifikasi untuk aplikasi.

Dan sekarang, teori (ringan) telah berakhir! Mari selami implementasi kode python yang menyenangkan dalam lima langkah🀲! Saya sarankan memiliki 🫐 mangkuk yang luar biasa.

1. Definisi Alur Kerja Pembelajaran Mesin 3D

Sumber Dataset Cloud Titik LiDAR Udara

Kamu tahu latihannya? Langkah pertama yang kami lakukan adalah menyelami web dan mencari data 3D yang menyenangkan! Kali ini, saya ingin mendalami tempat di Prancis (maaf karena terlalu sombong πŸ˜†) untuk menemukan kumpulan data LiDAR yang menarik: National Geography Institute (IGN) di Prancis. Dengan kampanye LiDAR HD, Prancis memulai pengumpulan OpenData di mana Anda bisa mendapatkan point cloud 3D yang tajam dari beberapa wilayah di Prancis! Dan di atas, beberapa memiliki label yang memudahkan untuk tidak memulai dari awal, seperti yang dapat Anda temukan pada tautan di bawah.



Namun untuk mempermudah tutorialnya, saya membuka portal di atas, memilih data yang mencakup sebagian kota Louhans (71), menghapus informasi georeferensi, menghitung beberapa atribut tambahan (yang akan saya jelaskan di tutorial lain 😜), dan kemudian menyediakannya di Buka Folder Drive Data saya. Data yang Anda minati adalah 3DML_urban_point_cloud.xyz dan 3DML_validation.xyz. Anda dapat membuka ekstrak Flyvast WebGL jika Anda ingin memvisualisasikannya secara online.

Strategi putaran keseluruhan

Saya mengusulkan untuk mengikuti prosedur sederhana yang dapat Anda tiru dengan cepat untuk melatih model pembelajaran mesin 3D dan menggunakannya pada aplikasi dunia nyata, seperti yang diilustrasikan di bawah ini.

πŸ€“ Catatan: Strategi ini adalah sedikit cuplikan dari salah satu dokumen yang diberikan pada kursus online yang saya selenggarakan di Akademi Geodata 3D. Tutorial ini akan mencakup langkah 4 hingga 8 + 10 + 11, langkah lainnya akan dibahas secara mendalam dalam kursus ini, atau dengan mengikuti salah satu tutorial melalui link dukungan ini.

2. Menyiapkan konteks python 3D kita

Dalam tutorial point cloud praktis ini, saya fokus pada penggunaan perpustakaan yang efisien dan minimal. Demi menguasai python, kami akan melakukan semuanya hanya dengan dua perpustakaan: Pandas, dan ScikitLearn. Dan kami akan melakukan keajaiban 😁. Lima baris kode untuk memulai skrip Anda:

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import MinMaxScaler

πŸ€“ Catatan: Seperti yang Anda lihat, saya mengimpor fungsi dan modul dari perpustakaan dengan cara yang berbeda. Untuk panda, saya menggunakan import module, yang memerlukan lebih sedikit pemeliharaan pernyataan import. Namun, bila Anda ingin kontrol lebih besar atas item modul mana yang dapat diakses, saya sarankan menggunakan from module import foo, yang memungkinkan lebih sedikit pengetikan untuk menggunakan foo.

Bagus! dari sana, saya mengusulkan agar kita secara relatif mengekspresikan jalur kita, memisahkan data_folder yang berisi kumpulan data kita dari nama dataset agar dapat beralih dengan mudah dengan cepat:

data_folder=”../DATA/”
dataset="3DML_urban_point_cloud.xyz"

Sekarang, kita dapat dengan cepat memuat dataset dalam variabel pcd menggunakan Pandas. Dan karena file asli tidak bersih dan berisi nilai NaN, kita akan menggunakan metode dropna yang sangat berguna inplace untuk memastikan kita memulai dengan kerangka data yang difilter dengan hanya baris lengkap. Namun, ini berarti kami akan kehilangan beberapa poin dalam prosesnya (<1% rekor), namun kali ini kami tidak keberatan dengan hal tersebut.

pcd=pd.read_csv(data_folder+dataset,delimiter=' ')
pcd.dropna(inplace=True)

πŸ€“ Catatan: Argumen inplace yang disetel ke True memungkinkan penggantian objek python secara langsung alih-alih membuat salinan kerangka data.

3. Seleksi dan Persiapan Fitur (Langkah 4)

Untuk memahami apa yang kami lakukan saat menggunakan kerangka Machine Learning, Anda harus memahami bahwa kami mengandalkan kumpulan fitur atau vektor fitur yang mewakili berbagai variasi. Dalam pendekatan kami, triknya adalah mengetahui dengan baik konteks di mana kami berevolusi dan menjadi kreatif dengan cara merekayasa fitur yang kami yakini akan menjadi deskripsi yang sangat baik tentang varians dalam data kami. Atau setidaknya membantu kita membedakan kelas-kelas yang diminati.

Saya memutuskan untuk membuat tutorial terfokus lainnya hanya pada langkah-langkah persiapan untuk mendapatkan fitur-fitur tersebut. Namun demi kesederhanaan, saya telah menghitung banyak di antaranya untuk Anda, disaring dengan tujuan utama agar relevan dengan tugas segmentasi semantik berikutnya.

Untuk memulai dengan dasar yang kuat, kami akan mengatur fitur-fitur kami di antara label, yaitu, apa yang akan kami coba prediksi, dan fitur, yaitu, apa yang akan kami gunakan untuk membuat prediksi. Dengan Pandas, kita dapat melakukannya dengan mudah dalam dua baris kode:

labels=pcd['Classification']
features=pcd[['X','Y','Z','R','G','B']]

Strukturasi kerangka data ini memungkinkan peralihan cepat ke serangkaian fitur terkait tertentu tanpa menggunakan indeks numerik. Jadi jangan ragu untuk kembali ke langkah ini dan mengubah kumpulan vektor features.

Memilih fitur

Pemilihan Fitur adalah metode mengurangi variabel masukan yang dimasukkan ke model Anda dengan hanya menggunakan variabel yang paling relevan dan menghilangkan gangguan dalam data. Ini adalah proses memilih fitur yang relevan untuk model pembelajaran mesin Anda berdasarkan jenis masalah yang ingin Anda selesaikan. Jika dilakukan secara otomatis, hal ini termasuk dalam proses AutoMLyang mengotomatiskan tugas penerapan pembelajaran mesin pada masalah dunia nyata.

Anda memiliki dua arah di sini. Anda bisa melakukannya sepenuhnya tanpa pengawasan (Misalnya, mengurangi korelasi dalam fitur Anda) atau dengan cara yang diawasi (Misalnya, ingin meningkatkan skor akhir model setelah mengubah fitur dan parameter).

Demi kesederhanaan, kami akan menyesuaikan pemilihan vektor fitur kami saat ini secara manual melalui arah yang diawasi: kami akan menjalankan eksperimen dan menyesuaikan jika hasilnya kurang baik. Siap? πŸ™‚

Mempersiapkan fitur-fiturnya

Setelah vektor fitur awal kita siap, kita dapat segera memprosesnya!πŸ’¨ atau bisakah? Berhati-hatilah! Bergantung pada Model Pembelajaran Mesin yang kami gunakan, kami mungkin menemui beberapa kejutan! Memang benar, mari kita ambil skenario sederhana.

Bayangkan vektor fitur pilihan kita adalah sebagai berikut:

features=pcd[['X','Y']]

Di sini, jika kita menggunakannya untuk melatih algoritma kita, maka kita akan terjebak pada rentang yang terlihat, misalnya, X bervariasi antara 0 dan 100. Jika, setelah pelatihan pada rentang ini, model diberi data masa depan dengan distribusi serupa tetapi rentang yang berbeda, misalnya X dari 1100 hingga 1200, maka kita bisa mendapatkan hasil yang sangat buruk, meskipun kumpulan datanya sama, hanya ada terjemahan di antaranya. Memang untuk beberapa model, nilai X yang berada di atas 100 dapat membuat model memprediksi nilai yang salah, padahal sebelumnya kita memastikan bahwa kita menerjemahkan data ke rentang yang sama seperti yang terlihat pada pelatihan. Prediksi tersebut akan memiliki peluang lebih besar untuk masuk akal.

Saya beralih ke konsep penskalaan dan normalisasi fitur. Ini adalah bagian penting dari tahap prapemrosesan data, tetapi saya melihat banyak pemula mengabaikannya (sehingga merugikan model pembelajaran mesin mereka). Sebuah kesalahan yang tidak akan kami lakukan! πŸ’ͺ

Karena kita berada dalam konteks spasial yang berat, cara yang baik untuk menghindari masalah generalisasi adalah dengan mengurangi ke apa yang kita sebut normalisasi Min-Max. Untuk ini, kita akan menggunakan fungsi MinMaxScaler:

from sklearn.preprocessing import MinMaxScaler
features_scaled = MinMaxScaler().fit_transform(features)

πŸ’‘ Petunjuk: MinMaxScaler() mengubah fitur dengan menskalakan dan menerjemahkan setiap fitur satu per satu agar berada dalam rentang tertentu, misalnya antara nol dan satu. Jika data Anda terdistribusi secara normal, maka Anda dapat menggunakan StandardScaler.

Penyiapan Pelatihan Pembelajaran Mesin 3D

Oke, kita punya vektor labels dan vektor features yang tepat. Sekarang, kita perlu mempersiapkan persiapan untuk tahap pelatihan. Untuk memulai, kami akan membagi kedua vektor β€” sambil menjaga kecocokan indeks yang tepat antara label dan fitur β€” untuk menggunakan sebagian untuk melatih model pembelajaran mesin dan sebagian lainnya hanya untuk melihat performanya. Kami menggunakan 60% data untuk pelatihan, dan 40% untuk melihat performa, keduanya diambil dari distribusi yang sama secara acak. Itu dibuat menggunakan fungsi train_test_split dari scikitlearn:

X_train, X_test, y_train, y_test = train_test_split(features_scaled, labels, test_size=0.4)

πŸ€“ Catatan: Kami menggunakan konvensi penamaan saat menangani data untuk tugas Machine Learning. X menunjukkan fitur (atau data) yang dimasukkan ke model dan y menunjukkan label. Masing-masing didekomposisi menjadi _train atau _test bergantung pada finalitasnya.

Kami kemudian membuat objek pengklasifikasi melalui:

rf_classifier = RandomForestClassifier()

πŸ€“Catatan: Pengklasifikasi di atas adalah pengklasifikasi Random Forest. Dalam satu kalimat, ini cocok dengan beberapa pengklasifikasi pohon keputusan pada berbagai sub-sampel fitur dan menggunakan rata-rata untuk meningkatkan akurasi prediksi dan kontrol over-fitting. Hal-hal menarik😁.

Setelah inisialisasi pengklasifikasi, kami menyesuaikan pengklasifikasi ke data pelatihan untuk menyesuaikan parameter intinya. Fase ini adalah fase pelatihan, yang dapat memakan waktu beberapa menit bergantung pada hyperparameter (yaitu parameter yang menentukan arsitektur model Machine Learning) yang kita gunakan sebelumnya (jumlah pohon, kedalaman):

rf_classifier.fit(X_train, y_train)

Dan pada akhirnya, voila! Kami memiliki model terlatih! Ya, semudah itu! Jadi, mengambil jalan pintas juga mudah. πŸ˜‰

Untuk tahap prediksi, apakah Anda memiliki label atau tidak, Anda perlu melakukan hal berikut:

rf_predictions = rf_classifier.predict(X_test)

Anda kemudian dapat memvisualisasikan hasil dan perbedaan dengan blok kode berikut yang akan membuat tiga subplot: kebenaran dasar data cloud titik 3D, prediksi, dan perbedaan antara keduanya:

fig, axs = plt.subplots(1, 3, figsize=(20,5))
axs[0].scatter(X_test['X'], X_test['Y'], c =y_test, s=0.05)
axs[0].set_title('3D Point Cloud Ground Truth')
axs[1].scatter(X_test['X'], X_test['Y'], c = rf_predictions, s=0.05)
axs[1].set_title('3D Point Cloud Predictions')
axs[2].scatter(X_test['X'], X_test['Y'], c = y_test-rf_predictions, cmap = plt.cm.rainbow, s=0.5*(y_test-rf_predictions))
axs[2].set_title('Differences')

dan jika Anda ingin memeriksa beberapa metrik, kita dapat mencetak laporan klasifikasi dengan sekumpulan angka menggunakan fungsi classification_report dari scikit-learn:

print(classification_report(y_test, rf_predictions))

Namun bukankah kita harus memahami arti setiap metrik? πŸ€”

4. Penyetelan Pembelajaran Mesin 3D (Langkah 5)

Performa dan Metrik

Kita dapat menggunakan beberapa metrik kuantitatif untuk menilai hasil segmentasi dan klasifikasi semantik. Saya akan memperkenalkan kepada Anda empat metrik yang sangat berguna untuk penilaian segmentasi semantik point cloud 3D: presisi, perolehan, skor F1, dan akurasi keseluruhan. Semuanya bergantung pada apa yang kita sebut benar-benar positif dan benar-benar negatif:

  • True Positive (TP): Pengamatan bernilai positif dan diprediksi positif.
  • False Negative (FN): Pengamatan positif tetapi diprediksi negatif.
  • True Negative (TN): Pengamatan bersifat negatif dan diprediksi negatif.
  • False Positive (FP): Pengamatan negatif tetapi diprediksi positif.

Akurasi Keseluruhan adalah ukuran umum pada semua pengamatan tentang kinerja pengklasifikasi untuk memprediksi label dengan benar. Presisi adalah kemampuan pengklasifikasi untuk tidak memberi label positif pada sampel yang negatif; penarikan kembali secara intuitif adalah kemampuan pengklasifikasi untuk menemukan semua sampel positif. Oleh karena itu, Anda dapat melihat presisi sebagai ukuran yang sangat baik untuk mengetahui apakah model Anda tepat dan penarikan kembali untuk mengetahui tingkat ketelitian yang Anda temukan pada semua objek per kelas (atau secara global). Skor F1 dapat diartikan sebagai rata-rata harmonik tertimbang dari presisi dan perolehan, sehingga memberikan ukuran yang baik tentang seberapa baik kinerja pengklasifikasi dengan satu angka.

πŸ€“Catatan: Metrik akurasi global lainnya bukanlah ukuran evaluasi yang tepat ketika frekuensi kelas tidak seimbang, seperti yang terjadi di sebagian besar skenario, baik dalam pemandangan alam di dalam maupun di luar ruangan, karena kelas dominan membiaskannya . Selanjutnya, skor F1 dalam eksperimen kami menunjukkan kinerja rata-rata pengklasifikasi yang diusulkan.

Pemilihan Model

Saatnya memilih Model Pembelajaran Mesin 3D tertentu. Untuk tutorial ini, saya membatasi pilihan pada tiga model Machine Learning: Random Forests, K-Nearest Neighbors, dan Multi-Layer Perceptron yang termasuk dalam kategori Deep Learning. Untuk menggunakannya, pertama-tama kita akan mengimpor fungsi yang diperlukan dengan yang berikut ini:

from sklearn.neighbors import RandomForestClassifier
rf_classifier = RandomForestClassifier()
from sklearn.neighbors import KNeighborsClassifier
knn_classifier = KNeighborsClassifier()
from sklearn.neural_network import MLPClassifier
mlp_classifier = MLPClassifier(solver='lbfgs', alpha=1e-5,hidden_layer_sizes=(15, 2), random_state=1)

Kemudian, Anda tinggal mengganti XXXClassifier() pada blok kode berikut dengan tumpukan algoritma yang diinginkan:

XXX_classifier = XXXClassifier()
XXX_classifier.fit(X_train, y_train)
XXX_predictions = XXXclassifier.predict(X_test)
print(classification_report(y_test, XXX_predictions, target_names=['ground','vegetation','buildings']))

πŸ€“Catatan: Untuk mempermudah, saya meneruskan ke classification_report daftar kelas pohon yang sesuai dengan tanah, vegetasi, dan bangunan yang ada di kumpulan data kami.

Dan sekarang ke tahap pengujian penggunaan ketiga classifier di atas dengan parameter sebagai berikut:

Train / Test Data: 60%/40% 
Number of Point in the test set: 1 351 791 / 3 379 477 pts
Features selected: ['X','Y','Z','R','G','B'] - With Normalization

Hutan Acak

Kita mulai dengan Hutan Acak. Semacam sulap pohon ajaib melalui algoritme ansambel yang menggabungkan beberapa pohon keputusan untuk memberi kita hasil akhir: akurasi keseluruhan 98%, berdasarkan dukungan 1.3 million points. Selanjutnya diuraikan sebagai berikut:

╔════════════╦══════════════╦══════════╦════════════╦═════════╗
β•‘  classes   β•‘    precision β•‘   recall β•‘   f1-score β•‘ support β•‘
╠════════════╬══════════════╬══════════╬════════════╬═════════╣
β•‘ ground     β•‘         0.99 β•‘     1.00 β•‘       1.00 β•‘  690670 β•‘
β•‘ vegetation β•‘         0.97 β•‘     0.98 β•‘       0.98 β•‘  428324 β•‘
β•‘ buildings  β•‘         0.97 β•‘     0.94 β•‘       0.96 β•‘  232797 β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•

πŸ€“Catatan: Tidak banyak yang bisa dikatakan di sini, karena ini memberikan hasil yang mengesankan. Titik-titik dasar hampir terklasifikasi dengan sempurna: penarikan 1.00 berarti bahwa semua titik yang termasuk dalam permukaan tanah telah ditemukan, dan presisi 0.99 berarti masih ada sedikit margin perbaikan untuk memastikan tidak ada Positif Palsu. Kami juga melihat bahwa kesalahan tersebar sedikit di mana-mana, yang dapat menjadi masalah jika harus diperbaiki secara manual.

K-NN

Pengklasifikasi K-Nearest Neighbors menggunakan kedekatan untuk membuat prediksi tentang pengelompokan titik data individual. Kami memperoleh akurasi global 91%, yang selanjutnya diuraikan sebagai berikut:

╔════════════╦══════════════╦══════════╦════════════╦═════════╗
β•‘  classes   β•‘    precision β•‘   recall β•‘   f1-score β•‘ support β•‘
╠════════════╬══════════════╬══════════╬════════════╬═════════╣
β•‘ ground     β•‘         0.92 β•‘     0.90 β•‘       0.91 β•‘  690670 β•‘
β•‘ vegetation β•‘         0.88 β•‘     0.91 β•‘       0.90 β•‘  428324 β•‘
β•‘ buildings  β•‘         0.92 β•‘     0.92 β•‘       0.92 β•‘  232797 β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•

πŸ€“ Catatan: Hasil ini lebih rendah dibandingkan Random Forests, yang diharapkan karena kita lebih rentan terhadap kebisingan lokal di ruang vektor saat ini. Kami memiliki keseimbangan presisi/recall yang homogen di semua kelas, yang merupakan pertanda baik bahwa kami menghindari masalah overfitting. Setidaknya dalam distribusi saat ini 😁.

Pembelajaran Mendalam 3D dengan Perceptron Multi-Lapisan

Multi-Layer Perceptron (MLP) adalah algoritma Neural Network yang mempelajari hubungan data linier dan non-linier. MLP memerlukan penyetelan beberapa hyperparameter, seperti jumlah neuron tersembunyi, lapisan, dan iterasi, sehingga sulit untuk mendapatkan performa tinggi secara langsung. Misalnya, dengan set hyperparameter, kita memiliki akurasi global 64% yang selanjutnya didekomposisi sebagai berikut:

╔════════════╦══════════════╦══════════╦════════════╦═════════╗
β•‘  classes   β•‘    precision β•‘   recall β•‘   f1-score β•‘ support β•‘
╠════════════╬══════════════╬══════════╬════════════╬═════════╣
β•‘ ground     β•‘         0.63 β•‘     0.76 β•‘       0.69 β•‘  690670 β•‘
β•‘ vegetation β•‘         0.69 β•‘     0.74 β•‘       0.71 β•‘  428324 β•‘
β•‘ buildings  β•‘         0.50 β•‘     0.13 β•‘       0.20 β•‘  232797 β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•

πŸ€“ Catatan: Metrik MLP sengaja memberikan contoh yang baik tentang apa yang dianggap sebagai metrik buruk. Kami memiliki skor akurasi yang lebih rendah dari 75%, yang sering kali menjadi metrik langsung yang ditargetkan, dan kemudian kami melihat perbedaan yang signifikan antara Intra dan antar kelas. Khususnya, kelas bangunan masih jauh dari kata kokoh, dan kita mungkin mengalami masalah overfitting. Secara visual, hal ini juga ditemukan, karena kita dapat melihat bahwa ini adalah sumber utama kebingungan tentang model Pembelajaran Mendalam.

Pada langkah ini, kami tidak akan melakukan perbaikan melalui pemilihan fitur, namun kami selalu memiliki kemungkinan ini. Kami memutuskan untuk menggunakan model dengan kinerja terbaik pada langkah ini, pendekatan Random Forest. Dan sekarang, kita harus menyelidiki apakah model yang saat ini dilatih memiliki kinerja yang baik dalam skenario menantang yang belum pernah terjadi sebelumnya, siap? πŸ˜„

5. Kinerja Pembelajaran Mesin 3D: Menuju Generalisasi

Sekarang menjadi rumit. Melihat apa yang ada di atas, kita mungkin berada dalam masalah besar jika ingin menskalakan model saat ini ke aplikasi dunia nyata yang memperluas cakupan kumpulan data sampel saat ini. Jadi, mari kita mulai menerapkan model ini secara menyeluruh.

Kumpulan data validasi

Ini adalah konsep penting yang saya usulkan untuk memastikan menghindari masalah overfitting. Daripada hanya menggunakan kumpulan data pelatihan dan kumpulan data pengujian dari distribusi yang sama, saya yakin sangat penting untuk memiliki kumpulan data lain yang tidak terlihat dengan karakteristik berbeda untuk mengukur kinerja di dunia nyata. Karena itu, kami memiliki:

  • Data Pelatihan: Sampel data yang digunakan agar sesuai dengan model.
  • Data Uji: Sampel data yang digunakan untuk memberikan evaluasi yang tidak bias terhadap model yang dipasang pada data pelatihan, tetapi digunakan untuk menyesuaikan hyperparameter model dan vektor fitur. Oleh karena itu, evaluasi menjadi sedikit bias karena kami menggunakannya untuk menyesuaikan parameter masukan.
  • Data Validasi: Sampel data yang tidak berkorelasi digunakan untuk memberikan evaluasi yang tidak bias terhadap model akhir yang disesuaikan dengan data pelatihan.

Berikut adalah beberapa catatan klarifikasi tambahan:

  • Kumpulan data pengujian juga dapat berperan dalam bentuk persiapan model lainnya, seperti pemilihan fitur.
  • Model akhir mungkin cocok dengan kumpulan data pelatihan dan validasi, namun kami memutuskan untuk tidak melakukannya.

Data validasi yang dipilih berasal dari kota Manosque (04), yang menyajikan konteks perkotaan yang berbeda, topografi yang berbeda, dan konteks perkotaan yang sangat berbeda, misalnya seperti terlihat di bawah ini. Dengan cara ini, kami meningkatkan tantangan untuk mengatasi Generalisasi πŸ˜†.

Anda dapat mengunduh kumpulan data 3DML_validation.xyz dari Buka Folder Drive Data saya jika belum selesai. Seperti yang dijelaskan di bawah, Anda juga akan menemukan label untuk mempelajari metrik dan potensi keuntungan pada berbagai iterasi yang saya buat.

Meningkatkan hasil Generalisasi

Tujuan kami adalah memeriksa hasil kumpulan data validasi dan melihat apakah kami mengabaikan beberapa kemungkinan.

Pertama, kita mengimpor data validasi dalam skrip kita dengan tiga baris kode berikut:

val_dataset="3DML_validation.xyz"
val_pcd=pd.read_csv(data_folder+dataset,delimiter=' ')
val_pcd.dropna(inplace=True)

Kemudian, kita menyiapkan vektor fitur agar memiliki fitur yang sama dengan yang digunakan untuk melatih model: tidak kurang, tidak lebih. Kami selanjutnya menormalkan vektor fitur agar berada dalam kondisi yang sama dengan data pelatihan kami.

val_labels=val_pcd['Classification']
val_features=val_pcd[['X','Y','Z','R','G','B']]
val_features_scaled = MinMaxScaler().fit_transform(val_features)

Lalu kami menerapkan model yang sudah dilatih ke data validasi, dan kami mencetak hasilnya:

val_predictions = rf_classifier.predict(val_features_scaled)
print(classification_report(val_labels, val_predictions, target_names=['ground','vegetation','buildings']))

Hal ini menghasilkan akurasi akhir sebesar 54% untuk 3.1 million poin (dibandingkan 98% untuk data pengujian yang berisi 1.3 million poin) yang terdapat dalam kumpulan data validasi. Itu didekomposisi sebagai berikut:

╔════════════╦══════════════╦══════════╦════════════╦═════════╗
β•‘  classes   β•‘    precision β•‘   recall β•‘   f1-score β•‘ support β•‘
╠════════════╬══════════════╬══════════╬════════════╬═════════╣
β•‘ ground     β•‘         0.65 β•‘     0.16 β•‘       0.25 β•‘ 1188768 β•‘
β•‘ vegetation β•‘         0.59 β•‘     0.85 β•‘       0.70 β•‘ 1315231 β•‘
β•‘ buildings  β•‘         0.43 β•‘     0.67 β•‘       0.53 β•‘  613317 β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•

Anda baru saja menyaksikan kekuatan sisi gelap sebenarnya dari Machine Learning: melakukan penyesuaian model secara berlebihan ke distribusi sampel dan mengalami kesulitan besar dalam menggeneralisasi. Karena kami telah memastikan bahwa kami telah menormalisasi data, kami dapat menyelidiki kemungkinan bahwa perilaku kinerja rendah ini mungkin disebabkan oleh fitur yang tidak cukup khas. Maksud saya, kami menggunakan beberapa fitur paling umum/dasar. Jadi mari kita tingkatkan dengan pemilihan fitur yang lebih baik, misalnya di bawah ini:

features=pcd[['Z','R','G','B','omnivariance_2','normal_cr_2','NumberOfReturns','planarity_2','omnivariance_1','verticality_1']]
val_features=val_pcd[['Z','R','G','B','omnivariance_2','normal_cr_2','NumberOfReturns','planarity_2','omnivariance_1','verticality_1']]

Bagus, sekarang kita memulai kembali fase pelatihan pada data pengujian, memeriksa performa model, lalu memeriksa perilaku model pada kumpulan data validasi:

features_scaled = MinMaxScaler().fit_transform(features)
X_train, X_test, y_train, y_test = train_test_split(features_scaled, labels, test_size=0.3)
rf_classifier = RandomForestClassifier(n_estimators = 10)
rf_classifier.fit(X_train, y_train)
rf_predictions = rf_classifier.predict(X_test)
print(classification_report(y_test, rf_predictions, target_names=['ground','vegetation','buildings']))
val_features_scaled = MinMaxScaler().fit_transform(val_features)
val_rf_predictions = rf_classifier.predict(val_features_scaled)
print(classification_report(val_labels, val_rf_predictions, target_names=['ground','vegetation','buildings']))

Mari kita pelajari hasilnya. Kami sekarang memiliki akurasi 97% pada data pengujian, yang selanjutnya diuraikan sebagai berikut:

╔════════════╦══════════════╦══════════╦════════════╦═════════╗
β•‘  classes   β•‘    precision β•‘   recall β•‘   f1-score β•‘ support β•‘
╠════════════╬══════════════╬══════════╬════════════╬═════════╣
β•‘ ground     β•‘         0.97 β•‘     0.98 β•‘       0.98 β•‘  518973 β•‘
β•‘ vegetation β•‘         0.97 β•‘     0.98 β•‘       0.97 β•‘  319808 β•‘
β•‘ buildings  β•‘         0.95 β•‘     0.91 β•‘       0.93 β•‘  175063 β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•

Menambahkan fitur menyebabkan sedikit penurunan kinerja dibandingkan dengan hanya menggunakan set X, Y, Z, R, G, B dasar, yang menunjukkan bahwa kami menambahkan beberapa gangguan. Tapi ini layak dilakukan demi Generalisasi! Kami sekarang memiliki akurasi global sebesar 85% pada set validasi, sehingga terjadi peningkatan sebesar 31%, hanya melalui pemilihan fitur! Ini sangat besar. Dan seperti yang Anda lihat, bangunan adalah aspek utama yang merugikan pertunjukan. Hal ini dijelaskan terutama oleh fakta bahwa mereka sangat berbeda dari yang ada di set pengujian dan bahwa set fitur tidak dapat benar-benar mewakilinya dalam konteks yang tidak berkorelasi.

╔════════════╦══════════════╦══════════╦════════════╦═════════╗
β•‘  classes   β•‘    precision β•‘   recall β•‘   f1-score β•‘ support β•‘
╠════════════╬══════════════╬══════════╬════════════╬═════════╣
β•‘ ground     β•‘         0.89 β•‘     0.81 β•‘       0.85 β•‘ 1188768 β•‘
β•‘ vegetation β•‘         0.92 β•‘     0.92 β•‘       0.92 β•‘ 1315231 β•‘
β•‘ buildings  β•‘         0.68 β•‘     0.80 β•‘       0.73 β•‘  613317 β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•

Ini sangat, sangat bagus! Kami sekarang memiliki model yang kinerjanya melebihi sebagian besar model yang dapat Anda temukan, bahkan menggunakan arsitektur pembelajaran mendalam!

Misalkan kita ingin meningkatkan skala lebih jauh lagi. Dalam hal ini, mungkin menarik untuk memasukkan beberapa data dari distribusi validasi untuk memeriksa apakah itu yang diperlukan dalam model, dengan mengorbankan validasi kita kehilangan statusnya dan menjadi bagian dari rangkaian pengujian. Kami mengambil 10% kumpulan data validasi dan 60% kumpulan data awal untuk melatih Model Hutan Acak. Kami kemudian menggunakannya dan memeriksa hasil pada 40% sisanya yang merupakan data pengujian, dan 90% dari data validasi:

val_labels=val_pcd['Classification']
val_features=val_pcd[['Z','R','G','B','omnivariance_2','normal_cr_2','NumberOfReturns','planarity_2','omnivariance_1','verticality_1']]
val_features_sampled, val_features_test, val_labels_sampled, val_labels_test = train_test_split(val_features, val_labels, test_size=0.9)
val_features_scaled_sample = MinMaxScaler().fit_transform(val_features_test)
labels=pd.concat([pcd['Classification'],val_labels_sampled])
features=pd.concat([pcd[['Z','R','G','B','omnivariance_2','normal_cr_2','NumberOfReturns','planarity_2','omnivariance_1','verticality_1']],val_features_sampled])
features_scaled = MinMaxScaler().fit_transform(features)
X_train, X_test, y_train, y_test = train_test_split(features_scaled, labels, test_size=0.4)
rf_classifier = RandomForestClassifier(n_estimators = 10)
rf_classifier.fit(X_train, y_train)
rf_predictions = rf_classifier.predict(X_test)
print(classification_report(y_test, rf_predictions, target_names=['ground','vegetation','buildings']))
val_rf_predictions_90 = rf_classifier.predict(val_features_scaled_sample)
print(classification_report(val_labels_test, val_rf_predictions_90, target_names=['ground','vegetation','buildings']))

Dan dengan senang hati kami melihat bahwa metrik kami meningkat setidaknya 5% sementara hanya kehilangan 1% pada set pengujian, sehingga mengorbankan gangguan fitur minimal seperti yang ditunjukkan di bawah ini:

40% Test Predicitions - Accuracy = 0.96    1476484

╔════════════╦══════════════╦══════════╦════════════╦═════════╗
β•‘  classes   β•‘    precision β•‘   recall β•‘   f1-score β•‘ support β•‘
╠════════════╬══════════════╬══════════╬════════════╬═════════╣
β•‘ ground     β•‘         0.97 β•‘     0.98 β•‘       0.97 β•‘  737270 β•‘
β•‘ vegetation β•‘         0.97 β•‘     0.97 β•‘       0.97 β•‘  481408 β•‘
β•‘ buildings  β•‘         0.94 β•‘     0.90 β•‘       0.95 β•‘  257806 β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•
90% Validation Predicitions - Accuracy = 0.90    2805585
╔════════════╦══════════════╦══════════╦════════════╦═════════╗
β•‘  classes   β•‘    precision β•‘   recall β•‘   f1-score β•‘ support β•‘
╠════════════╬══════════════╬══════════╬════════════╬═════════╣
β•‘ ground     β•‘         0.88 β•‘     0.92 β•‘       0.90 β•‘  237194 β•‘
β•‘ vegetation β•‘         0.93 β•‘     0.94 β•‘       0.94 β•‘  263364 β•‘
β•‘ buildings  β•‘         0.87 β•‘     0.79 β•‘       0.83 β•‘  122906 β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•

Yang biasanya menarik adalah memeriksa hasil akhir dengan model berbeda dan parameter yang sama, lalu melalui fase akhir penyetelan hyperparameter. Tapi itu untuk lain waktu πŸ˜‰. Apakah kamu tidak kelelahan? Saya pikir energi otak kita perlu diisi ulang; mari kita tinggalkan sisanya untuk lain waktu dan menyelesaikan proyek. 😁

Mengekspor kumpulan data berlabel

Judulnya menjelaskan semuanya: sekarang saatnya mengekspor hasilnya untuk digunakan di aplikasi lain. Mari kita ekspor sebagai file Ascii dengan baris berikut:

val_pcd['predictions']=val_rf_predictions
result_folder="../DATA/RESULTS/"
val_pcd[['X','Y','Z','R','G','B','predictions']].to_csv(result_folder+dataset.split(".")[0]+"_result_final.xyz", index=None, sep=';')

Mengekspor Model Pembelajaran Mesin 3D

Dan, tentu saja, jika Anda puas dengan model Anda, Anda dapat menyimpannya secara permanen dan meletakkannya di suatu tempat untuk digunakan dalam produksi untuk kumpulan data yang tidak terlihat/tidak berlabel. Kita dapat menggunakan modul acar untuk melakukan hal itu. Tiga baris kode kecil:

import pickle
pickle.dump(rf_classifier, open(result_folder+"urban_classifier.poux", 'wb'))

Dan kapan Anda perlu menggunakan kembali model tersebut:

model_name="urban_classifier.poux"
loaded_model = pickle.load(open(result_folder+model_name, 'rb'))
predictions = loaded_model.predict(data_to_predict)
print(classification_report(y_test, loaded_predictions, target_names=['ground','vegetation','buildings']))

Anda dapat mengakses kode lengkapnya langsung di browser Anda dengan notebook Google Colab ini.

Kesimpulan

Itu adalah perjalanan yang gila! Kursus 201 lengkap dengan tutorial praktis tentang Pembelajaran Mesin 3D! 😁 Anda belajar banyak, terutama cara mengimpor point cloud dengan fitur, memilih, melatih, dan mengubah model pembelajaran mesin 3D yang diawasi, dan mengekspornya untuk mendeteksi kelas luar ruangan dengan generalisasi yang sangat baik ke Kumpulan Data Aerial Point Cloud yang besar! Selamat Besar-besaran! Namun ini hanyalah sebagian dari persamaan untuk Pembelajaran Mesin 3D. Untuk memperluas hasil perjalanan pembelajaran, artikel mendatang akan mendalami segmentasi semantik dan instance [2–4], animasi, dan pembelajaran mendalam [1]. Kami akan membahas pengelolaan data cloud titik besar seperti yang dijelaskan dalam artikel di bawah ini.



Kontribusi saya bertujuan untuk menyingkat informasi yang dapat ditindaklanjuti sehingga Anda dapat memulai dari awal untuk membangun sistem otomasi 3D untuk proyek Anda. Anda dapat memulai hari ini dengan mengikuti kursus di Akademi Geodata.

Referensi

1. Poux, F., & J.-J Ponciano. (2020). Ontologi Belajar Mandiri Misalnya Segmentasi Cloud Titik Dalam Ruangan 3d. ISPRS Int. Lengkungan. dari Pho. & Rem. XLIII-B2, 309–316; https://doi.org/10.5194/isprs-archives-XLIII-B2–2020–309–2020

2. Poux, F., & Billen, R. (2019). Segmentasi semantik cloud titik 3D berbasis Voxel: fitur geometris dan hubungan tanpa pengawasan vs. metode pembelajaran mendalam. Jurnal Internasional Geo-Informasi ISPRS. 8(5), 213; https://doi.org/10.3390/ijgi8050213

3. Poux, F., Neuville, R., Nys, G.-A., & Billen, R. (2018). Pemodelan Semantik Cloud Titik 3D: Kerangka Terintegrasi untuk Ruang dan Furnitur Dalam Ruangan. Penginderaan Jauh, 10(9), 1412. https://doi.org/10.3390/rs10091412

4. Poux, F., Neuville, R., Van Wersch, L., Nys, G.-A., & Billen, R. (2017). Awan Titik 3D dalam Arkeologi: Kemajuan dalam Akuisisi, Pemrosesan, dan Integrasi Pengetahuan yang Diterapkan pada Objek Kuasi-Planar. Geosains, 7(4), 96. https://doi.org/10.3390/GEOSCIENCES7040096