Pengenalan objek waktu-nyata pada iOS menggunakan YOLOv3


Halo semuanya!

Pada artikel ini kita akan menulis sebuah program kecil untuk menyelesaikan masalah deteksi dan pengenalan objek (deteksi objek) secara real time. Program ini akan ditulis dalam bahasa pemrograman Swift untuk platform iOS. Untuk mendeteksi objek, kita akan menggunakan jaringan saraf convolutional dengan arsitektur yang disebut YOLOv3. Dalam artikel ini, kita akan belajar cara bekerja di iOS dengan jaringan saraf menggunakan kerangka kerja CoreML, sedikit pemahaman tentang apa jaringan YOLOv3 dan bagaimana menggunakan dan memproses output dari jaringan ini. Kami juga akan memeriksa pengoperasian program dan membandingkan beberapa variasi YOLOv3: YOLOv3-tiny dan YOLOv3-416.

Sumber akan tersedia di akhir artikel, sehingga semua orang akan dapat menguji operasi jaringan saraf pada perangkat mereka.

Deteksi objek


Untuk memulainya, kita akan secara singkat memahami apa tugas mendeteksi objek (deteksi objek) dalam gambar dan alat apa yang digunakan untuk ini hari ini. Saya mengerti bahwa banyak yang cukup akrab dengan topik ini, tetapi saya masih membiarkan diri saya menceritakan sedikit tentangnya.

Sekarang banyak tugas di bidang visi komputer diselesaikan dengan bantuan jaringan saraf convolutional (Convolutional Neural Networks), selanjutnya CNN. Karena strukturnya, mereka juga mengekstrak fitur dari gambar. CNN digunakan dalam klasifikasi, pengakuan, segmentasi, dan banyak lainnya.

Arsitektur CNN populer untuk pengenalan objek:

  • R-CNN. Kita dapat mengatakan model pertama untuk menyelesaikan masalah ini. Bekerja seperti penggolong gambar biasa. Berbagai daerah gambar diumpankan ke input jaringan dan prediksi dibuat untuk mereka. Sangat lambat karena menjalankan gambar tunggal beberapa ribu kali.
  • Cepat R-CNN. Versi R-CNN yang lebih baik dan lebih baik, bekerja dengan prinsip yang sama, tetapi pertama-tama seluruh gambar diumpankan ke input CNN, lalu wilayah dihasilkan dari representasi internal yang diterima. Namun masih cukup lambat untuk tugas-tugas real-time.
  • Lebih cepat R-CNN. Perbedaan utama dari yang sebelumnya adalah bahwa alih-alih algoritma pencarian selektif, ia menggunakan jaringan saraf untuk memilih daerah untuk "menghafal" mereka.
  • YOLO. Prinsip operasi yang sama sekali berbeda dibandingkan dengan yang sebelumnya tidak menggunakan daerah sama sekali. Tercepat. Rincian lebih lanjut tentang itu akan dibahas dalam artikel ini.
  • SSD Ini pada prinsipnya mirip dengan YOLO, tetapi menggunakan VGG16 sebagai jaringan untuk mengekstrak fitur. Juga cukup cepat dan cocok untuk pekerjaan real-time.
  • Fitur Jaringan Piramida (FPN). Jenis jaringan lain seperti Single Shot Detector, karena fitur ekstraksi fitur lebih baik daripada SSD mengenali objek kecil.
  • RetinaNet. Ini menggunakan kombinasi FPN + ResNet dan, berkat fungsi kesalahan khusus (kehilangan fokus), memberikan akurasi yang lebih tinggi.

Pada artikel ini, kita akan menggunakan arsitektur YOLO, yaitu modifikasi terbarunya, YOLOv3.

Mengapa YOLO?




YOLO atau You Only Look Once adalah arsitektur CNN yang sangat populer, yang digunakan untuk mengenali banyak objek dalam suatu gambar. Informasi yang lebih lengkap tentang hal itu dapat diperoleh di situs web resmi , di tempat yang sama Anda dapat menemukan publikasi di mana teori dan komponen matematika dari jaringan ini dijelaskan secara rinci, serta proses pelatihannya dijelaskan.

Fitur utama arsitektur ini dibandingkan dengan yang lain adalah bahwa sebagian besar sistem menerapkan CNN beberapa kali untuk berbagai wilayah gambar, di YOLO, CNN diterapkan satu kali untuk seluruh gambar sekaligus. Jaringan membagi gambar menjadi semacam kotak dan memprediksi kotak pembatas dan kemungkinan bahwa ada objek yang diinginkan untuk setiap bagian.

Keuntungan dari pendekatan ini adalah bahwa jaringan melihat seluruh gambar sekaligus dan mempertimbangkan konteks ketika mendeteksi dan mengenali suatu objek. YOLO juga 1000 kali lebih cepat dari R-CNN dan sekitar 100x lebih cepat dari Fast R-CNN. Pada artikel ini, kami akan meluncurkan jaringan pada perangkat seluler untuk pemrosesan online, jadi ini adalah kualitas yang paling penting bagi kami.

Informasi lebih rinci tentang perbandingan arsitektur dapat ditemukan di sini .

YOLOv3


YOLOv3 adalah versi lanjutan dari arsitektur YOLO. Ini terdiri dari 106 lapisan konvolusional dan lebih baik mendeteksi benda-benda kecil dibandingkan dengan pendahulunya YOLOv2. Fitur utama YOLOv3 adalah bahwa ada tiga lapisan pada output, yang masing-masing dirancang untuk mendeteksi objek dengan ukuran yang berbeda.
Gambar di bawah ini menunjukkan struktur skematiknya:



YOLOv3-tiny - Versi terpangkas dari arsitektur YOLOv3, terdiri dari lebih sedikit lapisan (hanya ada 2 lapisan keluaran). Ini memprediksi objek yang lebih kecil lebih buruk dan dimaksudkan untuk dataset kecil. Tetapi, karena struktur terpotong, bobot jaringan menempati sejumlah kecil memori (~ 35 MB) dan menghasilkan FPS yang lebih tinggi. Karena itu, arsitektur seperti itu lebih disukai untuk digunakan pada perangkat seluler.

Kami sedang menulis sebuah program untuk pengenalan objek


Bagian yang menyenangkan dimulai!

Mari kita membuat aplikasi yang akan mengenali berbagai objek dalam gambar secara real time menggunakan kamera ponsel. Semua kode akan ditulis dalam bahasa pemrograman Swift 4.2 dan dijalankan pada perangkat iOS.

Dalam tutorial ini kita akan mengambil jaringan yang sudah jadi dengan skala yang telah dilatih sebelumnya pada dataset COCO . Ini menyajikan 80 kelas yang berbeda. Oleh karena itu, neuron kita akan dapat mengenali 80 objek yang berbeda.

Dari Darknet ke CoreML


Arsitektur YOLOv3 asli diimplementasikan menggunakan kerangka Darknet .

Di iOS, dimulai dengan versi 11.0, ada perpustakaan CoreML yang luar biasa yang memungkinkan Anda menjalankan model pembelajaran mesin langsung di perangkat. Tetapi ada satu batasan: program hanya dapat dijalankan pada perangkat yang menjalankan iOS 11 ke atas.

Masalahnya adalah bahwa CoreML hanya memahami format spesifik dari model .coreml . Untuk sebagian besar perpustakaan populer, seperti Tensorflow, Keras atau XGBoost, dimungkinkan untuk secara langsung mengkonversi ke format CoreML. Tetapi untuk Darknet tidak ada kemungkinan seperti itu. Untuk mengonversi model yang disimpan dan dilatih dari Darknet ke CoreML, Anda dapat menggunakan berbagai opsi, misalnya, menyimpan Darknet ke ONNX , dan kemudian mengonversinya dari ONNX ke CoreML.

