MASK-RCNN untuk menemukan atap dari gambar drone


Di kota putih dan putih di jalan putih dan putih ada rumah-rumah putih dan putih ... Dan seberapa cepat Anda bisa menemukan semua atap rumah di foto ini?

Semakin banyak orang dapat mendengar tentang rencana pemerintah untuk melakukan inventarisasi lengkap real estat untuk mengklarifikasi data kadaster. Untuk solusi utama untuk masalah ini, metode sederhana dapat diterapkan berdasarkan perhitungan luas atap bangunan modal dari foto udara dan perbandingan lebih lanjut dengan data kadaster. Sayangnya, pencarian dan perhitungan manual membutuhkan banyak waktu, dan karena rumah-rumah baru dihancurkan dan dibangun terus menerus, perhitungannya perlu diulang-ulang. Hipotesis segera muncul bahwa proses ini dapat diotomatisasi menggunakan algoritma pembelajaran mesin, khususnya, Computer Vision. Dalam artikel ini saya akan berbicara tentang bagaimana kita berada di NORBIT memecahkan masalah ini dan kesulitan apa yang mereka temui.

Spoiler - kami berhasil . Layanan ML yang dikembangkan didasarkan pada model pembelajaran mesin dalam yang didasarkan pada jaringan saraf konvolusi. Layanan menerima gambar dari kendaraan udara tak berawak sebagai input, pada output, ia menghasilkan file GeoJSON dengan markup objek konstruksi modal yang ditemukan dengan mengacu pada koordinat geografis.

Hasilnya, terlihat seperti ini:


Masalah


Mari kita mulai dengan masalah teknis yang kami temui:

  • ada perbedaan yang signifikan antara foto udara musim dingin dan musim panas (model yang hanya dilatih dalam foto musim panas sama sekali tidak dapat menemukan atap di musim dingin);
  • , ;
  • , ( ), ( ) , ;
  • , , ( ). ;
  • (, ) .

Dan drone terkadang membawa foto-foto ini:


Saya juga ingin mencatat masalah yang mungkin terjadi, tetapi mereka tidak mempedulikan kami:

  • kami tidak memiliki tugas untuk melakukan inferensi untuk waktu yang terbatas (misalnya, langsung pada saat penerbangan), yang segera menyelesaikan semua masalah yang mungkin terjadi dengan kinerja;
  • pada input untuk diproses, kami segera menerima gambar resolusi tinggi berkualitas tinggi (menggunakan lensa dengan panjang fokus 21 mm pada ketinggian 250 m, yaitu 5 cm / px) dari pelanggan kami, perusahaan Shakhty, dapat menggunakan keahlian mereka dalam geolokasi objek pada peta, dan mereka juga memiliki kesempatan untuk menetapkan serangkaian persyaratan khusus untuk penerbangan UAV di masa depan, yang pada akhirnya sangat mengurangi kemungkinan ubin unik yang tidak ada dalam rangkaian pelatihan;

Solusi pertama untuk masalah ini, gunakan kotak Boundary 


Beberapa kata tentang alat apa yang kami gunakan untuk membuat solusi.

  • Anaconda adalah sistem manajemen paket yang mudah digunakan untuk Python dan R.
  • Tensorflow adalah perpustakaan perangkat lunak pembelajaran mesin sumber terbuka yang dikembangkan oleh Google.
  • Keras adalah add-on untuk framework Deeplearning4j, TensorFlow dan Theano.
  • OpenCV adalah perpustakaan algoritma untuk visi komputer, pemrosesan gambar, dan algoritma numerik open-source untuk tujuan umum.
  • Flask adalah kerangka kerja untuk membuat aplikasi web dalam bahasa pemrograman Python.

Sebagai OS yang digunakan Ubuntu 18.04. Dengan driver pada GPU (NVIDIA) di Ubuntu, semuanya sudah beres, sehingga tugas biasanya diselesaikan dengan satu perintah:

> sudo apt install nvidia-cuda-toolkit

Persiapan Ubin


