VNCoreMLRequest — là một lớp con của VNRequest cho phép chạy các mô hình Core ML bên trong đường ống Vision, kết hợp lợi ích của các bộ dò Vision có sẵn (khuôn mặt, văn bản, đối tượng) với các mô hình ML tùy chỉnh cho phân loại và hồi quy. Theo Apple Machine Learning Documentation (2024), VNCoreMLRequest tự động xử lý tiền xử lý hình ảnh — chia tỷ lệ, cắt và chuyển đổi không gian màu — theo yêu cầu của mô hình Core ML.
Điểm chính
VNCoreMLRequest là một lớp con của VNRequest, được thêm vào iOS 11 cùng với Vision, cho phép chạy các mô hình Core ML trong ngữ cảnh Vision. Nó xử lý tất cả tiền xử lý hình ảnh cần thiết cho mô hình Core ML: thay đổi kích thước, cắt, chuẩn hóa và chuyển đổi không gian màu.
Nếu không có VNCoreMLRequest, nhà phát triển sẽ phải thủ công chuyển đổi UIImage/CGImage thành MultiArray (MLMultiArray) hoặc PixelBuffer (CVPixelBuffer) với kích thước cần thiết. VNCoreMLRequest tự động hóa quá trình này: bạn truyền CGImage qua VNImageRequestHandler, và VNCoreMLRequest sẽ tự điều chỉnh tỷ lệ cho đầu vào mô hình.
VNCoreMLRequest kế thừa tất cả khả năng của VNRequest: bộ xử lý hoàn thành, regionOfInterest, khả năng thực hiện nhiều yêu cầu cùng lúc, hỗ trợ VNImageRequestHandler và VNSequenceRequestHandler.
import Vision
import CoreML
// 1. Tải và bọc mô hình
guard let model = try VNCoreMLModel(
for: MobileNetV2().model)
else { return }
// 2. Tạo 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. Thực thi qua bộ xử lý
let handler = VNImageRequestHandler(cgImage: image, options: [:])
try handler.perform([request])
VNCoreMLRequest hỗ trợ các mô hình với các loại đầu vào khác nhau: hình ảnh (Image Feature), MultiArray và Double. Đối với hình ảnh, Vision tự động chuyển đổi CGImage thành CVPixelBuffer với kích thước và không gian màu cần thiết. Đối với các loại dữ liệu đầu vào khác, hãy sử dụng Core ML trực tiếp mà không qua Vision.
Theo Apple WWDC 2023, VNCoreMLRequest được sử dụng trong 40% tất cả các ứng dụng iOS sử dụng Core ML để xử lý hình ảnh. Đây là cách phổ biến nhất để tích hợp các mô hình ML vào ứng dụng iOS.
VNCoreMLModel là một lớp bọc giúp thích ứng mô hình Core ML (MLModel) để sử dụng trong Vision. Nó chuyển đổi dữ liệu đầu vào và đầu ra của mô hình thành định dạng mà Vision có thể hiểu được: hình ảnh → CVPixelBuffer, kết quả → VNObservation.
Khởi tạo VNCoreMLModel kiểm tra tính tương thích của mô hình với Vision: mô hình phải chấp nhận hình ảnh làm đầu vào (Image Feature) và trả về phân loại (MLMultiArray hoặc Dictionary). Nếu mô hình không tương thích, trình khởi tạo sẽ báo lỗi.
import Vision
import CoreML
// Tùy chọn 1: Từ .mlmodel (biên dịch tại thời điểm xây dựng)
let model1 = try VNCoreMLModel(
for: MyVisionModel().model)
// Tùy chọn 2: Từ .mlmodelc (biên dịch trên thiết bị)
let compiledURL = Bundle.main.url(
forResource: "MyVisionModel",
withExtension: "mlmodelc")!
let model2 = try VNCoreMLModel(
for: MLModel(contentsOf: compiledURL))
VNCoreMLModel lưu vùng đệm mô hình trong bộ nhớ sau lần tải đầu tiên. Tải lại cùng một mô hình sẽ trả về phiên bản đã lưu vùng đệm, giúp tăng tốc các yêu cầu tiếp theo. Tuy nhiên, nếu mô hình nặng hơn 100 MB, iOS có thể giải phóng nó khỏi bộ nhớ khi tài nguyên khan hiếm — trong trường hợp này, VNCoreMLModel sẽ tự động tải lại mô hình.
Đối với các mô hình được huấn luyện qua Create ML, VNCoreMLModel hoạt động mà không cần cấu hình thêm. Create ML xuất các mô hình với siêu dữ liệu chính xác mà Vision tự động nhận dạng — chỉ cần truyền mô hình vào VNCoreMLModel(model:).
imageCropAndScaleOption là thuộc tính chính của VNCoreMLRequest quyết định cách Vision biến đổi hình ảnh gốc để phù hợp với kích thước đầu vào của mô hình Core ML. Việc chọn đúng tùy chọn ảnh hưởng trực tiếp đến độ chính xác phân loại.
.centerCrop cắt hình ảnh từ trung tâm thành hình vuông, sau đó chia tỷ lệ về kích thước đầu vào mô hình. Phù hợp cho các mô hình được huấn luyện trên các đối tượng ở trung tâm (hầu hết các bộ phân loại ImageNet). .scaleFill kéo giãn hình ảnh đến kích thước đầu vào mà không giữ tỷ lệ. Nhanh, nhưng làm biến dạng hình học. .scaleFit chia tỷ lệ trong khi giữ tỷ lệ, thêm letterbox (thanh đen) ở các cạnh.
import Vision
let request = VNCoreMLRequest(model: model)
// .centerCrop — cho đối tượng trung tâm (mặc định)
request.imageCropAndScaleOption = .centerCrop
// .scaleFill — cho kết cấu đồng nhất (không biến dạng)
request.imageCropAndScaleOption = .scaleFill
// .scaleFit — khi tỷ lệ đối tượng quan trọng
request.imageCropAndScaleOption = .scaleFit
Khuyến nghị: đối với hầu hết các mô hình phân loại, hãy sử dụng .centerCrop — nó cân bằng tốt nhất giữa độ chính xác và hiệu suất. Nếu mô hình được huấn luyện trên hình ảnh có tỷ lệ được giữ nguyên (ví dụ: phát hiện bất thường trên ảnh tài liệu), hãy chọn .scaleFit với letterbox.
Theo Apple Developer Documentation 2024, việc chọn sai imageCropAndScaleOption có thể làm giảm độ chính xác của mô hình từ 15–25%. Ví dụ: .scaleFill cho một khuôn mặt ở cạnh khung hình có thể cắt mất một phần với .centerCrop hoặc làm biến dạng tỷ lệ với .scaleFill.
Điểm mạnh chính của VNCoreMLRequest là khả năng kết hợp nó với các VNRequest khác trong một lần gọi perform(). Điều này cho phép xây dựng các đường ống: đầu tiên phát hiện khuôn mặt (VNDetectFaceRectanglesRequest), sau đó phân loại từng khuôn mặt qua mô hình Core ML tùy chỉnh (VNCoreMLRequest).
VNCoreMLRequest cũng hỗ trợ regionOfInterest — nếu bạn đặt khu vực này, Vision sẽ cắt hình ảnh theo hình chữ nhật được chỉ định trước khi truyền vào mô hình Core ML. Điều này rất quan trọng cho các đường ống: sau khi phát hiện khuôn mặt, bạn truyền hộp giới hạn của nó làm regionOfInterest cho VNCoreMLRequest.
import Vision
// 1. Phát hiện khuôn mặt
let faceRequest = VNDetectFaceRectanglesRequest()
// 2. Phân loại cảm xúc qua Core ML
guard let emotionModel = try VNCoreMLModel(
for: EmotionClassifier().model)
else { return }
let emotionRequest = VNCoreMLRequest(model: emotionModel)
try handler.perform([faceRequest, emotionRequest])
// 3. Đặt regionOfInterest cho mỗi khuôn mặt
for face in faceRequest.results as? [VNFaceObservation] ?? [] {
emotionRequest.regionOfInterest = face.boundingBox
try handler.perform([emotionRequest])
// Xử lý kết quả phân loại cảm xúc
}
Giới hạn: regionOfInterest cho VNCoreMLRequest chỉ có ý nghĩa khi mô hình được huấn luyện trên các hình ảnh có cùng kích thước và tỷ lệ. Nếu mô hình mong đợi đầu vào hình vuông nghiêm ngặt (224x224), .centerCrop với regionOfInterest sẽ cho kết quả tốt nhất.
Theo Apple ML Research, đường ống “phát hiện → phân loại” qua regionOfInterest mang lại cải thiện độ chính xác 20–30% so với phân loại toàn bộ hình ảnh, vì mô hình ML chỉ nhận được khu vực liên quan mà không có nhiễu nền.
| Loại đường ống | Yêu cầu 1 (phát hiện) | Yêu cầu 2 (ML) | Ví dụ |
|---|---|---|---|
| Khuôn mặt → cảm xúc | VNDetectFaceRectanglesRequest | VNCoreMLRequest | Phát hiện tâm trạng |
| Đối tượng → thương hiệu | VNDetectObjectAtPointRequest | VNCoreMLRequest | Nhận dạng logo |
| Văn bản → ngôn ngữ | VNRecognizeTextRequest | VNCoreMLRequest | Phân loại ngôn ngữ văn bản |
| Cảnh → mô tả | VNClassifyImageRequest | VNCoreMLRequest | Tạo thẻ |
VNCoreMLRequest trả về kết quả dưới dạng VNClassificationObservation (cho mô hình phân loại) hoặc VNCoreMLFeatureValueObservation (cho hồi quy và các loại khác). Loại kết quả phụ thuộc vào dữ liệu đầu ra của mô hình Core ML.
VNClassificationObservation chứa identifier (tên lớp) và confidence. Các mô hình có đầu ra softmax trả về mảng các quan sát này được sắp xếp theo confidence giảm dần. VNCoreMLFeatureValueObservation chứa một MLFeatureValue tùy ý — có thể là MultiArray, Double, String hoặc Dictionary.
// Cho mô hình phân loại
if let classificationResults = request.results
as? [VNClassificationObservation] {
for result in classificationResults
where result.confidence > 0.5 {
print("\\(result.identifier): \\(result.confidence)")
}
}
// Cho mô hình hồi quy (giá trị đặc trưng)
if let featureResults = request.results
as? [VNCoreMLFeatureValueObservation] {
for result in featureResults {
let value = result.featureValue
print("\\(result.featureName): \\(value)")
}
}
Lọc theo confidence: Apple khuyến nghị loại bỏ các kết quả có confidence < 0.3 đối với các bộ phân loại tổng quát và < 0.7 đối với các ứng dụng quan trọng. Đối với các mô hình được huấn luyện trên tập dữ liệu cân bằng, confidence tương quan với xác suất câu trả lời đúng nhưng không đảm bảo điều đó.
VNCoreMLFeatureValueObservation.featureName tương ứng với tên lớp đầu ra của mô hình (ví dụ: “classLabel” hoặc “features”). Điều này cho phép xử lý các mô hình có nhiều đầu ra — mỗi đầu ra được đại diện bởi một quan sát riêng biệt với một featureName duy nhất.
VNCoreMLRequest được tối ưu hóa để chạy trên Neural Engine (A12+), GPU và CPU. Vision tự động chọn thiết bị tốt nhất để thực thi mô hình tùy theo loại và kích thước của nó. Tuy nhiên, hiệu suất có thể được cải thiện hơn nữa với cấu hình phù hợp.
Các mô hình Core ML được tải vào bộ nhớ khi VNCoreMLRequest đầu tiên và ở đó cho đến khi ứng dụng được giải phóng. Đối với các mô hình lớn hơn 200 MB, Apple khuyến nghị tải chúng theo nhu cầu và giải phóng qua MLModel.release(). VNCoreMLModel tự quản lý bộ nhớ đệm, nhưng bạn có thể kiểm soát nó qua autoreleasepool.
Để xử lý hàng loạt hình ảnh, hãy tạo một VNCoreMLRequest và tái sử dụng nó với các VNImageRequestHandler khác nhau. Đừng tạo một VNCoreMLRequest mới cho mỗi hình ảnh — điều này sẽ làm chậm quá trình xử lý do tải đi tải lại mô hình. Tái sử dụng yêu cầu mang lại hiệu suất tăng lên đến 40% khi xử lý 10+ hình ảnh.
// Đúng: một yêu cầu cho tất cả hình ảnh
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 cập nhật trên mỗi lần gọi
}
Chọn thiết bị: theo mặc định, Vision chọn Neural Engine cho các mô hình tương thích trên các thiết bị A12+. Nếu mô hình không hỗ trợ Neural Engine, Vision sử dụng GPU hoặc CPU. Bạn có thể buộc chọn thiết bị qua MLModelConfiguration.computeUnits, nhưng Apple khuyến nghị để chế độ tự động chọn.
Theo Apple Performance Benchmarks 2024, VNCoreMLRequest trên Neural Engine (iPhone 15 Pro) xử lý phân loại MobileNetV2 trong 3–5 ms, trên GPU — 8–12 ms, trên CPU — 20–30 ms. Sự khác biệt này trở nên quan trọng đối với các ứng dụng thời gian thực xử lý 30+ khung hình mỗi giây.
Câu hỏi thường gặp
Có, Core ML có thể được sử dụng trực tiếp qua MLModel.prediction() mà không cần Vision. Tuy nhiên, VNCoreMLRequest tự động hóa tiền xử lý hình ảnh (chia tỷ lệ, cắt, chuyển đổi sang CVPixelBuffer). Nếu mô hình chấp nhận không phải hình ảnh mà là MultiArray hoặc Double — hãy sử dụng Core ML trực tiếp. VNCoreMLRequest chỉ dành cho các mô hình có đầu vào Image Feature.
Tạo một VNCoreMLModel mới từ MLModel đã cập nhật và một VNCoreMLRequest mới. Yêu cầu cũ sẽ tiếp tục sử dụng phiên bản mô hình cũ. Đối với các bản cập nhật mô hình từ xa, hãy sử dụng MLModel.compileModel(at:) để biên dịch mô hình trên thiết bị từ tệp .mlmodelc được tải xuống từ máy chủ.
VNCoreMLRequest chỉ hỗ trợ các mô hình có một đầu vào Image Feature duy nhất. Nếu mô hình có nhiều đầu vào (ví dụ: hình ảnh + văn bản), hãy sử dụng Core ML trực tiếp qua MLModel. Vision không thể truyền các tham số bổ sung ngoài hình ảnh.
Giới hạn là 8192 x 8192 pixel cho CGImage được truyền vào VNImageRequestHandler. Tuy nhiên, các mô hình Core ML thường mong đợi đầu vào 224x224, 299x299 hoặc 512x512. Vision tự động chia tỷ lệ hình ảnh lớn về kích thước đầu vào. Nếu hình ảnh gốc quá lớn, hãy thu nhỏ nó trước qua CGImage để tiết kiệm bộ nhớ.
Có, hãy đặt preferBackgroundProcessing = true trên VNRequest. Điều này cho phép Vision trì hoãn thực thi yêu cầu nếu hệ thống đang ở chế độ tốn nhiều tài nguyên (ví dụ: đang tải nội dung). Đồng thời, hãy sử dụng DispatchQueue.global(qos: .background) để gọi handler.perform().
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm