Hal yang akan Anda buat
Dalam tutorial ini, Anda akan mendownload model TensorFlow Lite kustom yang diekspor dari AutoML Vision Edge. Kemudian, Anda akan menjalankan aplikasi iOS siap pakai yang menggunakan model untuk mendeteksi beberapa objek dalam gambar (dengan kotak pembatas), dan memberikan pelabelan kustom kategori objek.
Tujuan
Dalam panduan pengantar menyeluruh ini, Anda akan menggunakan kode untuk:
- Jalankan model AutoML Vision Object Detection Edge di aplikasi iOS menggunakan penafsir TF Lite.
Sebelum memulai
Meng-clone repositori Git
Dengan menggunakan command line, clone repositori Git berikut dengan perintah berikut:
git clone https://github.com/tensorflow/examples.git
Buka direktori ios
clone lokal repositori
(examples/lite/examples/object_detection/ios/
). Anda akan menjalankan semua contoh
kode berikut dari direktori ios
:
cd examples/lite/examples/object_detection/ios
Prasyarat
- Git diinstal.
- Versi iOS yang didukung: iOS 12.0 dan yang lebih baru.
Menyiapkan aplikasi iOS
Membuat & membuka file ruang kerja
Untuk mulai menyiapkan aplikasi iOS asli, Anda harus terlebih dahulu membuat file ruang kerja menggunakan software yang diperlukan:
Buka folder
ios
jika Anda belum melakukannya:cd examples/lite/examples/object_detection/ios
Instal pod untuk membuat file ruang kerja:
pod install
Jika Anda sudah pernah menginstal pod ini, gunakan perintah berikut:
pod update
Setelah membuat file ruang kerja, Anda dapat membuka project dengan Xcode. Untuk membuka project melalui command line, jalankan perintah berikut dari direktori
ios
:open ./ObjectDetection.xcworkspace
Membuat ID unik & membuat aplikasi
Saat ObjectDetection.xcworkspace
terbuka di Xcode, Anda harus terlebih dahulu mengubah
ID paket (ID paket) ke nilai yang unik.
Pilih item project
ObjectDetection
teratas pada navigator project di sebelah kiri.Pastikan Anda telah memilih Targets > ObjectDetection.
Di bagian General > Identity, ubah kolom ID Paket ke nilai yang unik. Gaya yang lebih disukai adalah notasi nama domain terbalik.
Di bagian Umum > Penandatanganan di bawah Identitas, tentukan Tim dari menu drop-down. Nilai ini diberikan dari ID Developer Anda.
Hubungkan perangkat iOS ke komputer Anda. Setelah perangkat terdeteksi, pilih dari daftar perangkat.
Setelah menentukan semua perubahan konfigurasi, build aplikasi di Xcode menggunakan perintah berikut: Command + B.
Menjalankan aplikasi asli
Aplikasi contoh adalah aplikasi kamera yang terus mendeteksi objek (kotak pembatas dan label) dalam frame yang terlihat oleh kamera belakang perangkat, menggunakan model SSD MobileNet terkuantifikasi yang dilatih pada COCO.
Petunjuk ini akan memandu Anda dalam membuat dan menjalankan demo di perangkat iOS.
File model didownload melalui skrip di Xcode saat Anda mem-build dan menjalankan. Anda tidak perlu melakukan langkah-langkah apa pun untuk mendownload model TF Lite ke dalam project secara eksplisit.
Sebelum memasukkan model yang disesuaikan, uji versi dasar aplikasi yang menggunakan model terlatih "mobilenet" dasar.
Untuk meluncurkan aplikasi di Simulator, pilih tombol play di sudut kiri atas jendela Xcode.
Setelah Anda mengizinkan aplikasi mengakses kamera dengan memilih tombol Izinkan aplikasi akan memulai deteksi dan anotasi langsung. Objek akan dideteksi dan ditandai dengan kotak pembatas dan label di setiap frame kamera.
Pindahkan perangkat ke berbagai objek di sekeliling Anda dan pastikan aplikasi mendeteksi gambar dengan benar.
Menjalankan aplikasi yang disesuaikan
Ubah aplikasi agar dapat menggunakan model yang dilatih ulang dengan kategori gambar objek kustom.
Menambahkan file model Anda ke project
Project demo dikonfigurasi untuk menelusuri dua file dalam
direktori ios/objectDetection/model
:
detect.tflite
labelmap.txt
Untuk mengganti kedua file tersebut dengan versi kustom Anda, jalankan perintah berikut:
cp tf_files/optimized_graph.lite ios/objectDetection/model/detect.tflite cp tf_files/retrained_labels.txt ios/objectDetection/model/labelmap.txt
Jalankan aplikasi Anda
Untuk meluncurkan kembali aplikasi di perangkat iOS, pilih tombol play di sudut kiri atas jendela Xcode.
Untuk menguji modifikasi, gerakkan kamera perangkat Anda ke berbagai objek untuk melihat prediksi langsung.
Hasilnya akan terlihat seperti ini:
Bagaimana cara kerjanya?
Setelah aplikasi berjalan, lihat kode khusus TensorFlow Lite.
Pod TensorFlowLite
Aplikasi ini menggunakan TFLite Cocoapod yang telah dikompilasi sebelumnya. Podfile berisi cocoapod dalam project:
# Uncomment the next line to define a global platform for your project platform :ios, '12.0' target 'ObjectDetection' do # Comment the next line if you're not using Swift and don't want to use dynamic frameworks use_frameworks! # Pods for ObjectDetection pod 'TensorFlowLiteSwift' end
Kode yang berinteraksi ke TF Lite ada di dalam
file ModelDataHandler.swift
. Class ini menangani semua pra-pemrosesan data dan
membuat panggilan untuk menjalankan inferensi pada frame tertentu dengan memanggil Interpreter
.
Kemudian, fitur ini akan memformat inferensi yang diperoleh dan menampilkan
hasil N teratas untuk inferensi yang berhasil.
Menjelajahi kode
Blok minat pertama (setelah impor yang diperlukan) adalah deklarasi
properti. Parameter inputShape
model tfLite (batchSize
,
inputChannels
, inputWidth
, inputHeight
) dapat ditemukan di
tflite_metadata.json
. Anda akan memiliki file ini saat mengekspor
model tflite. Untuk mengetahui info selengkapnya, buka topik petunjuk Mengekspor model Edge.
Contoh tflite_metadata.json
terlihat mirip dengan kode berikut:
{ "inferenceType": "QUANTIZED_UINT8", "inputShape": [ 1, // This represents batch size 512, // This represents image width 512, // This represents image Height 3 //This represents inputChannels ], "inputTensor": "normalized_input_image_tensor", "maxDetections": 20, // This represents max number of boxes. "outputTensorRepresentation": [ "bounding_boxes", "class_labels", "class_confidences", "num_of_boxes" ], "outputTensors": [ "TFLite_Detection_PostProcess", "TFLite_Detection_PostProcess:1", "TFLite_Detection_PostProcess:2", "TFLite_Detection_PostProcess:3" ] } ...
Parameter model:
Ganti nilai di bawah sesuai dengan file tflite_metadata.json
untuk
model Anda.
let batchSize = 1 //Number of images to get prediction, the model takes 1 image at a time let inputChannels = 3 //The pixels of the image input represented in RGB values let inputWidth = 300 //Width of the image let inputHeight = 300 //Height of the image ...
init
Metode init, yang membuat Interpreter
dengan Model
jalur
dan InterpreterOptions
, lalu mengalokasikan memori untuk input model.
init?(modelFileInfo: FileInfo, labelsFileInfo: FileInfo, threadCount: Int = 1) { let modelFilename = modelFileInfo.name // Construct the path to the model file. guard let modelPath = Bundle.main.path(forResource: modelFilename,ofType: modelFileInfo.extension) // Specify the options for the `Interpreter`. var options = InterpreterOptions() options.threadCount = threadCount do { // Create the `Interpreter`. interpreter = try Interpreter(modelPath: modelPath, options: options) // Allocate memory for the model's input `Tensor`s. try interpreter.allocateTensors() } super.init() // Load the classes listed in the labels file. loadLabels(fileInfo: labelsFileInfo) } …
runModel
Metode runModel
di bawah:
- Menskalakan gambar input ke rasio aspek yang modelnya dilatih.
- Menghapus komponen alfa dari buffering gambar untuk mendapatkan data RGB.
- Menyalin data RGB ke Tensor input.
- Menjalankan inferensi dengan memanggil
Interpreter
. - Mendapatkan output dari Penerjemah.
- Memformat output.
func runModel(onFrame pixelBuffer: CVPixelBuffer) -> Result? {
Pangkas gambar ke persegi terbesar di tengah dan perkecil skalanya untuk menyesuaikan dimensi model:
let scaledSize = CGSize(width: inputWidth, height: inputHeight) guard let scaledPixelBuffer = pixelBuffer.resized(to: scaledSize) else { return nil } ... do { let inputTensor = try interpreter.input(at: 0)
Hapus komponen alfa dari buffering gambar untuk mendapatkan data RGB:
guard let rgbData = rgbDataFromBuffer( scaledPixelBuffer, byteCount: batchSize * inputWidth * inputHeight * inputChannels, isModelQuantized: inputTensor.dataType == .uInt8 ) else { print("Failed to convert the image buffer to RGB data.") return nil }
Salin data RGB ke Tensor
input:
try interpreter.copy(rgbData, toInputAt: 0)
Jalankan inferensi dengan memanggil Interpreter
:
let startDate = Date() try interpreter.invoke() interval = Date().timeIntervalSince(startDate) * 1000 outputBoundingBox = try interpreter.output(at: 0) outputClasses = try interpreter.output(at: 1) outputScores = try interpreter.output(at: 2) outputCount = try interpreter.output(at: 3) }
Memformat hasil:
let resultArray = formatResults( boundingBox: [Float](unsafeData: outputBoundingBox.data) ?? [], outputClasses: [Float](unsafeData: outputClasses.data) ?? [], outputScores: [Float](unsafeData: outputScores.data) ?? [], outputCount: Int(([Float](unsafeData: outputCount.data) ?? [0])[0]), width: CGFloat(imageWidth), height: CGFloat(imageHeight) ) ... }
Memfilter semua hasil dengan skor keyakinan < ambang batas dan menampilkan N hasil teratas yang diurutkan dalam urutan menurun:
func formatResults(boundingBox: [Float], outputClasses: [Float], outputScores: [Float], outputCount: Int, width: CGFloat, height: CGFloat) -> [Inference]{ var resultsArray: [Inference] = [] for i in 0...outputCount - 1 { let score = outputScores[i]
Filter hasil dengan keyakinan < ambang batas:
guard score >= threshold else { continue }
Mendapatkan nama class output untuk class yang terdeteksi dari daftar label:
let outputClassIndex = Int(outputClasses[i]) let outputClass = labels[outputClassIndex + 1] var rect: CGRect = CGRect.zero
Menerjemahkan kotak pembatas yang terdeteksi ke CGRect.
rect.origin.y = CGFloat(boundingBox[4*i]) rect.origin.x = CGFloat(boundingBox[4*i+1]) rect.size.height = CGFloat(boundingBox[4*i+2]) - rect.origin.y rect.size.width = CGFloat(boundingBox[4*i+3]) - rect.origin.x
Sudut yang terdeteksi adalah untuk dimensi model. Jadi, kita menskalakan rect
sesuai
dengan dimensi gambar yang sebenarnya.
let newRect = rect.applying(CGAffineTransform(scaleX: width, y: height))
Mendapatkan warna yang ditetapkan untuk class:
let colorToAssign = colorForClass(withIndex: outputClassIndex + 1) let inference = Inference(confidence: score, className: outputClass, rect: newRect, displayColor: colorToAssign) resultsArray.append(inference) } // Sort results in descending order of confidence. resultsArray.sort { (first, second) -> Bool in return first.confidence > second.confidence } return resultsArray }
CameraFeedManager
CameraFeedManager.swift
mengelola semua fungsi terkait kamera.
Tindakan ini akan melakukan inisialisasi dan mengonfigurasi AVCaptureSession:
private func configureSession() {
session.beginConfiguration()
Kemudian, kode ini akan mencoba menambahkan
AVCaptureDeviceInput
dan menambahkanbuiltInWideAngleCamera
sebagai input perangkat untuk Sesi.addVideoDeviceInput()
Kemudian, kode ini akan mencoba menambahkan
AVCaptureVideoDataOutput
:addVideoDataOutput()
session.commitConfiguration() self.cameraConfiguration = .success }
Memulai sesi.
Menghentikan sesi.
Menambahkan dan menghapus notifikasi
AVCaptureSession
.
Penanganan Error:
- NSNotification.Name.AVCaptureSessionRuntimeError: Pesan
ini diposting saat terjadi
error yang tidak terduga saat instance
AVCaptureSession
berjalan. Kamus userInfo berisi objekNSError
untuk kunciAVCaptureSessionErrorKey
. - NSNotification.Name.AVCaptureSessionWasInterrupted: Pesan ini
diposting saat gangguan
(mis. Panggilan telepon, alarm, dll.) terjadi. Jika sesuai, instance
AVCaptureSession
akan berhenti berjalan secara otomatis karena gangguan respons. userInfo akan berisiAVCaptureSessionInterruptionReasonKey
yang menunjukkan alasan gangguan. - NSNotification.Name.AVCaptureSessionInterruptionEnded: Pesan ini
diposting saat
AVCaptureSession
menghentikan gangguan. Instance sesi dapat dilanjutkan setelah gangguan seperti panggilan telepon berakhir.
Class InferenceViewController.swift bertanggung jawab di bawah layar, yang mana sebagai fokus utama kita akan menjadi bagian yang ditandai.
- Resolution: Fitur ini menampilkan resolusi frame saat ini (Gambar dari sesi Video).
- Pangkas: Menampilkan ukuran pemangkasan frame yang aktif.
- InferenceTime: Metrik ini menampilkan berapa lama waktu yang diperlukan model untuk mendeteksi objek.
- Thread: Panel ini menampilkan jumlah thread yang berjalan.
Pengguna dapat menambah atau mengurangi jumlah ini dengan mengetuk tanda
+
atau-
Stepper. Jumlah thread saat ini yang digunakan oleh TensorFlow Lite Interpreter.
Class ViewController.swift menyimpan instance CameraFeedManager
, yang mengelola fungsi terkait kamera dan ModelDataHandler
. ModelDataHandler
menangani Model
(model terlatih) dan
mendapatkan output untuk frame gambar sesi video.
private lazy var cameraFeedManager = CameraFeedManager(previewView: previewView) private var modelDataHandler: ModelDataHandler? = ModelDataHandler(modelFileInfo: MobileNetSSD.modelInfo, labelsFileInfo: MobileNetSSD.labelsInfo)
Mulai sesi kamera dengan memanggil:
cameraFeedManager.checkCameraConfigurationAndStartSession()
Jika Anda mengubah jumlah thread, class ini akan menginisialisasi ulang model dengan jumlah thread baru dalam fungsi didChangeThreadCount
.
Class CameraFeedManager
akan mengirim ImageFrame
sebagai CVPixelBuffer
ke ViewController
, yang akan dikirim ke model untuk prediksi.
Metode ini menjalankan pixelBuffer
kamera live melalui TensorFlow untuk mendapatkan
hasilnya.
@objc func runModel(onPixelBuffer pixelBuffer: CVPixelBuffer) {
Jalankan pixelBuffer k amera live melalui tensorFlow untuk mendapatkan hasil:
result = self.modelDataHandler?.runModel(onFrame: pixelBuffer) ... let displayResult = result let width = CVPixelBufferGetWidth(pixelBuffer) let height = CVPixelBufferGetHeight(pixelBuffer) DispatchQueue.main.async {
Tampilkan hasil dengan memberikan ke InferenceViewController
:
self.inferenceViewController?.resolution = CGSize(width: width, height: height) self.inferenceViewController?.inferenceTime = inferenceTime
Menggambar kotak pembatas dan menampilkan nama kelas dan skor keyakinan:
self.drawAfterPerformingCalculations(onInferences: displayResult.inferences, withImageSize: CGSize(width: CGFloat(width), height: CGFloat(height))) } }
Apa Selanjutnya
Sekarang Anda telah menyelesaikan panduan aplikasi deteksi dan anotasi objek iOS menggunakan model Edge. Anda telah menggunakan model Edge Tensorflow Lite yang terlatih untuk menguji aplikasi deteksi objek sebelum memodifikasinya dan mendapatkan anotasi contoh. Anda kemudian memeriksa kode khusus TensorFlow Lite untuk memahami fungsionalitas yang mendasarinya.
Referensi berikut dapat membantu Anda terus mempelajari model TensorFlow dan AutoML Vision Edge:
- Pelajari TFLite lebih lanjut dari dokumentasi resmi dan repositori kode.
- Coba beberapa model siap TFLite lainnya, termasuk detektor kata kunci ucapan dan versi smart reply di perangkat.
- Pelajari lebih lanjut TensorFlow secara umum dengan dokumentasi memulai TensorFlow.