Tugas pertama yang kami hadapi adalah untuk membagi gambar flyby menjadi ubin (2048x2048 px). Anda dapat menulis skrip Anda sendiri, tetapi kemudian Anda harus berpikir tentang mempertahankan lokasi geografis setiap ubin. Lebih mudah menggunakan solusi yang sudah jadi, misalnya, GeoServer - ini adalah perangkat lunak sumber terbuka yang memungkinkan Anda untuk mempublikasikan geodata di server. Selain itu, GeoServer memecahkan masalah lain bagi kami - tampilan nyaman dari hasil penandaan otomatis pada peta. Ini dapat dilakukan secara lokal, misalnya, dalam qGIS, tetapi untuk perintah dan demonstrasi yang didistribusikan, sumber daya web lebih nyaman.

Untuk melakukan ubin, Anda harus menentukan skala dan ukuran yang diperlukan dalam pengaturan.


Untuk terjemahan antara sistem koordinat, kami menggunakan pyproj library:

from pyproj import Proj, transform

class Converter:
    P3857 = Proj(init='epsg:3857')
    P4326 = Proj(init='epsg:4326')
...
    def from_3857_to_GPS(self, point):
        x, y = point
        return transform(self.P3857, self.P4326, x, y)
    def from_GPS_to_3857(self, point):
        x, y = point
        return transform(self.P4326, self.P3857, x, y)
...

Sebagai hasilnya, adalah mungkin untuk dengan mudah membentuk satu lapisan besar dari semua poligon dan meletakkannya di atas substrat. 


Untuk menginstal perangkat lunak GeoServer, Anda harus menyelesaikan langkah-langkah berikut.
  1. Java 8.
  2. GeoServer.
  3. , , /usr/share/geoserver
  4.  

    echo ยซexport GEOSERVER_HOME=/usr/share/geoserverยป >> ~/.profile
  5. :

    sudo groupadd geoserver
  6. , , :

    sudo usermod -a -G geoserver <user_name>
  7. - :

    sudo chown -R :geoserver /usr/share/geoserver/
  8. :

    sudo chmod -R g+rwx /usr/share/geoserver/
  9. GeoServer 

    cd geoserver/bin && sh startup.sh

GeoServer bukan satu-satunya aplikasi yang memungkinkan kita untuk menyelesaikan masalah kita. Sebagai alternatif, misalnya, Anda dapat mempertimbangkan ArcGIS untuk Server, tetapi produk ini adalah hak milik, jadi kami tidak menggunakannya.

Selanjutnya, setiap ubin harus menemukan semua atap yang terlihat. Pendekatan pertama untuk memecahkan masalah adalah dengan menggunakan object_detection dari model / set penelitian Tensorflow. Dengan cara ini, kelas pada gambar dapat ditemukan dan dilokalkan dengan pilihan persegi panjang (kotak batas). 

Pelatihan markup data 


Jelas, untuk melatih model Anda memerlukan dataset berlabel. Secara kebetulan, selain berputar-putar, di tempat sampah kami set data untuk 50 ribu atap disimpan dari masa lalu yang indah, ketika semua set data untuk pelatihan masih dalam domain publik di mana-mana.

Ukuran persis sampel pelatihan yang diperlukan untuk mendapatkan akurasi model yang dapat diterima agak sulit untuk diprediksi sebelumnya. Ini dapat bervariasi tergantung pada kualitas gambar, tingkat perbedaannya satu sama lain, dan kondisi di mana model akan digunakan dalam produksi. Kami memiliki kasus ketika 200 lembar sudah cukup, dan kadang-kadang 50 ribu sampel yang ditandai juga hilang. Jika terjadi kekurangan gambar yang ditandai, kami biasanya menambahkan metode augmentasi: putaran, refleksi cermin, penilaian warna, dll.

Sekarang ada banyak layanan yang tersedia yang memungkinkan Anda untuk menandai gambar - baik dengan kode sumber terbuka untuk instalasi di komputer / server Anda, dan solusi korporat yang mencakup karya penilai eksternal, misalnya Yandex.Tolok. Dalam proyek ini, kami menggunakan VGG Image Annotator yang paling sederhana . Atau, Anda dapat mencoba coco-annotator atau label-studio . Kami biasanya menggunakan yang terakhir untuk menandai file teks dan audio.


