VNCoreMLRequest — زیرکلاس VNRequest است که به شما اجازه میدهد مدلهای Core ML را در داخل pipeline Vision اجرا کنید، مزایای آشکارسازهای آماده Vision (چهره، متن، اشیاء) را با مدلهای سفارشی ML برای طبقهبندی و رگرسیون ترکیب میکند. به گزارش Apple Machine Learning Documentation (2024)، VNCoreMLRequest پیشپردازش تصویر را — تغییر اندازه، برش و تبدیل فضای رنگ — به طور خودکار مطابق نیازهای مدل Core ML انجام میدهد.
نکات کلیدی
VNCoreMLRequest — زیرکلاس VNRequest است که در iOS 11 همراه با Vision اضافه شده و به شما اجازه میدهد مدلهای Core ML را در زمینه Vision اجرا کنید. این کلاس کل پیشپردازش تصویر مورد نیاز مدل Core ML را بر عهده میگیرد: تغییر اندازه، برش، نرمالسازی و تبدیل فضای رنگ.
بدون VNCoreMLRequest، توسعهدهنده مجبور بود UIImage/CGImage را به صورت دستی به MultiArray (MLMultiArray) یا PixelBuffer (CVPixelBuffer) با اندازه مورد نیاز تبدیل کند. VNCoreMLRequest این فرآیند را خودکار میسازد: شما CGImage را از طریق VNImageRequestHandler ارسال میکنید و VNCoreMLRequest آن را به طور خودکار مطابق اندازه ورودی مدل مقیاس میکند.
VNCoreMLRequest تمامی قابلیتهای VNRequest را به ارث میبرد: completion handler، regionOfInterest، امکان اجرای چندین درخواست به صورت همزمان، پشتیبانی از VNImageRequestHandler و VNSequenceRequestHandler.
import Vision
import CoreML
// 1. بارگذاری و پیچیدن مدل
guard let model = try VNCoreMLModel(
for: MobileNetV2().model)
else { return }
// 2. ایجاد 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. اجرا از طریق handler
let handler = VNImageRequestHandler(cgImage: image, options: [:])
try handler.perform([request])
VNCoreMLRequest از مدلهایی با انواع مختلف ورودی پشتیبانی میکند: تصاویر (Image Feature)، MultiArray و Double. برای تصاویر، Vision به طور خودکار CGImage را به CVPixelBuffer با اندازه و فضای رنگی مورد نیاز تبدیل میکند. برای سایر انواع دادههای ورودی، باید بدون Vision از Core ML به صورت مستقیم استفاده کنید.
به گزارش Apple WWDC 2023، VNCoreMLRequest در 40% از کل برنامههای iOS که از Core ML برای کار با تصاویر استفاده میکنند، مورد استفاده قرار میگیرد. این محبوبترین راه ادغام مدلهای ML در برنامههای iOS است.
VNCoreMLModel — پیچیدهای است که مدل Core ML (MLModel) را برای استفاده در Vision سازگار میکند. دادههای ورودی و خروجی مدل را به فرمت قابل فهم برای Vision تبدیل میکند: تصویر → CVPixelBuffer، نتیجه → VNObservation.
مقداردهی VNCoreMLModel سازگاری مدل با Vision را بررسی میکند: مدل باید در ورودی تصویر (Image Feature) بپذیرد و یک طبقهبندی (MLMultiArray یا Dictionary) برگرداند. اگر مدل ناسازگار باشد، مقداردهی خطا صادر میکند.
import Vision
import CoreML
// گزینه 1: از .mlmodel (کامپایل شده در زمان ساخت)
let model1 = try VNCoreMLModel(
for: MyVisionModel().model)
// گزینه 2: از .mlmodelc (کامپایل شده روی دستگاه)
let compiledURL = Bundle.main.url(
forResource: "MyVisionModel",
withExtension: "mlmodelc")!
let model2 = try VNCoreMLModel(
for: MLModel(contentsOf: compiledURL))
VNCoreMLModel مدل را پس از اولین بارگذاری در حافظه کش میکند. بارگذاری مجدد همان مدل، نمونه کش شده را برمیگرداند که درخواستهای بعدی را سرعت میبخشد. اما اگر مدل بیش از 100 MB وزن داشته باشد، iOS ممکن است آن را در کمبود منابع از حافظه خارج کند — در این صورت VNCoreMLModel مدل را به طور خودکار دوباره بارگذاری میکند.
برای مدلهای آموزش داده شده توسط Create ML، VNCoreMLModel بدون پیکربندی اضافی کار میکند. Create ML مدلها را با ابردادههای صحیح صادر میکند که Vision به طور خودکار تشخیص میدهد — کافی است مدل را به VNCoreMLModel(model:) ارسال کنید.
imageCropAndScaleOption — ویژگی کلیدی VNCoreMLRequest است که تعیین میکند Vision如何 تصویر اصلی را به اندازه ورودی مدل Core ML تبدیل کند. انتخاب گزینه صحیح مستقیماً بر دقت طبقهبندی تأثیر میگذارد.
.centerCrop — تصویر را از مرکز به صورت مربع برش میدهد، سپس به اندازه ورودی مدل مقیاس میکند. مناسب برای مدلهای آموزش دیده بر روی اشیاء مرکزی (اکثر طبقهبندیکنندههای ImageNet). .scaleFill — تصویر را بدون حفظ نسبت به اندازه ورودی کش میدهد. سریع، اما هندسه را تحریف میکند. .scaleFit — با حفظ نسبت مقیاس میکند، letterbox (نوارهای سیاه) در لبهها اضافه میکند.
import Vision
let request = VNCoreMLRequest(model: model)
// .centerCrop — برای اشیاء مرکزی (پیشفرض)
request.imageCropAndScaleOption = .centerCrop
// .scaleFill — برای بافتهای یکنواخت (بدون تحریف)
request.imageCropAndScaleOption = .scaleFill
// .scaleFit — وقتی نسبتهای شیء مهم هستند
request.imageCropAndScaleOption = .scaleFit
توصیهها: برای اکثر مدلهای طبقهبندی از .centerCrop استفاده کنید — بهترین نسبت دقت به کارایی را فراهم میکند. اگر مدل بر روی تصاویر با حفظ نسبت آموزش دیده است (مثلاً تشخیص ناهنجاری در عکسهای اسناد)، .scaleFit با letterbox را انتخاب کنید.
به گزارش Apple Developer Documentation 2024، انتخاب نادرست imageCropAndScaleOption میتواند دقت مدل را 15–25% کاهش دهد. به عنوان مثال، .scaleFill برای چهرهای که در لبه کادر قرار دارد ممکن است بخشی از آن را در .centerCrop برش دهد یا نسبتها را در .scaleFill تحریف کند.
نیروی اصلی VNCoreMLRequest — امکان ترکیب آن با سایر VNRequest در یک فراخوانی perform() است. این امکان ساخت pipelineها را فراهم میکند: ابتدا چهرهها را پیدا کنید (VNDetectFaceRectanglesRequest)، سپس هر چهره را از طریق یک مدل سفارشی Core ML (VNCoreMLRequest) طبقهبندی کنید.
VNCoreMLRequest همچنین regionOfInterest را پشتیبانی میکند — اگر این ناحیه را تنظیم کنید، Vision تصویر را قبل از ارسال به مدل Core ML تا مستطیل مشخص شده برش میدهد. این برای pipelineها حیاتی است: پس از تشخیص چهره، bounding box آن را به عنوان regionOfInterest برای VNCoreMLRequest ارسال میکنید.
import Vision
// 1. تشخیص چهره
let faceRequest = VNDetectFaceRectanglesRequest()
// 2. طبقهبندی احساسات از طریق Core ML
guard let emotionModel = try VNCoreMLModel(
for: EmotionClassifier().model)
else { return }
let emotionRequest = VNCoreMLRequest(model: emotionModel)
try handler.perform([faceRequest, emotionRequest])
// 3. تنظیم regionOfInterest برای هر چهره
for face in faceRequest.results as? [VNFaceObservation] ?? [] {
emotionRequest.regionOfInterest = face.boundingBox
try handler.perform([emotionRequest])
// پردازش نتیجه طبقهبندی احساسات
}
محدودیت: regionOfInterest برای VNCoreMLRequest زمانی معنا دارد که مدل بر روی تصاویر با اندازه و نسبت یکسان آموزش دیده باشد. اگر مدل ورودی کاملاً مربعی (224x224) انتظار دارد، .centerCrop با regionOfInterest بهترین نتیجه را میدهد.
به گزارش Apple ML Research، pipeline «تشخیص → طبقهبندی» از طریق regionOfInterest دقت را 20–30% در مقایسه با طبقهبندی کل تصویر افزایش میدهد، زیرا مدل ML در ورودی فقط ناحیه مربوطه را بدون نویز پسزمینه دریافت میکند.
| نوع pipeline | درخواست 1 (تشخیص) | درخواست 2 (ML) | مثال |
|---|---|---|---|
| چهره → احساس | VNDetectFaceRectanglesRequest | VNCoreMLRequest | تشخیص خلق و خو |
| شیء → برند | VNDetectObjectAtPointRequest | VNCoreMLRequest | تشخیص لوگو |
| متن → زبان | VNRecognizeTextRequest | VNCoreMLRequest | طبقهبندی زبان متن |
| صحنه → توصیف | VNClassifyImageRequest | VNCoreMLRequest | تولید برچسب |
VNCoreMLRequest نتایج را به صورت VNClassificationObservation (برای مدلهای طبقهبندی) یا VNCoreMLFeatureValueObservation (برای رگرسیون و سایر انواع) برمیگرداند. نوع نتیجه به دادههای خروجی مدل Core ML بستگی دارد.
VNClassificationObservation شامل identifier (نام کلاس) و confidence (اطمینان) است. مدلهای با خروجی softmax آرایهای از این مشاهدات را مرتب شده به ترتیب نزولی confidence برمیگردانند. VNCoreMLFeatureValueObservation شامل یک مقدار دلخواه MLFeatureValue است — میتواند MultiArray، Double، String یا Dictionary باشد.
// برای مدلهای طبقهبندی
if let classificationResults = request.results
as? [VNClassificationObservation] {
for result in classificationResults
where result.confidence > 0.5 {
print("\\(result.identifier): \\(result.confidence)")
}
}
// برای مدلهای رگرسیون (مقادیر ویژگی)
if let featureResults = request.results
as? [VNCoreMLFeatureValueObservation] {
for result in featureResults {
let value = result.featureValue
print("\\(result.featureName): \\(value)")
}
}
فیلتر کردن بر اساس confidence: Apple توصیه میکند نتایج با confidence < 0.3 برای طبقهبندیکنندههای عمومی و < 0.7 برای برنامههای حیاتی دور انداخته شوند. برای مدلهای آموزش دیده بر روی مجموعه دادههای متوازن، confidence با احتمال پاسخ صحیح همبستگی دارد، اما آن را تضمین نمیکند.
VNCoreMLFeatureValueObservation.featureName با نام لایه خروجی مدل مطابقت دارد (مثلاً «classLabel» یا «features»). این امکان پردازش مدلهای با چندین خروجی را فراهم میکند — هر خروجی با یک مشاهده جداگانه با featureName منحصر به فرد نمایش داده میشود.
VNCoreMLRequest برای کار بر روی Neural Engine (A12+)، GPU و CPU بهینه شده است. Vision به طور خودکار بهترین دستگاه را برای اجرای مدل بسته به نوع و اندازه آن انتخاب میکند. با این حال، کارایی را میتوان با پیکربندی مناسب بیشتر بهبود بخشید.
مدلهای Core ML در اولین VNCoreMLRequest در حافظه بارگذاری میشوند و تا تخلیه برنامه در آنجا باقی میمانند. برای مدلهای بزرگتر از 200 MB، Apple توصیه میکند آنها را بر اساس تقاضا بارگذاری و از طریق MLModel.release() تخلیه کنید. VNCoreMLModel خودش کش را مدیریت میکند، اما شما میتوانید این را از طریق autoreleasepool کنترل کنید.
برای پردازش دستهای تصاویر، یک VNCoreMLRequest ایجاد کنید و آن را با VNImageRequestHandlerهای مختلف مجدداً استفاده کنید. برای هر تصویر VNCoreMLRequest جدید ایجاد نکنید — این به دلیل بارگذاری مجدد مدل پردازش را کند میکند. استفاده مجدد از درخواست تا 40% افزایش کارایی در پردازش 10+ تصویر میدهد.
// درست: یک درخواست برای همه تصاویر
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 در هر فراخوانی بهروزرسانی میشود
}
انتخاب دستگاه: به طور پیشفرض Vision برای مدلهای سازگار در دستگاههای A12+ Neural Engine را انتخاب میکند. اگر مدل از Neural Engine پشتیبانی نمیکند، Vision از GPU یا CPU استفاده میکند. شما میتوانید از طریق MLModelConfiguration.computeUnits دستگاه را اجباری تعیین کنید، اما Apple توصیه میکند انتخاب خودکار را保留 کنید.
به گزارش Apple Performance Benchmarks 2024، VNCoreMLRequest در Neural Engine (iPhone 15 Pro) طبقهبندی MobileNetV2 را در 3–5 ms، در GPU — 8–12 ms، در CPU — 20–30 ms پردازش میکند. تفاوت برای برنامههای real-time که 30+ فریم در ثانیه پردازش میکنند حیاتی میشود.
سؤالات متداول
بله، Core ML را میتوان مستقیماً از طریق MLModel.prediction()، بدون Vision استفاده کرد. با این حال، VNCoreMLRequest پیشپردازش تصاویر (تغییر اندازه، برش، تبدیل به CVPixelBuffer) را خودکار میکند. اگر مدل تصویر نمیپذیرد، بلکه MultiArray یا Double میپذیرد — از Core ML مستقیم استفاده کنید. VNCoreMLRequest فقط برای مدلهای با Image Feature در ورودی است.
یک VNCoreMLModel جدید از MLModel بهروزرسانی شده و یک VNCoreMLRequest جدید ایجاد کنید. درخواست قدیمی به استفاده از نسخه قدیمی مدل ادامه میدهد. برای بهروزرسانی از راه دور مدلها از MLModel.compileModel(at:) برای کامپایل مدل روی دستگاه از فایل .mlmodelc دانلود شده از سرور استفاده کنید.
VNCoreMLRequest فقط از مدلهای با یک ورودی Image Feature پشتیبانی میکند. اگر مدل چندین ورودی دارد (مثلاً تصویر + متن)، از Core ML مستقیم از طریق MLModel استفاده کنید. Vision نمیتواند پارامترهای اضافی فراتر از تصویر ارسال کند.
محدودیت — 8192 x 8192 پیکسل برای CGImage ارسال شده به VNImageRequestHandler. اما مدلهای Core ML معمولاً ورودی 224x224، 299x299 یا 512x512 انتظار دارند. Vision به طور خودکار تصویر بزرگ را به اندازه ورودی مقیاس میکند. اگر تصویر اصلی بیش از حد بزرگ است، برای صرفهجویی در حافظه آن را از طریق CGImage پیشاپیش کوچک کنید.
بله، preferBackgroundProcessing = true را روی VNRequest تنظیم کنید. این به Vision اجازه میدهد اجرای درخواست را به تأخیر بیندازد اگر سیستم در حالت مصرفکننده منابع است (مثلاً بارگذاری محتوا). همچنین حتماً از DispatchQueue.global(qos: .background) برای فراخوانی handler.perform() استفاده کنید.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید