
Vision merupakan salah satu Framework dari Apple yang dapat kita gunakan untuk melakukan berbagai task terkait dengan Computer Vision, misalnya seperti mendeteksi wajah, mendeteksi teks dalam gambar, membaca barcode, dll.
Pada iOS 15 Apple menambahkan fitur baru dalam Framework Vision untuk melakukan Person Segmentation.
Person / Image Segmentation itu hampir sama seperti Object Detection, bedanya jika Object Detection akan mengembalikan hasil berupa bounding box suatu object, sedangkan Image Segmentation akan mengembalikan hasil pixel mask suatu object.
Object Detection vs Image SegmentationAda 2 macam Image Segmentation, yaitu:
Semantic Segmentation adalah proses untuk mendeteksi dan mengelompokkan objects berdasarkan kelas yang sama.
Instance Segmentation adalah proses untuk mendeteksi suatu object tanpa mengelompokkannya.
Jadi jika kita melakukan Semantic Segmentation pada foto hewan di atas, maka hasilnya adalah 1 pixel mask yang berisi beberapa hewan. Sedangkan jika Instance Segmentation hasilnya adalah 4 pixel mask dari masing-masing hewan (seperti foto di atas).
Fitur Person Segmentation yang ada pada Framework Vision itu menggunakan Semantic Segmentation. Jadi, hasil yang dikembalikan adalah 1 pixel mask saja meskipun ada beberapa orang dalam satu foto.
Nah, pada artikel kali ini kita akan belajar bagaimana cara mengubah background foto menggunakan pada Framework Vision.
Pertama, Silakan download dulu starter project-nya di sini: https://github.com/alfinsyahruddin/BGChanger
Projectnya cukup sederhana, terdiri dari 2 halaman:
Home Page: halaman utama untuk mengubah background foto.
Output Page: halaman untuk menampilkan hasil dari Person Segmentation.
BGChangerUntuk mengikuti tutorial ini silakan siapkan iPhone fisik dengan versi iOS >= 15.0
Berikut adalah langkah-langkah untuk melakukan Person Segmentation:
Membuat Request Person Segmentation
Membuat Request Handler untuk Request tersebut
Menjalankan Request
Memproses hasil dari Request tersebut
Silakan buka file "HomeViewModel.swift" kemudian import framework Vision.
HomeViewModel.swift1import SwiftUI2import Combine4import Vision
Kemudian tambahkan kode berikut pada class HomeViewModel :
HomeViewModel.swift1private let request = VNGeneratePersonSegmentationRequest()
di atas adalah kode untuk membuat instance dari Image Segmentation request. Request ini bisa digunakan berulang kali, jadi bisa kita gunakan untuk melakukan Image Segmentation dari frame-frame suatu video / live camera.
Sekarang, kita akan membuat Request Handler untuk Request yang telah kita buat.
Silakan tambahkan kode berikut di dalam method changeBackground :
HomeViewModel.swift1func changeBackground() {3 guard let backgroundImage = backgroundImage.cgImage,4 let foregroundImage = foregroundImage.cgImage5 else {6 print("Missing required images")7 return8 }1012 let requestHandler = VNImageRequestHandler(13 cgImage: foregroundImage,14 options: [:]15 )17}
Penjelasan kode:
Pertama, kita ubah dulu tipe gambar kita dari UIImage ke CGImage, karena tipe gambar yang didukung oleh Vision adalah CGImage.
Kemudian, kita buat Request Handler-nya yang berisi gambar yang ingin kita ubah background-nya.
Kita akan menjalankan Request menggunakan Request Handler yang telah kita buat.
Tambahkan kode berikut di dalam method changeBackground :
HomeViewModel.swift1 do {3 try requestHandler.perform([request])46 guard let mask = request.results?.first else {7 print("Error generating person segmentation mask.")8 return9 }1113 let foreground = CIImage(cgImage: foregroundImage)14 let maskImage = CIImage(cvPixelBuffer: mask.pixelBuffer)15 let background = CIImage(cgImage: backgroundImage)1718 // TODO: Blend Images19 } catch {20 print("Error processing person segmentation request")21 }
Penjelasan kode:
Method perform(_:) digunakan untuk menjalankan / memproses Request yang telah kita buat.
Lalu kita dapatkan hasil dari proses Image Segmentation menggunakan request.results?.first
Terakhir, kita akan memproses hasil dari Image Segmentation. Kita akan memasking gambar foreground agar backgroundnya menjadi transparan, kemudian kita gabungkan gambar yang telah di-masking tersebut dengan gambar background yang kita inginkan.
Tambahkan kode berikut di dalam method changeBackground :
HomeViewModel.swift1guard let output = blendImages(2 background: CIImage(cgImage: backgroundImage),3 foreground: CIImage(cgImage: foregroundImage),4 mask: CIImage(cvPixelBuffer: mask.pixelBuffer)5) else {6 print("Error blending images")7 return8}910if let result = convertImage(output) {11 self.output = result12 self.showOutput = true13}
Penjelasan kode:
Kita gabungkan antara foreground dan background menggunakan method blendImages, namun kita perlu ubah dulu tipe gambarnya menjadi CIImage karena kita akan menggunakan framework Core Image untuk blending-nya.
Setelah kita dapat hasil dari proses blending, kita convert tipe gambarnya menjadi UIImage agar bisa ditampilkan di SwiftUI.
Berikut adalah implementasi dari method blendImages dan convertImage :
HomeViewModel.swift1private let context = CIContext()23private func blendImages(4 background: CIImage,5 foreground: CIImage,6 mask: CIImage7) -> CIImage? {8 let maskScaleX = foreground.extent.width / mask.extent.width9 let maskScaleY = foreground.extent.height / mask.extent.height10 let maskScaled = mask.transformed(11 by: __CGAffineTransformMake(maskScaleX, 0, 0, maskScaleY, 0, 0)12 )1314 let backgroundScaleX = (foreground.extent.width / background.extent.width)15 let backgroundScaleY = (foreground.extent.height / background.extent.height)16 let backgroundScaled = background.transformed(17 by: __CGAffineTransformMake(backgroundScaleX, 0, 0, backgroundScaleY, 0, 0)18 )1920 let blendFilter = CIFilter.blendWithMask()21 blendFilter.inputImage = foreground22 blendFilter.maskImage = maskScaled23 blendFilter.backgroundImage = backgroundScaled2425 return blendFilter.outputImage26}2728private func convertImage(_ image: CIImage) -> UIImage? {29 guard let cgImage = context.createCGImage(image, from: image.extent) else {30 return nil31 }32 return UIImage(cgImage: cgImage)33}
dan jangan lupa import CIFilterBuiltins dari framework Core Image:
HomeViewModel.swift1import SwiftUI2import Combine3import Vision5import CoreImage.CIFilterBuiltins
Lalu jalankan project kita menggunakan iPhone fisik (tidak bisa di Simulator), maka hasilnya akan seperti ini:
OutputSecara default, Segmentation Request yang kita buat itu menggunakan Quality Level accurate, berikut adalah beberapa Quality Level yang bisa kita gunakan:
accurate: Jika kita ingin kualitas yang paling tinggi, Cocok untuk foto.
balanced: Cocok untuk memproses video.
fast: Cocok untuk memproses video streaming.
Jika kamu ingin mengatur Quality Level, caranya seperti ini:
1request.qualityLevel = .accurate
Quality LevelNamun perlu diketahui bahwa semakin tinggi Quality Level-nya maka memory, frame size dan waktu yang dibutuhkan untuk memprosesnya juga akan semakin meningkat!
Quality Level Tarde-OffSekarang kita telah mengetahui bagaimana cara mengubah background foto menggunakan framework Vision, selanjutnya mungkin kamu bisa tambahkan fitur di project ini untuk mengubah background pada video secara real time, dll 😄
Selain Vision, kita juga bisa melakukan Person Segmentation menggunakan beberapa framework berikut:
AVFoundation, melalui properti portraitEffectsMatte pada AVCapturePhoto
ARKit, melalui properti segmentationBuffer pada ARFrame
Core Image, menggunakan CIFilter.personSegmentation()
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! 😁 🙏
Referensi:
Always open to new ideas 🕊️
Articles that you might want to read.

Tutorial Object Detection menggunakan Create ML dan Vision Framework.

Tutorial Image Classification menggunakan Create ML dan Vision Framework.

Sebuah Reactive Framework dari Apple.