VNCoreMLRequest — adalah subclass dari VNRequest yang memungkinkan menjalankan model Core ML di dalam pipeline Vision, menggabungkan keunggulan detektor Vision yang sudah jadi (wajah, teks, objek) dengan model ML kustom untuk klasifikasi dan regresi. Menurut Apple Machine Learning Documentation (2024), VNCoreMLRequest secara otomatis menangani prapemrosesan gambar — penskalaan, pemotongan, dan konversi ruang warna — sesuai dengan persyaratan model Core ML.
Poin Penting
VNCoreMLRequest — adalah subclass dari VNRequest, ditambahkan di iOS 11 bersama Vision, yang memungkinkan menjalankan model Core ML dalam konteks Vision. Ia menangani semua prapemrosesan gambar yang diperlukan untuk model Core ML: mengubah ukuran, memotong, normalisasi, dan konversi ruang warna.
Tanpa VNCoreMLRequest pengembang harus secara manual mengonversi UIImage/CGImage ke MultiArray (MLMultiArray) atau PixelBuffer (CVPixelBuffer) dengan ukuran yang tepat. VNCoreMLRequest mengotomatiskan proses ini: Anda mengirim CGImage melalui VNImageRequestHandler, dan VNCoreMLRequest sendiri yang menskalakannya ke input model.
VNCoreMLRequest mewarisi semua kemampuan VNRequest: completion handler, regionOfInterest, kemampuan menjalankan beberapa permintaan secara bersamaan, dukungan untuk VNImageRequestHandler dan VNSequenceRequestHandler.
import Vision
import CoreML
// 1. Memuat dan membungkus model
guard let model = try VNCoreMLModel(
for: MobileNetV2().model)
else { return }
// 2. Membuat VNCoreMLRequest
let request = VNCoreMLRequest(model: model) { req, _ in
guard let results = req.results
as? [VNClassificationObservation]
else { return }
for r in results.prefix(3) {
print("\\(r.identifier): \\(r.confidence)")
}
}
// 3. Mengeksekusi melalui handler
let handler = VNImageRequestHandler(cgImage: image, options: [:])
try handler.perform([request])
VNCoreMLRequest mendukung model dengan berbagai tipe input: gambar (Image Feature), MultiArray, dan Double. Untuk gambar, Vision secara otomatis mengonversi CGImage ke CVPixelBuffer dengan ukuran dan ruang warna yang tepat. Untuk tipe data input lainnya, Anda perlu menggunakan Core ML secara langsung tanpa Vision.
Menurut Apple WWDC 2023, VNCoreMLRequest digunakan di 40% dari semua aplikasi iOS yang menerapkan Core ML untuk bekerja dengan gambar. Ini adalah cara paling populer untuk mengintegrasikan model ML ke dalam aplikasi iOS.
VNCoreMLModel — adalah pembungkus yang mengadaptasi model Core ML (MLModel) untuk digunakan di Vision. Ia mengonversi data input dan output model ke format yang dipahami Vision: gambar → CVPixelBuffer, hasil → VNObservation.
Inisialisasi VNCoreMLModel memeriksa kompatibilitas model dengan Vision: model harus menerima gambar sebagai input (Image Feature) dan mengembalikan klasifikasi (MLMultiArray atau Dictionary). Jika model tidak kompatibel, penginisialisasi akan mengeluarkan error.
import Vision
import CoreML
// Opsi 1: Dari .mlmodel (dikompilasi saat build)
let model1 = try VNCoreMLModel(
for: MyVisionModel().model)
// Opsi 2: Dari .mlmodelc (dikompilasi di perangkat)
let compiledURL = Bundle.main.url(
forResource: "MyVisionModel",
withExtension: "mlmodelc")!
let model2 = try VNCoreMLModel(
for: MLModel(contentsOf: compiledURL))
VNCoreMLModel menyimpan cache model di memori setelah pemuatan pertama. Pemuatan ulang model yang sama mengembalikan instance yang di-cache, yang mempercepat permintaan berikutnya. Namun, jika model berukuran lebih dari 100 MB, iOS dapat mengeluarkannya dari memori saat sumber daya tidak mencukupi — dalam kasus ini VNCoreMLModel akan memuat ulang model secara otomatis.
Untuk model yang dilatih melalui Create ML, VNCoreMLModel bekerja tanpa konfigurasi tambahan. Create ML mengekspor model dengan metadata yang benar yang dikenali Vision secara otomatis — cukup kirim model ke VNCoreMLModel(model:).
imageCropAndScaleOption — properti kunci VNCoreMLRequest yang menentukan bagaimana Vision mengubah gambar asli ke ukuran input model Core ML. Pemilihan opsi yang tepat secara langsung mempengaruhi akurasi klasifikasi.
.centerCrop — memotong gambar dari tengah menjadi persegi, lalu menskalakannya ke ukuran input model. Cocok untuk model yang dilatih pada objek terpusat (sebagian besar pengklasifikasi ImageNet). .scaleFill — meregangkan gambar ke ukuran input tanpa mempertahankan proporsi. Cepat, tetapi mendistorsi geometri. .scaleFit — menskalakan dengan mempertahankan proporsi, menambahkan letterbox (garis hitam) di tepinya.
import Vision
let request = VNCoreMLRequest(model: model)
// .centerCrop — untuk objek terpusat (default)
request.imageCropAndScaleOption = .centerCrop
// .scaleFill — untuk tekstur seragam (tanpa distorsi)
request.imageCropAndScaleOption = .scaleFill
// .scaleFit — saat proporsi objek penting
request.imageCropAndScaleOption = .scaleFit
Rekomendasi: untuk sebagian besar model klasifikasi gunakan .centerCrop — ini memberikan rasio akurasi dan kinerja terbaik. Jika model dilatih pada gambar dengan proporsi yang dipertahankan (misalnya, deteksi anomali pada foto dokumen), pilih .scaleFit dengan letterbox.
Menurut Apple Developer Documentation 2024, pemilihan imageCropAndScaleOption yang salah dapat menurunkan akurasi model sebesar 15–25%. Misalnya, .scaleFill untuk wajah yang terletak di tepi bingkai dapat memotong sebagiannya saat .centerCrop atau mendistorsi proporsi saat .scaleFill.
Kekuatan utama VNCoreMLRequest — kemampuannya untuk dikombinasikan dengan VNRequest lain dalam satu panggilan perform(). Ini memungkinkan pembangunan pipeline: pertama menemukan wajah (VNDetectFaceRectanglesRequest), kemudian mengklasifikasikan setiap wajah melalui model Core ML kustom (VNCoreMLRequest).
VNCoreMLRequest juga mendukung regionOfInterest — jika Anda mengatur area ini, Vision akan memotong gambar hingga persegi panjang yang ditentukan sebelum meneruskannya ke model Core ML. Ini sangat penting untuk pipeline: setelah deteksi wajah, Anda mengirim bounding box-nya sebagai regionOfInterest untuk VNCoreMLRequest.
import Vision
// 1. Deteksi wajah
let faceRequest = VNDetectFaceRectanglesRequest()
// 2. Klasifikasi emosi melalui Core ML
guard let emotionModel = try VNCoreMLModel(
for: EmotionClassifier().model)
else { return }
let emotionRequest = VNCoreMLRequest(model: emotionModel)
try handler.perform([faceRequest, emotionRequest])
// 3. Mengatur regionOfInterest untuk setiap wajah
for face in faceRequest.results as? [VNFaceObservation] ?? [] {
emotionRequest.regionOfInterest = face.boundingBox
try handler.perform([emotionRequest])
// Memproses hasil klasifikasi emosi
}
Keterbatasan: regionOfInterest untuk VNCoreMLRequest berguna ketika model dilatih pada gambar dengan satu ukuran dan proporsi. Jika model mengharapkan input persegi ketat (224x224), .centerCrop dengan regionOfInterest akan memberikan hasil terbaik.
Menurut Apple ML Research, pipeline 'deteksi → klasifikasi' melalui regionOfInterest memberikan peningkatan akurasi sebesar 20–30% dibandingkan dengan klasifikasi seluruh gambar, karena model ML hanya menerima area yang relevan tanpa noise latar belakang.
| Jenis Pipeline | Permintaan 1 (deteksi) | Permintaan 2 (ML) | Contoh |
|---|---|---|---|
| Wajah → emosi | VNDetectFaceRectanglesRequest | VNCoreMLRequest | Menentukan suasana hati |
| Objek → merek | VNDetectObjectAtPointRequest | VNCoreMLRequest | Pengenalan logo |
| Teks → bahasa | VNRecognizeTextRequest | VNCoreMLRequest | Klasifikasi bahasa teks |
| Adegan → deskripsi | VNClassifyImageRequest | VNCoreMLRequest | Pembuatan tag |
VNCoreMLRequest mengembalikan hasil dalam bentuk VNClassificationObservation (untuk model klasifikasi) atau VNCoreMLFeatureValueObservation (untuk regresi dan tipe lainnya). Tipe hasil tergantung pada data output model Core ML.
VNClassificationObservation berisi identifier (nama kelas) dan confidence (keyakinan). Model dengan output softmax mengembalikan array observasi semacam itu, diurutkan berdasarkan confidence menurun. VNCoreMLFeatureValueObservation berisi nilai MLFeatureValue arbitrer — bisa berupa MultiArray, Double, String, atau Dictionary.
// Untuk model klasifikasi
if let classificationResults = request.results
as? [VNClassificationObservation] {
for result in classificationResults
where result.confidence > 0.5 {
print("\\(result.identifier): \\(result.confidence)")
}
}
// Untuk model regresi (nilai fitur)
if let featureResults = request.results
as? [VNCoreMLFeatureValueObservation] {
for result in featureResults {
let value = result.featureValue
print("\\(result.featureName): \\(value)")
}
}
Pemfilteran berdasarkan confidence: Apple merekomendasikan untuk membuang hasil dengan confidence < 0.3 untuk pengklasifikasi umum dan < 0.7 untuk aplikasi kritis. Untuk model yang dilatih pada dataset seimbang, confidence berkorelasi dengan probabilitas jawaban yang benar, tetapi tidak menjaminnya.
VNCoreMLFeatureValueObservation.featureName sesuai dengan nama layer output model (misalnya, 'classLabel' atau 'features'). Ini memungkinkan pemrosesan model dengan beberapa output — setiap output diwakili oleh observation terpisah dengan featureName yang unik.
VNCoreMLRequest dioptimalkan untuk bekerja pada Neural Engine (A12+), GPU, dan CPU. Vision secara otomatis memilih perangkat terbaik untuk menjalankan model tergantung pada tipe dan ukurannya. Namun, kinerja dapat ditingkatkan lebih lanjut dengan konfigurasi yang tepat.
Model Core ML dimuat ke memori pada VNCoreMLRequest pertama dan tetap di sana hingga aplikasi ditutup. Untuk model berukuran lebih dari 200 MB, Apple merekomendasikan untuk memuatnya sesuai permintaan dan membongkarnya melalui MLModel.release(). VNCoreMLModel mengelola caching sendiri, tetapi Anda dapat mengontrolnya melalui autoreleasepool.
Untuk pemrosesan batch gambar, buat satu VNCoreMLRequest dan gunakan kembali dengan VNImageRequestHandler yang berbeda. Jangan membuat VNCoreMLRequest baru untuk setiap gambar — ini akan memperlambat pemrosesan karena pemuatan ulang model. Penggunaan kembali permintaan memberikan peningkatan kinerja hingga 40% saat memproses 10+ gambar.
// Benar: satu permintaan untuk semua gambar
let batchSize = 20
let batchRequest = VNCoreMLRequest(model: model)
for i in 0..<batchSize {
let handler = VNImageRequestHandler(
cgImage: images[i],
options: [:])
try handler.perform([batchRequest])
// batchRequest.results diperbarui pada setiap panggilan
}
Pemilihan perangkat: secara default Vision memilih Neural Engine untuk model yang kompatibel pada perangkat A12+. Jika model tidak mendukung Neural Engine, Vision menggunakan GPU atau CPU. Anda dapat memaksa menentukan perangkat melalui MLModelConfiguration.computeUnits, tetapi Apple merekomendasikan untuk membiarkan pemilihan otomatis.
Menurut Apple Performance Benchmarks 2024, VNCoreMLRequest pada Neural Engine (iPhone 15 Pro) memproses klasifikasi MobileNetV2 dalam 3–5 ms, pada GPU — 8–12 ms, pada CPU — 20–30 ms. Perbedaan menjadi kritis untuk aplikasi real-time yang memproses 30+ frame per detik.
Pertanyaan yang Sering Diajukan
Ya, Core ML dapat digunakan langsung melalui MLModel.prediction(), tanpa Vision. Namun, VNCoreMLRequest mengotomatiskan prapemrosesan gambar (penskalaan, pemotongan, konversi ke CVPixelBuffer). Jika model menerima bukan gambar, tetapi MultiArray atau Double — gunakan Core ML secara langsung. VNCoreMLRequest hanya untuk model dengan Image Feature pada input.
Buat VNCoreMLModel baru dari MLModel yang diperbarui dan VNCoreMLRequest baru. Permintaan lama akan terus menggunakan versi model lama. Untuk pembaruan model jarak jauh, gunakan MLModel.compileModel(at:) untuk mengkompilasi model di perangkat dari file .mlmodelc yang diunduh dari server.
VNCoreMLRequest hanya mendukung model dengan satu input Image Feature. Jika model memiliki beberapa input (misalnya, gambar + teks), gunakan Core ML langsung melalui MLModel. Vision tidak dapat mengirimkan parameter tambahan selain gambar.
Batasnya — 8192 x 8192 piksel untuk CGImage yang dikirim ke VNImageRequestHandler. Namun, model Core ML biasanya mengharapkan input 224x224, 299x299, atau 512x512. Vision secara otomatis menskalakan gambar besar ke ukuran input. Jika gambar asli terlalu besar, perkecil terlebih dahulu melalui CGImage untuk menghemat memori.
Ya, atur preferBackgroundProcessing = true pada VNRequest. Ini akan memungkinkan Vision untuk menunda eksekusi permintaan jika sistem berada dalam mode intensif sumber daya (misalnya, memuat konten). Juga wajib menggunakan DispatchQueue.global(qos: .background) untuk memanggil handler.perform().
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga