logo
hero image

Object Detection pada iOS

Tutorial Object Detection menggunakan Create ML dan Vision Framework.
22 June 2023 · 10 Minutes

Pada artikel kali ini kita akan mempelajari bagaimana cara mendeteksi objek pada gambar di iOS.

Kita akan membuat aplikasi sederhana untuk menghitung jumlah uang koin yang ada di gambar secara real-time serta menampilkan Bounding Box dari setiap koin yang terdeteksi.

Apa itu Object Detection?

Object Detection adalah proses untuk mendeteksi keberadaan suatu objek dalam sebuah gambar. Object Detection biasanya memanfaatkan teknologi Machine Learning dalam proses pembuatannya. Salah satu contoh penerapan Object Detection adalah pada mobil Self Driving.

Object DetectionObject Detection

Di iOS sendiri kita bisa menggunakan Framework Vision untuk melakukan Object Detection. Vision merupakan salah satu Framework dari Apple yang dapat kita gunakan untuk melakukan berbagai task terkait dengan Computer Vision, misalnya seperti mendeteksi objek, mendeteksi wajah, membaca barcode, dll.

Object Detection vs Image Classification

Sebelumnya saya telah menulis artikel mengenai Image Classification pada iOS, kamu bisa membacanya di sini: https://blog.alfin.dev/article/image-classification-pada-ios.

Lalu apa bedanya dengan Object Detection? Jadi, kalau Image Classification itu akan mengembalikan hasil berupa 1 label saja yang mendeskripsikan suatu gambar. Sedangkan Object Detection bisa mengembalikan hasil lebih dari 1 label pada suatu gambar, dan pada Object Detection, kita juga akan mendapatkan Bounding Box dari setiap objek yang terdeteksi.

Melatih Model dengan Create ML

Dalam Machine Learning ada satu komponen penting bernama Model, Model adalah sebuah file yang telah dilatih untuk mengenali pola tertentu berdasarkan data yang kita berikan dan bisa membuat prediksi terhadap data baru.

Untuk membuat Model, kita akan menggunakan aplikasi Create ML bawaan Xcode, namun sebelum itu kita harus mengumpulkan dataset atau data-data yang akan kita gunakan dalam melatih Model kita.

Mengumpulkan Datasets

Silakan ambil beberapa foto uang koin. Untuk jumlahnya sendiri dari Apple disarankan minimal 30 foto per kategori. Semakin banyak Datasets yang kita punya tentunya akan semakin akurat Model kita dalam memprediksi data baru.

Lalu kita bagi Datasets kita menjadi 2 yaitu untuk training, dan untuk testing. Jumlah data testing disarankan sekitar 20% dari jumlah data training.

Tips dalam membuat Datasets

Berikut adalah beberapa tips dalam membuat Datasets agar model kita lebih akurat dalam memprediksi data baru.

  1. Minimal 30 foto per kategori.

  2. Ukuran foto setidaknya 299 x 299 pixel.

  3. Jumlah data per kategori usahakan tidak terlalu jauh, misalnya kategori "Kucing" ada 100 foto, maka kategori yang lain sebaiknya ada sekitar 100 foto juga.

  4. Ambil foto dari berbagai angle atau sudut pengambilan gambar.

  5. Ambil foto dari pencahayaan yang berbeda-beda.

  6. Ambil foto dari berbagai background.

WWDC 2019WWDC 2019

Membuat file JSON Annotation

Sebelum kita melatih Model kita dengan Datasets yang baru saja kita kumpulkan, kita perlu untuk membuat sebuah file Annotation dalam format json.

File Annotation adalah sebuah file yang mendeskripsikan kategori serta bounding box objek yang ingin kita deteksi. Format file Annotation itu seperti ini:

Annotations.json
1[
2 {
3 "imagefilename": "coin.png",
4 "annotation": [
5 {
6 "label": "Coin",
7 "coordinates": {
8 "y": 156.062,
9 "x": 195.122,
10 "height": 148.872,
11 "width": 148.03
12 }
13 }
14 ]
15 }
16]

Bounding BoxBounding Box

Nah agar lebih mudah dalam membuat file Annotation, kita bisa menggunakan aplikasi "AnnotationCreater", kamu bisa mengunduhnya di sini: https://apps.apple.com/id/app/annotationcreater/id1623375683?mt=12

Cara menggunakannya pun sangat mudah, kita tinggal import foto-foto kita, kemudian buat kategori baru, lalu gambar bounding box di mana objek yang ingin kita deteksi berada. Terakhir kita tinggal export dengan cara klik icon "Export" pada bagian kanan atas.

Aplikasi AnnotationCreaterAplikasi AnnotationCreater

Membuat Model