Kami akan menggunakan cara yang lebih sederhana dan kami akan menggunakan implementasi Keras YOLOv3. Algoritme tindakannya adalah ini: muat bobot Darknet ke dalam model Keras, simpan dalam format Keras dan langsung konversikan ke CoreML dari sini.

  1. Unduh Darknet. Unduh file dari model Darknet-YOLOv3 yang terlatih dari sini . Pada artikel ini, saya akan menggunakan dua arsitektur: YOLOv3-416 dan YOLOv3-tiny. Kita membutuhkan file cfg dan bobot.
  2. Dari Darknet ke Keras. Pertama, klon repositori , buka folder repo dan jalankan perintah:

    python convert.py yolov3.cfg yolov3.weights yolo.h5 

    di mana yolov3.cfg dan yolov3.weights mengunduh file Darknet. Akibatnya, kita harus memiliki file dengan ekstensi .h5 - ini adalah model YOLOv3 yang disimpan dalam format Keras.
  3. Dari Keras ke CoreML. Langkah terakhir tetap. Untuk mengonversi model ke CoreML, Anda harus menjalankan skrip python (Anda harus menginstal pustaka coremltools terlebih dahulu untuk python):

     import coremltools coreml_model = coremltools.converters.keras.convert( 'yolo.h5', input_names='image', image_input_names='image', input_name_shape_dict={'image': [None, 416, 416, 3]}, #      image_scale=1/255.) coreml_model.input_description['image'] = 'Input image' coreml_model.save('yolo.mlmodel') 

Langkah-langkah yang dijelaskan di atas harus dilakukan untuk dua model YOLOv3-416 dan YOLOv3-mungil.
Ketika kami melakukan semua ini, kami memiliki dua file: yolo.mlmodel dan yolo-tiny.mlmodel. Sekarang Anda dapat mulai menulis kode aplikasi itu sendiri.

Membuat aplikasi iOS


Saya tidak akan menjelaskan semua kode aplikasi, Anda dapat melihatnya di repositori, tautan yang akan diberikan di akhir artikel. Izinkan saya mengatakan bahwa kami memiliki tiga UIViewController-a: OnlineViewController, PhotoViewController, dan SettingsViewController. Yang pertama adalah output kamera dan deteksi objek secara online untuk setiap frame. Dalam yang kedua, Anda dapat mengambil foto atau memilih gambar dari galeri dan menguji jaringan pada gambar-gambar ini. Yang ketiga berisi pengaturan, Anda dapat memilih model YOLOv3-416 atau YOLOv3-mungil, serta memilih ambang batas IoU (persimpangan atas kesatuan) dan kepercayaan objek (probabilitas bahwa ada objek di bagian gambar saat ini).

Memuat Model dalam CoreML

Setelah kami mengkonversi model terlatih dari format Darknet ke CoreML, kami memiliki file dengan ekstensi .mlmodel . Dalam kasus saya, saya membuat dua file: yolo.mlmodel dan yolo-tiny.mlmodel , masing-masing untuk model YOLOv3-416 dan YOLOv3-tiny. Sekarang Anda dapat memuat file-file ini ke proyek di Xcode.

Kami membuat kelas ModelProvider, itu akan menyimpan model dan metode saat ini untuk secara serentak memohon jaringan saraf untuk dieksekusi. Model dimuat dengan cara ini:

  private func loadModel(type: YOLOType) { do { self.model = try YOLO(type: type) } catch { assertionFailure("error creating model") } } 

Kelas YOLO bertanggung jawab langsung untuk memuat file .mlmodel dan menangani output model. Unduh file model:

  var url: URL? = nil self.type = type switch type { case .v3_Tiny: url = Bundle.main.url(forResource: "yolo-tiny", withExtension:"mlmodelc") self.anchors = tiny_anchors case .v3_416: url = Bundle.main.url(forResource: "yolo", withExtension:"mlmodelc") self.anchors = anchors_416 } guard let modelURL = url else { throw YOLOError.modelFileNotFound } do { model = try MLModel(contentsOf: modelURL) } catch let error { print(error) throw YOLOError.modelCreationError } 

Kode Pemberi Model Lengkap.
 import UIKit import CoreML protocol ModelProviderDelegate: class { func show(predictions: [YOLO.Prediction]?, stat: ModelProvider.Statistics, error: YOLOError?) } @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) class ModelProvider { struct Statistics { var timeForFrame: Float var fps: Float } static let shared = ModelProvider(modelType: Settings.shared.modelType) var model: YOLO! weak var delegate: ModelProviderDelegate? var predicted = 0 var timeOfFirstFrameInSecond = CACurrentMediaTime() init(modelType type: YOLOType) { loadModel(type: type) } func reloadModel(type: YOLOType) { loadModel(type: type) } private func loadModel(type: YOLOType) { do { self.model = try YOLO(type: type) } catch { assertionFailure("error creating model") } } func predict(frame: UIImage) { DispatchQueue.global().async { do { let startTime = CACurrentMediaTime() let predictions = try self.model.predict(frame: frame) let elapsed = CACurrentMediaTime() - startTime self.showResultOnMain(predictions: predictions, elapsed: Float(elapsed), error: nil) } catch let error as YOLOError { self.showResultOnMain(predictions: nil, elapsed: -1, error: error) } catch { self.showResultOnMain(predictions: nil, elapsed: -1, error: YOLOError.unknownError) } } } private func showResultOnMain(predictions: [YOLO.Prediction]?, elapsed: Float, error: YOLOError?) { if let delegate = self.delegate { DispatchQueue.main.async { let fps = self.measureFPS() delegate.show(predictions: predictions, stat: ModelProvider.Statistics(timeForFrame: elapsed, fps: fps), error: error) } } } private func measureFPS() -> Float { predicted += 1 let elapsed = CACurrentMediaTime() - timeOfFirstFrameInSecond let currentFPSDelivered = Double(predicted) / elapsed if elapsed > 1 { predicted = 0 timeOfFirstFrameInSecond = CACurrentMediaTime() } return Float(currentFPSDelivered) } } 


Pemrosesan output jaringan saraf

Sekarang mari kita mencari cara untuk memproses output dari jaringan saraf dan mendapatkan kotak pembatas yang sesuai. Dalam Xcode, jika Anda memilih file model, Anda dapat melihat apa itu dan melihat lapisan output.


Masuk dan keluar YOLOv3-mungil.


Masuk dan keluar YOLOv3-416.

Seperti yang dapat Anda lihat pada gambar di atas, kami memiliki tiga untuk YOLOv3-416 dan dua untuk lapisan keluaran YOLOv3-kecil di masing-masing kotak yang terikat untuk berbagai objek diprediksi.
Dalam hal ini, ini adalah array angka biasa, mari kita cari tahu cara menguraikannya.

Model YOLOv3 menggunakan tiga lapisan sebagai output untuk membagi gambar ke dalam kisi yang berbeda, ukuran sel dari kisi-kisi ini memiliki nilai berikut: 8, 16 dan 32. Misalkan kita memiliki gambar berukuran 416x416 piksel pada input, maka matriks keluaran (kisi) akan memiliki ukuran 52x52 , 26x26 dan 13x13 (416/8 = 52, 416/16 = 26 dan 416/32 = 13). Dalam kasus YOLOv3-tiny, semuanya sama, tetapi alih-alih tiga kisi, kita memiliki dua: 16 dan 32, yaitu, matriks 26x26 dan 13x13 dimensi.

Setelah memulai model CoreML yang dimuat, kami mendapatkan dua (atau tiga) objek kelas MLMultiArray pada output. Dan jika Anda melihat properti bentuk dari objek-objek ini, kita akan melihat gambar berikut (untuk YOLOv3-tiny):

[1,1,255,26,26][1,1,255,13,13]