Untuk pelatihan tentang markup berbagai annotator, Anda biasanya perlu melakukan pergeseran kecil bidang, contoh untuk VGG .

Untuk menghitung dengan benar area atap yang jatuh ke area alokasi persegi panjang, perlu diperhatikan beberapa kondisi:

  • / . :


  • , , :


Untuk mengatasi masalah kedua, Anda dapat mencoba melatih model terpisah yang akan menentukan sudut rotasi ubin yang tepat untuk penandaan, tetapi semuanya ternyata sedikit lebih mudah. Orang sendiri berusaha mengurangi entropi, sehingga mereka menyelaraskan semua struktur buatan manusia dalam kaitannya satu sama lain, terutama dengan bangunan padat. Jika Anda melihat dari atas, maka di area terlokalisasi, pagar, jalur pejalan kaki, penanaman, rumah kaca, arbors akan sejajar atau tegak lurus dengan batas atap. Tetap hanya untuk menemukan semua garis yang jelas dan menghitung sudut kemiringan paling umum ke vertikal. Untuk ini, OpenCV memiliki alat HoughLinesP yang hebat. 

...

lines = cv2.HoughLinesP(edges, 1, np.pi/180, 50, minLineLength=minLineLength, maxLineGap=5)
if lines is not None:
    length = image.shape[0]
    angles = []
    for x1, y1, x2, y2 in lines[0]:
        angle = math.degrees(math.atan2(y2 โ€” y1, x2 - x1))
        angles.append(angle)
    parts_angles.append(angles)
    median_angle = np.median(angles)
...

#     

for x in range(0, image.shape[0]-1, image.shape[0] // count_crops):
    for y in range(0, image.shape[1]-1, image.shape[1] // count_crops):
        get_line(image[x:x+image.shape[0]//count_crops, y:y+image.shape[1]//count_crops, :])
...

#      

np.median([a if a>0 else 90+a for a in np.array(parts_angles).flatten()])

Setelah menemukan sudutnya, kami memutar gambar menggunakan transformasi affine:


h, w = image.shape[:2]
image_center = (w/2, h/2)

if size is None:
    radians = math.radians(angle)
    sin = math.sin(radians)
    cos = math.cos(radians)
    size = (int((h * abs(sin)) + (w * abs(cos))), int((h * abs(cos)) + (w * abs(sin))))
    rotation_matrix = cv2.getRotationMatrix2D(image_center, angle, 1)
    rotation_matrix[0, 2] += ((size[0] / 2) โ€” image_center[0])
    rotation_matrix[1, 2] += ((size[1] / 2) โ€” image_center[1])
else:
    rotation_matrix = cv2.getRotationMatrix2D(image_center, angle, 1)

cv2.warpAffine(image, rotation_matrix, size)

Kode contoh lengkap ada di sini . Begini tampilannya:



Metode membalik ubin dan menandai dengan persegi panjang bekerja lebih cepat daripada menandai dengan topeng, hampir semua atap ditemukan, tetapi dalam produksi metode ini hanya digunakan sebagai tambahan karena beberapa kelemahan:

  • ada banyak overflight di mana ada sejumlah besar atap non-persegi panjang, karena ini ada terlalu banyak pekerjaan manual untuk memperbaiki area tersebut,
  • terkadang ditemukan di rumah dengan orientasi berbeda pada ubin yang sama,
  • kadang-kadang ada banyak garis palsu pada ubin, yang pada akhirnya mengarah ke belokan yang salah. Ini terlihat seperti ini:



Solusi akhir berdasarkan Mask-RCNN


Upaya kedua adalah untuk mencari dan menyorot atap dengan topeng pixel demi pixel, dan kemudian secara otomatis menguraikan kontur topeng yang ditemukan dan membuat poligon vektor.  

Sudah ada cukup bahan tentang prinsip-prinsip operasi, jenis dan tugas jaringan saraf convolutional, termasuk yang di Rusia, jadi kami tidak akan membahasnya dalam artikel ini. Mari kita membahas satu implementasi tertentu saja, Mask-RCNN - sebuah arsitektur untuk melokalisasi dan menyoroti kontur objek dalam gambar. Ada solusi luar biasa lainnya dengan kelebihan dan kekurangan mereka, misalnya, UNet, tetapi dimungkinkan untuk mencapai kualitas yang lebih baik di Mask-RCNN.

Dalam proses pengembangannya, ia melewati beberapa tahap. Versi pertama R-CNN dikembangkan pada 2014. Prinsip kerjanya adalah untuk menyoroti area kecil dalam gambar, untuk masing-masing estimasi dibuat dari kemungkinan keberadaan objek target di area ini. R-CNN melakukan pekerjaan yang sangat baik dengan tugas itu, tetapi kecepatannya meninggalkan banyak yang harus diinginkan. Pengembangan logis adalah jaringan Fast R-CNN dan Faster R-CNN, yang menerima peningkatan dalam algoritma penelusuran gambar, yang memungkinkan untuk secara signifikan meningkatkan kecepatan. Di pintu keluar ke Faster R-CNN, sebuah tanda muncul dengan pilihan persegi panjang yang menunjukkan batas-batas objek, yang tidak selalu cukup untuk menyelesaikan masalah. 

Mask R-CNN juga menambahkan overlay masker piksel demi piksel untuk mendapatkan garis besar objek yang tepat.

Kotak batas dan topeng dapat dilihat dengan jelas pada hasil operasi model (filter berdasarkan luas bangunan minimum dihidupkan):


Secara konvensional, ada 4 tahap dalam pengoperasian jaringan ini:

  • standar untuk semua jaringan saraf convolutional, alokasi fitur dalam gambar, seperti garis, tikungan, batas kontras dan lainnya;
  • Region Proposal Network (RPN) memindai fragmen kecil gambar, yang disebut jangkar (jangkar) dan menentukan apakah jangkar ini mengandung tanda-tanda karakteristik kelas target (dalam kasus kami, atap);
  • Klasifikasi Wilayah Bunga dan Bounding Box. Pada tahap ini, jaringan, berdasarkan hasil dari tahap sebelumnya, sedang mencoba untuk menyoroti area persegi panjang yang besar dalam foto, mungkin mengandung objek target;
  • Masker Segmentasi. Pada tahap ini, topeng dari objek yang diinginkan diperoleh dari area persegi panjang yang diperoleh dengan menerapkan kotak batas.

Selain itu, jaringan ternyata sangat fleksibel dalam konfigurasi, dan kami dapat membangunnya kembali untuk memproses gambar dengan lapisan informasi tambahan.

Dengan hanya menggunakan gambar RGB saja tidak memungkinkan kami untuk mencapai akurasi pengenalan yang diperlukan (model kehilangan seluruh bangunan, ada kesalahan rata-rata 15% dalam menghitung luas atap), jadi kami menyediakan model dengan data berguna tambahan, misalnya, peta ketinggian yang diperoleh dengan fotogrametri. 


Metrik digunakan untuk mengevaluasi kualitas model


Saat menentukan kualitas model, kami paling sering menggunakan metrik Intersection over Union (IoU)


Kode contoh untuk menghitung IoU menggunakan pustaka geometri.shapely:

from shapely.geometry import Polygon

true_polygon = Polygon([(2, 2), (2, 6), (5, 6), (5, 2)])
predicted_polygon = Polygon([(3, 3), (3, 7), (6, 7), (6, 3)])
print(true_polygon.intersection(predicted_polygon).area / true_polygon.union(predicted_polygon).area)

>>> 0.3333333333333333

Melacak proses pelatihan model dengan mudah dikontrol menggunakan Tensorboard, alat kontrol metrik yang nyaman yang memungkinkan Anda menerima data waktu nyata mengenai kualitas model dan membandingkannya dengan model lain.


Tensorboard menyediakan data pada banyak metrik yang berbeda. Yang paling menarik bagi kami adalah:

  • val_mrcnn_bbox_loss - menunjukkan seberapa baik model melokalkan objek (mis. memaksakan kotak batas);
  • val_mrcnn_mask_loss - menunjukkan seberapa baik model melakukan segmentasi objek (mis. memaksakan mask).

Pelatihan model dan validasi


Saat pelatihan, kami menggunakan praktik standar membagi dataset secara acak menjadi 3 bagian - pelatihan, validasi, dan tes. Dalam proses pembelajaran, kualitas model dievaluasi pada sampel validasi, dan setelah selesai melewati tes akhir pada data tes yang ditutup dari itu dalam proses pembelajaran. 

Kami melakukan pelatihan pertama kami dimulai pada serangkaian kecil tembakan musim panas dan, memutuskan untuk memeriksa seberapa baik model kami di musim dingin, kami diharapkan menerima hasil yang mengecewakan. Pilihan untuk menggunakan model yang berbeda untuk musim yang berbeda, tentu saja, merupakan jalan keluar yang sangat baik dari situasi ini, tetapi itu akan memerlukan sejumlah ketidaknyamanan, jadi kami memutuskan untuk mencoba membuat model tersebut universal. Dengan bereksperimen dengan berbagai konfigurasi lapisan, dan juga menutup bobot masing-masing lapisan dari perubahan bobot, kami menemukan strategi optimal untuk melatih model dengan menerapkan gambar musim panas dan musim dingin secara bergantian ke input.

Membuat layanan latar belakang untuk pengakuan


Sekarang setelah kita memiliki model yang berfungsi, kita dapat membuat layanan API latar belakang dari skrip pengenalan yang menerima gambar sebagai input dan menghasilkan json dengan poligon atap yang ditemukan di output. Ini tidak secara langsung mempengaruhi solusi masalah, tetapi mungkin bermanfaat bagi seseorang. 

Ubuntu menggunakan systemd, dan sebuah contoh akan diberikan secara khusus untuk sistem ini. Kode layanan itu sendiri dapat dilihat di sini . Unit pengguna berada di direktori / etc / systemd / system, di mana kami akan membuat file layanan kami. Edit file:

cd /etc/systemd/system

sudo touch my_srv.service




sudo vim my_srv.service

Unit systemd terdiri dari tiga bagian:

  • [Unit] - menjelaskan urutan dan kondisi awal (misalnya, Anda dapat memberi tahu proses untuk menunggu dimulainya layanan tertentu dan baru kemudian memulainya sendiri);
  • [Layanan] - menjelaskan parameter startup;
  • [Instal] - menjelaskan perilaku layanan saat menambahkannya ke startup.

Akibatnya, file kami akan terlihat seperti ini:

[Unit]
Description=my_test_unit

[Service]
WorkingDirectory=/home/user/test_project
User=root
ExecStart=/home/user/test_project/venv/bin/python3 /home/user/test_project/script.py

[Install]
WantedBy=multi-user.target

Sekarang muat ulang konfigurasi systemd dan jalankan layanan kami:

sudo systemctl daemon-reload
sudo systemctl start my_srv.service

Ini adalah contoh sederhana dari proses latar belakang, systemd mendukung banyak parameter berbeda yang memungkinkan Anda mengkonfigurasi perilaku layanan secara fleksibel, tetapi tidak ada yang lebih rumit yang diperlukan untuk tugas kami.

temuan


Hasil utama dari proyek ini adalah kemampuan untuk secara otomatis mendeteksi inkonsistensi dalam pengembangan aktual dan informasi yang terkandung dalam data kadaster.

Sebagai hasil dari evaluasi keakuratan model pada data uji, nilai-nilai berikut diperoleh: jumlah atap yang ditemukan - 91%, akurasi poligon garis atap - 94%.

Dimungkinkan untuk mencapai kualitas model yang dapat diterima dalam penerbangan musim panas dan musim dingin, tetapi kualitas pengakuan dapat menurun dalam gambar segera setelah hujan salju.

Sekarang bahkan Gedung Opera Sydney tidak akan luput dari pandangan model kita. 


Kami berencana untuk menempatkan layanan ini dengan model yang terlatih di demostand kami. Jika Anda tertarik untuk mencoba layanan pada foto Anda sendiri, kirim aplikasi ke ai@norbit.ru.

All Articles