Silakan buka aplikasi Create ML dengan cara klik "Xcode -> Open Developer Tool -> Create ML"

Create MLCreate ML

Lalu buat dokumen baru, pilih template "Object Detection", dan beri nama "CoinDetector".

Training Model

setelah itu klik icon "+" untuk memasukkan data training dari folder "Annotation Export"

Object DetectionObject Detection

kita juga memberikan beberapa parameter seperti:

  1. Algorithm

Algoritma yang digunakan dalam training model. Pada CreateML ada 2 pilihan algoritma:

  • Full Network

Kita melatih model kita dari awal. Cocok jika kita punya banyak data (200+) dan ingin support minimal iOS 12.

Full NetworkFull Network

  • Transfer Learning

Kita menggunakan "object feature print" dari Vision. Cocok jika kita hanya punya sedikit data dan ingin ukuran dari model kita lebih kecil. Namun algoritma ini hanya mendukung iOS 14 ke atas.

Transfer LearningTransfer Learning

Model Size - Full Network vs Transfer LearningModel Size - Full Network vs Transfer Learning

  1. Iterations

Berapa kali Datasets kita ingin dilatih.

  1. Batch Size

Jumlah data yang dilatih dalam 1 Iteration. Semakin banyak Batch Size, jumlah memori yang digunakan juga akan semakin banyak.

  1. Grid Size (khusus Full Network)

Jadi cara algoritma Full Network (YOLOv2) dalam mendeteksi objek adalah dengan membagi gambar kita menjadi beberapa Cell (algoritma ini akan mendeteksi 1 objek saja dalam 1 Cell). Nah, kita bisa mengatur ukuran Cell tersebut melalui Grid Size.

Grid SizeGrid Size

kemudian kita klik "Train" untuk melatih model kita. Lalu tunggu sampai proses training selesai, training model pada Object Detection memang agak lebih lama daripada Image Classification.


Evaluasi & Preview Model

Setelah itu kita bisa mengevaluasi apakah model kita sudah cukup akurat untuk memprediksi suatu data atau belum.

EvaluationEvaluation

Kita juga bisa melakukan preview dengan cara drag image kita ke tab "Preview".

PreviewPreview

Export Model

Untuk meng-export model, silakan ke tab "Output" dan klik icon "Get" lalu pilih lokasi di mana model kita akan disimpan.

Setup Project iOS

Sekarang kita mulai membuat project iOS nya. Silakan buka Xcode dan buat project baru dengan cara klik "File -> New -> Project", pilih interface "Storyboard" dan "Swift" sebagai bahasanya.

Setelah itu tarik file model yang telah kita buat (berekstensi .mlmodel) ke dalam project kita.

Membuat UI

Tampilan dari aplikasi yang akan kita buat cukup sederhana, yaitu:

  1. Preview View (UIView): Untuk menampilkan preview dari kamera.

  2. Total Label (UILabel): Untuk menampilkan label dari jumlah koin yang terdeteksi.

Jadi, silakan buat UI nya di Storyboard, dan jangan lupa untuk menghubungkan outlet-nya ke class ViewController

StoryboardStoryboard

ViewController.swift
icon
1class ViewController: UIViewController {
2
3 @IBOutlet weak var previewView: UIView!
4 @IBOutlet weak var totalLabel: UILabel!
5
6 override func viewDidLoad() {
7 super.viewDidLoad()
8 }
9}

Setup Layers

Kita akan membuat 2 CALayer, yang pertama previewLayer untuk menampilkan Preview dari kamera, kemudian yang kedua adalah detectionLayer untuk menggambar Bounding Box dari setiap koin yang terdeteksi.

Lalu kita juga perlu menambahkan sebuah method bernama updateLayerGeometry untuk memperbaiki posisi dan ukuran dari detectionLayer.

ViewController.swift
icon
1private var previewLayer: AVCaptureVideoPreviewLayer!
2private var detectionLayer: CALayer!
3
4override func viewDidLoad() {
5 super.viewDidLoad()
6
7 setupLayers()
8 updateLayerGeometry()
9}
10
11private func setupLayers() {
12 // Configure the preview layer
13 previewLayer = AVCaptureVideoPreviewLayer(session: session)
14 previewLayer.videoGravity = .resizeAspectFill
15 previewLayer.frame = self.previewView.layer.bounds
16 self.previewView.layer.addSublayer(previewLayer)
17
18 // Configure the detection Layer
19 detectionLayer = CALayer()
20 detectionLayer.bounds = CGRect(
21 x: 0.0,
22 y: 0.0,
23 width: cameraSize.width,
24 height: cameraSize.height
25 )
26 detectionLayer.position = CGPoint(
27 x: self.previewView.layer.bounds.midX,
28 y: self.previewView.layer.bounds.midY
29 )
30 self.previewView.layer.addSublayer(detectionLayer)
31}
32
33private func updateLayerGeometry() {
34 let bounds = self.previewView.layer.bounds
35
36 let xScale: CGFloat = bounds.size.width / cameraSize.height
37 let yScale: CGFloat = bounds.size.height / cameraSize.width
38
39 var scale = fmax(xScale, yScale)
40 if scale.isInfinite {
41 scale = 1.0
42 }
43
44 CATransaction.begin()
45 CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
46
47 // rotate the layer into screen orientation, scale and mirror
48 detectionLayer.setAffineTransform(
49 CGAffineTransform(
50 rotationAngle: CGFloat(.pi / 2.0)
51 )
52 .scaledBy(x: scale, y: -scale)
53 )
54
55 // center the layer
56 detectionLayer.position = CGPoint(x: bounds.midX, y: bounds.midY)
57
58 CATransaction.commit()
59}