Seperti yang diharapkan, dimensi matriks akan menjadi 26x26 dan 13x13. Tetapi apa artinya angka 255? Seperti yang disebutkan sebelumnya, lapisan output adalah matriks 52x52, 26x26 dan 13x13. Faktanya adalah bahwa setiap elemen dari matriks ini bukan angka, itu adalah vektor. Yaitu, lapisan keluaran adalah matriks tiga dimensi. Vektor ini memiliki dimensi B x (5 + C), di mana B adalah jumlah kotak pembatas dalam sel, C adalah jumlah kelas. Dari mana asal nomor 5? Alasannya adalah ini: untuk setiap kotak-a, probabilitas diprediksi bahwa ada objek (kepercayaan objek) - ini adalah satu angka, dan empat sisanya adalah x, y, lebar dan tinggi untuk kotak yang diprediksi-a. Gambar di bawah ini menunjukkan representasi skematis dari vektor ini:


Representasi skematis dari lapisan output (peta fitur).

Untuk jaringan kami yang terlatih dalam 80 kelas, 3 kotak pembatas-a diprediksi untuk setiap sel dari kotak partisi, untuk masing-masingnya - probabilitas kelas 80 + kepercayaan objek + 4 angka yang bertanggung jawab untuk posisi dan ukuran kotak ini-a. Total: 3 x (5 + 80) = 255.

Untuk mendapatkan nilai-nilai ini dari kelas MLMultiArray, lebih baik menggunakan pointer mentah ke array data dan alamat aritmatika:

  let pointer = UnsafeMutablePointer<Double>(OpaquePointer(out.dataPointer)) //    if out.strides.count < 3 { throw YOLOError.strideOutOfBounds } let channelStride = out.strides[out.strides.count-3].intValue let yStride = out.strides[out.strides.count-2].intValue let xStride = out.strides[out.strides.count-1].intValue func offset(ch: Int, x: Int, y: Int) -> Int { //     return ch * channelStride + y * yStride + x * xStride } 

Sekarang Anda perlu memproses vektor 255 elemen. Untuk setiap kotak, Anda perlu mendapatkan distribusi probabilitas untuk 80 kelas, Anda dapat melakukan ini menggunakan fungsi softmax.

Apa itu softmax
Fungsi mengubah vektor  mathbbxDimensi K menjadi vektor dari dimensi yang sama, di mana masing-masing koordinat  mathbbxivektor yang dihasilkan diwakili oleh bilangan real dalam interval [0,1] dan jumlah koordinat adalah 1.

 sigma( mathbbx)i= fracexi sumk=1Kexk

di mana K adalah dimensi vektor.

Fungsi Softmax di Swift:

  private func softmax(_ x: inout [Float]) { let len = vDSP_Length(x.count) var count = Int32(x.count) vvexpf(&x, x, &count) var sum: Float = 0 vDSP_sve(x, 1, &sum, len) vDSP_vsdiv(x, 1, &sum, &x, 1, len) } 

Untuk mendapatkan koordinat dan ukuran kotak pembatas-a, Anda perlu menggunakan rumus:

x= sigma( hatx)+cxy= sigma( haty)+cyw=pwe hatwh=phe hath


dimana  hatx, haty, hatw, hath- diprediksi masing-masing koordinat x, y, lebar dan tinggi,  sigma(x)Apakah fungsi sigmoid, dan pw,ph- nilai jangkar (jangkar) untuk tiga kotak. Nilai-nilai ini ditentukan selama pelatihan dan diatur dalam file Helpers.swift:

 let anchors1: [Float] = [116,90, 156,198, 373,326] //     let anchors2: [Float] = [30,61, 62,45, 59,119] //     let anchors3: [Float] = [10,13, 16,30, 33,23] //     


Representasi skematis dari perhitungan posisi kotak pembatas.

Kode lengkap untuk memproses lapisan keluaran.
  private func process(output out: MLMultiArray, name: String) throws -> [Prediction] { var predictions = [Prediction]() let grid = out.shape[out.shape.count-1].intValue let gridSize = YOLO.inputSize / Float(grid) let classesCount = labels.count print(out.shape) let pointer = UnsafeMutablePointer<Double>(OpaquePointer(out.dataPointer)) if out.strides.count < 3 { throw YOLOError.strideOutOfBounds } let channelStride = out.strides[out.strides.count-3].intValue let yStride = out.strides[out.strides.count-2].intValue let xStride = out.strides[out.strides.count-1].intValue func offset(ch: Int, x: Int, y: Int) -> Int { return ch * channelStride + y * yStride + x * xStride } for x in 0 ..< grid { for y in 0 ..< grid { for box_i in 0 ..< YOLO.boxesPerCell { let boxOffset = box_i * (classesCount + 5) let bbx = Float(pointer[offset(ch: boxOffset, x: x, y: y)]) let bby = Float(pointer[offset(ch: boxOffset + 1, x: x, y: y)]) let bbw = Float(pointer[offset(ch: boxOffset + 2, x: x, y: y)]) let bbh = Float(pointer[offset(ch: boxOffset + 3, x: x, y: y)]) let confidence = sigmoid(Float(pointer[offset(ch: boxOffset + 4, x: x, y: y)])) if confidence < confidenceThreshold { continue } let x_pos = (sigmoid(bbx) + Float(x)) * gridSize let y_pos = (sigmoid(bby) + Float(y)) * gridSize let width = exp(bbw) * self.anchors[name]![2 * box_i] let height = exp(bbh) * self.anchors[name]![2 * box_i + 1] for c in 0 ..< 80 { classes[c] = Float(pointer[offset(ch: boxOffset + 5 + c, x: x, y: y)]) } softmax(&classes) let (detectedClass, bestClassScore) = argmax(classes) let confidenceInClass = bestClassScore * confidence if confidenceInClass < confidenceThreshold { continue } predictions.append(Prediction(classIndex: detectedClass, score: confidenceInClass, rect: CGRect(x: CGFloat(x_pos - width / 2), y: CGFloat(y_pos - height / 2), width: CGFloat(width), height: CGFloat(height)))) } } } return predictions } 


Penindasan non maks

Setelah Anda menerima koordinat dan ukuran kotak pembatas dan probabilitas terkait untuk semua objek yang ditemukan dalam gambar, Anda bisa mulai menggambarnya di atas gambar. Tapi ada satu masalah! Situasi seperti itu dapat muncul ketika beberapa kotak dengan probabilitas yang agak tinggi diprediksi untuk satu objek. Apa yang harus dilakukan dalam kasus ini? Di sini algoritma yang cukup sederhana yang disebut Non maksimal suppression datang untuk membantu kami.

Algoritma adalah sebagai berikut:

  1. Kami mencari kotak pembatas dengan probabilitas tertinggi untuk memiliki objek.
  2. Kami menjalankan semua kotak terikat yang juga milik objek ini.
  3. Kami menghapusnya jika Persimpangan over Union (IoU) dengan kotak pembatas pertama lebih besar dari ambang yang ditentukan.

IoU dihitung dengan menggunakan rumus sederhana:

 textIoU= frac textAreapersimpangan textAreaAsosiasi
Perhitungan IoU.
  static func IOU(a: CGRect, b: CGRect) -> Float { let areaA = a.width * a.height if areaA <= 0 { return 0 } let areaB = b.width * b.height if areaB <= 0 { return 0 } let intersection = a.intersection(b) let intersectionArea = intersection.width * intersection.height return Float(intersectionArea / (areaA + areaB - intersectionArea)) } 


Penindasan non maks.
  private func nonMaxSuppression(boxes: inout [Prediction], threshold: Float) { var i = 0 while i < boxes.count { var j = i + 1 while j < boxes.count { let iou = YOLO.IOU(a: boxes[i].rect, b: boxes[j].rect) if iou > threshold { if boxes[i].score > boxes[j].score { if boxes[i].classIndex == boxes[j].classIndex { boxes.remove(at: j) } else { j += 1 } } else { if boxes[i].classIndex == boxes[j].classIndex { boxes.remove(at: i) j = i + 1 } else { j += 1 } } } else { j += 1 } } i += 1 } } 


Setelah itu, bekerja langsung dengan hasil prediksi jaringan saraf dapat dianggap lengkap. Selanjutnya, Anda perlu menulis fungsi dan kelas untuk mendapatkan rekaman dari kamera, menampilkan gambar di layar dan membuat kotak terikat yang diprediksi. Saya tidak akan menjelaskan semua kode ini di artikel ini, tetapi dapat dilihat di repositori.

Perlu juga disebutkan bahwa saya menambahkan sedikit penghalusan kotak pembatas saat memproses gambar online, dalam hal ini adalah rata-rata posisi dan ukuran kotak yang diprediksi selama 30 frame terakhir.

Menguji program


Sekarang kami menguji aplikasi.

Izinkan saya mengingatkan Anda sekali lagi: Ada tiga ViewControllers dalam aplikasi, satu untuk memproses foto atau foto, satu untuk memproses aliran video online, dan yang ketiga untuk mengatur jaringan.

Mari kita mulai dengan yang ketiga. Di dalamnya Anda dapat memilih salah satu dari dua model YOLOv3-tiny atau YOLOv3-416, pilih ambang batas kepercayaan dan ambang batas IoU, Anda juga dapat mengaktifkan atau menonaktifkan anti-aliasing online.


Sekarang mari kita lihat bagaimana neuron yang terlatih bekerja dengan gambar nyata, untuk ini kita mengambil foto dari galeri dan mengirimkannya melalui jaringan. Gambar di bawah ini menunjukkan hasil YOLOv3-mungil dengan pengaturan yang berbeda.


Mode operasi YOLOv3-mungil berbeda. Gambar kiri menunjukkan mode operasi yang biasa. Di tengah - ambang IoU = 1 i.e. seolah-olah penindasan Non-max hilang. Di sebelah kanan adalah ambang rendah kepercayaan objek, yaitu semua kotak pembatas yang mungkin ditampilkan.

Berikut ini adalah hasil dari YOLOv3-416. Anda mungkin memperhatikan bahwa, dibandingkan dengan YOLOv3-tiny, frame yang dihasilkan lebih benar, serta objek yang lebih kecil dalam gambar dikenali, yang sesuai dengan pekerjaan lapisan output ketiga.


Gambar diproses menggunakan YOLOv3-416.

Ketika mode operasi online dihidupkan, setiap frame diproses dan prediksi dibuat untuk itu, tes dilakukan pada iPhone XS, sehingga hasilnya cukup dapat diterima untuk kedua opsi jaringan. YOLOv3-tiny menghasilkan rata-rata 30 - 32 fps, YOLOv3-416 - dari 23 hingga 25 fps. Perangkat yang diuji cukup produktif, sehingga pada model sebelumnya hasilnya mungkin berbeda, dalam hal ini tentu saja lebih baik menggunakan YOLOv3-mungil. Poin penting lainnya: yolo-tiny.mlmodel (YOLOv3-tiny) memakan waktu sekitar 35 MB, sementara yolo.mlmodel (YOLOv3 -16) memiliki berat sekitar 250 MB, yang merupakan perbedaan yang sangat signifikan.

Kesimpulan


Akibatnya, aplikasi iOS ditulis bahwa dengan bantuan jaringan saraf dapat mengenali objek dalam gambar. Kami melihat bagaimana bekerja dengan pustaka CoreML dan bagaimana menggunakannya untuk menjalankan berbagai model pra-terlatih (omong-omong, Anda juga dapat berlatih dengannya). Masalah pengenalan objek diselesaikan menggunakan jaringan YOLOv3. Pada iPhone XS, jaringan ini (YOLOv3-tiny) mampu memproses gambar pada frekuensi ~ 30 frame per detik, yang cukup untuk operasi waktu nyata.

Kode aplikasi lengkap dapat dilihat di GitHub .

Source: https://habr.com/ru/post/id460869/


All Articles