Setup Vision

Membuat Request

Tambahkan kode berikut pada file ViewController.swift

ViewController.swift
icon
1import UIKit
3import Vision
4import CoreML
6
7class ViewController: UIViewController {
8
9 @IBOutlet weak var previewView: UIView!
10 @IBOutlet weak var totalLabel: UILabel!
11
13 private var request: VNCoreMLRequest!
14 private var previewLayer: AVCaptureVideoPreviewLayer!
15 private var detectionLayer: CALayer!
16
17 override func viewDidLoad() {
18 super.viewDidLoad()
19
21 setupVision()
22
23 setupLayers()
24 updateLayerGeometry()
25 }
26
28 private func setupVision() {
29 guard let coinDetector = try? CoinDetector(configuration: MLModelConfiguration()) else {
30 fatalError("Failed to create an object detector model instance.")
31 }
32
33 guard let model = try? VNCoreMLModel(for: coinDetector.model) else {
34 fatalError("Failed to create a `VNCoreMLModel` instance.")
35 }
36
37 let request = VNCoreMLRequest(
38 model: model,
39 completionHandler: visionRequestHandler
40 )
41 request.imageCropAndScaleOption = .scaleFit
42 self.request = request
43 }
45}

Pada method setupVision, kita membuat Vision Request untuk melakukan Object Detection menggunakan Model kita, Request ini nantinya akan dijalankan pada setiap frame sehingga akan terlihat real-time.

Handling Results

Kemudian kita handling hasil dari proses Object Detection, kita akan menampilkan Bounding Box dari setiap koin yang terdeteksi serta meng-update Label kita sesuai dengan jumlah koin yang terdeteksi.

ViewController.swift
icon
1private func visionRequestHandler(_ request: VNRequest, error: Error?) {
2 if let error = error {
3 print("Vision image detection error: \(error.localizedDescription)")
4 return
5 }
6
7 if request.results == nil {
8 print("Vision request had no results.")
9 return
10 }
11
12 guard let observations = request.results as? [VNRecognizedObjectObservation] else {
13 print("VNRequest produced the wrong result type: \(type(of: request.results)).")
14 return
15 }
16
17 DispatchQueue.main.async {
18 CATransaction.begin()
19 CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
20
21 self.detectionLayer.sublayers = nil // remove all the old recognized objects
22 for observation in observations {
23 let objectBounds = VNImageRectForNormalizedRect(
24 observation.boundingBox,
25 Int(self.cameraSize.width),
26 Int(self.cameraSize.height)
27 )
28
29 let shapeLayer = self.createRoundedRectLayer(objectBounds)
30 self.detectionLayer.addSublayer(shapeLayer)
31 }
32 self.updateLayerGeometry()
33 CATransaction.commit()
34
35 // Set Total Label
36 let total = observations.count
37 self.totalLabel.text = "\(total) Coins"
38 }
39}
40
41private func createRoundedRectLayer(_ bounds: CGRect) -> CALayer {
42 let shapeLayer = CALayer()
43 shapeLayer.bounds = bounds
44 shapeLayer.position = CGPoint(x: bounds.midX, y: bounds.midY)
45 shapeLayer.backgroundColor = UIColor.yellow.withAlphaComponent(0.15).cgColor
46 shapeLayer.cornerRadius = 8
47 shapeLayer.borderColor = UIColor.yellow.cgColor
48 shapeLayer.borderWidth = 1.5
49 return shapeLayer
50}

Setup Capture Session

Sekarang, kita akan mengintegrasikan Vision dengan AVFoundation agar bisa mendeteksi objek secara real-time.

Pada file bagian paling atas, silakan import AVFoundation:

icon
1import AVFoundation

Lalu setelah deklarasi properti detectionLayer, tambahkan beberapa properti berikut:

icon
1private var request: VNCoreMLRequest!
2
3private var previewLayer: AVCaptureVideoPreviewLayer!
4private var detectionLayer: CALayer!
5
7private let session = AVCaptureSession()
8private var cameraSize: CGSize!
9private let videoOutputQueue = DispatchQueue(label: "video-output-queue", qos: .userInitiated)

Kemudian tambahkan function berikut untuk Setup Capture Session:

icon
1private func setupCaptureSession() {
2 session.beginConfiguration()
3
4 // Add the video input to the capture session
5 let camera = AVCaptureDevice.default(
6 .builtInWideAngleCamera,
7 for: .video,
8 position: .back
9 )!
10
11 // Connect the camera to the capture session input
12 let cameraInput = try! AVCaptureDeviceInput(device: camera)
13 session.addInput(cameraInput)
14
15 session.sessionPreset = .vga640x480
16
17 // Create the video data output
18 let videoOutput = AVCaptureVideoDataOutput()
19 videoOutput.alwaysDiscardsLateVideoFrames = true
20 videoOutput.videoSettings = [
21 String(kCVPixelBufferPixelFormatTypeKey): Int(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)
22 ]
23 videoOutput.setSampleBufferDelegate(self, queue: videoOutputQueue)
24
25 // Add the video output to the capture session
26 session.addOutput(videoOutput)
27
28 // Set camera size
29 let dimension = CMVideoFormatDescriptionGetDimensions(camera.activeFormat.formatDescription)
30 cameraSize = CGSize(
31 width: CGFloat(dimension.width),
32 height: CGFloat(dimension.height)
33 )
34
35 session.commitConfiguration()
36}

Pada kode di atas, kita mendelegasikan SampleBufferDelegate ke self agar kita bisa mengakses tiap frame yang dicapture oleh AVFoundation. Nah, kita akan mendeteksi objek terhadap frame-frame tersebut.

Silakan tambahkan kode berikut di bagian paling bawah:

icon
1extension ViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
2 func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
3 guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
4
5 do {
6 let handler = VNImageRequestHandler(cvPixelBuffer: imageBuffer)
7 try handler.perform([request])
8 } catch {
9 print(error.localizedDescription)
10 }
11 }
12}

Terakhir, kita akan menjalankan Capture Session. Ubah isi dari viewDidLoad menjadi seperti ini:

icon
1override func viewDidLoad() {
2 super.viewDidLoad()
3
4 setupVision()
6 setupCaptureSession()
7
8 setupLayers()
9 updateLayerGeometry()
10
12 DispatchQueue.global(qos: .background).async {
13 self.session.startRunning()
14 }
16}

Kalau kita jalankan aplikasinya, maka hasilnya akan seperti ini 🎉

Coin Detector AppCoin Detector App


What's Next?

Sekarang kita telah mengetahui bagaimana cara membuat aplikasi Object Detection menggunakan Create ML dan Vision Framework serta mengintegrasikannya dengan AVFoundation agar kita bisa mendeteksi objek secara real-time, selanjutnya mungkin kamu bisa kembangkan lagi project ini untuk mendeteksi koin sesuai nominalnya apakah Rp100, Rp500, Rp1000, atau kamu bisa juga menambahkan suara menggunakan AVSpeechSynthesizer ketika koin terdeteksi, dll 😄

Oke mungkin itu saja yang bisa saya bagikan kali ini, kalau kamu merasa artikel ini bermanfaat silakan Like & Share artikel ini ke teman-teman kamu atau jika kamu punya pertanyaan, tulis aja di kolom komentar, Thank you! 😁 🙏

Source code lengkapnya bisa kamu lihat melalui link berikut: https://github.com/alfinsyahruddin/CoinDetector

iOS Development
Swift
Vision
Create ML
Artificial Intelligence

Written by :
Alfin Syahruddin
Developer · Stock Trader · Libertarian · Freethinker

Always open to new ideas. 🕊️

Loading...

Related articles

Articles that you might want to read.

hero image
Image Classification pada iOS

Tutorial Image Classification menggunakan Create ML dan Vision Framework.

18 June 2023 · 7 Minutes
iOS Development
Swift
Vision
Create ML
Artificial Intelligence
hero image
Tutorial membuat aplikasi Image Classification dengan Flutter dan Teachable Machine

Buat aplikasi AI pertama-mu dalam 10 menit ⚡️

17 January 2021 · 9 Minutes
Flutter
Artificial Intelligence
Image Classification
Teachable Machine
Cross Platform
hero image
Testable Code

Menulis kode yang mudah untuk di-test pada Swift.

1 May 2023 · 8 Minutes
iOS Development
Swift
Testing
All rights reserved © Alfin Syahruddin · 2019
RSS Feed