Bạn có thể dùng Bộ công cụ học máy để phát hiện và theo dõi các đối tượng trên nhiều khung hình của video.
Khi bạn truyền hình ảnh của Bộ công cụ học máy, Bộ công cụ học máy sẽ trả về một danh sách tối đa 5 đối tượng được phát hiện và vị trí của các đối tượng đó trong hình ảnh cho mỗi hình ảnh. Khi phát hiện các đối tượng trong luồng video, mỗi đối tượng đều có một mã nhận dạng mà bạn có thể dùng để theo dõi đối tượng trên các hình ảnh. Bạn cũng có thể tuỳ ý bật tính năng phân loại đối tượng tương đối. Tính năng này gắn nhãn các đối tượng bằng nội dung mô tả danh mục rộng.
Trước khi bắt đầu
- Nếu bạn chưa thêm Firebase vào ứng dụng của mình, hãy thực hiện bằng cách làm theo các bước trong hướng dẫn bắt đầu sử dụng.
- Đưa các thư viện Bộ công cụ học máy vào Podfile của bạn:
pod 'Firebase/MLVision', '6.25.0' pod 'Firebase/MLVisionObjectDetection', '6.25.0'
Sau khi bạn cài đặt hoặc cập nhật Nhóm của dự án, hãy nhớ mở dự án Xcode bằng cách sử dụng.xcworkspace
của dự án đó. - Trong ứng dụng của bạn, hãy nhập Firebase:
Swift
import Firebase
Objective-C
@import Firebase;
1. Định cấu hình trình phát hiện đối tượng
Để bắt đầu phát hiện và theo dõi đối tượng, trước tiên, hãy tạo một thực thể của VisionObjectDetector
, tuỳ ý chỉ định bất kỳ chế độ cài đặt trình phát hiện nào bạn muốn thay đổi so với giá trị mặc định.
Định cấu hình trình phát hiện đối tượng cho trường hợp sử dụng của bạn bằng đối tượng
VisionObjectDetectorOptions
. Bạn có thể thay đổi các chế độ cài đặt sau:Cài đặt trình phát hiện đối tượng Chế độ phát hiện .stream
(mặc định) |.singleImage
Ở chế độ phát trực tuyến (mặc định), trình phát hiện đối tượng chạy với độ trễ rất thấp nhưng có thể dẫn đến kết quả không đầy đủ (chẳng hạn như các hộp hoặc danh mục giới hạn không xác định) trong một số lệnh gọi đầu tiên của trình phát hiện. Ngoài ra, ở chế độ phát trực tuyến, trình phát hiện sẽ gán mã theo dõi cho các đối tượng và bạn có thể dùng mã này để theo dõi các đối tượng trên nhiều khung hình. Hãy sử dụng chế độ này khi bạn muốn theo dõi các đối tượng hoặc khi độ trễ thấp rất quan trọng, chẳng hạn như khi xử lý luồng video theo thời gian thực.
Ở chế độ hình ảnh đơn, trình phát hiện đối tượng sẽ đợi cho đến khi hộp giới hạn của đối tượng được phát hiện và danh mục (nếu bạn đã bật tính năng phân loại) xuất hiện trước khi trả về kết quả. Do đó, độ trễ phát hiện có thể cao hơn. Ngoài ra, ở chế độ một hình ảnh, mã theo dõi không được chỉ định. Hãy sử dụng chế độ này nếu độ trễ không quan trọng và bạn không muốn xử lý kết quả một phần.
Phát hiện và theo dõi nhiều đối tượng false
(mặc định) |true
Xác định xem có phát hiện và theo dõi tối đa 5 đối tượng hay chỉ phát hiện đối tượng nổi bật nhất (mặc định).
Phân loại đối tượng false
(mặc định) |true
Liệu có phân loại các đối tượng được phát hiện thành các danh mục tương đối hay không. Khi được bật, trình phát hiện vật thể sẽ phân loại các đối tượng thành các danh mục sau: hàng thời trang, thực phẩm, hàng gia dụng, địa điểm, thực vật và không xác định.
API theo dõi và phát hiện đối tượng được tối ưu hoá cho hai trường hợp sử dụng chính sau:
- Phát hiện trực tiếp và theo dõi đối tượng nổi bật nhất trong kính ngắm của máy ảnh
- Phát hiện nhiều đối tượng trong ảnh tĩnh
Cách định cấu hình API cho các trường hợp sử dụng này:
Swift
// Live detection and tracking let options = VisionObjectDetectorOptions() options.detectorMode = .stream options.shouldEnableMultipleObjects = false options.shouldEnableClassification = true // Optional // Multiple object detection in static images let options = VisionObjectDetectorOptions() options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true // Optional
Objective-C
// Live detection and tracking FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init]; options.detectorMode = FIRVisionObjectDetectorModeStream; options.shouldEnableMultipleObjects = NO; options.shouldEnableClassification = YES; // Optional // Multiple object detection in static images FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init]; options.detectorMode = FIRVisionObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES; // Optional
Nhận một thực thể của
FirebaseVisionObjectDetector
:Swift
let objectDetector = Vision.vision().objectDetector() // Or, to change the default settings: let objectDetector = Vision.vision().objectDetector(options: options)
Objective-C
FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetector]; // Or, to change the default settings: FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetectorWithOptions:options];
2. Chạy trình phát hiện đối tượng
Để phát hiện và theo dõi các đối tượng, hãy làm như sau cho từng hình ảnh hoặc khung video.
Nếu đã bật chế độ phát trực tiếp, bạn phải tạo các đối tượng VisionImage
từ các CMSampleBufferRef
.
Tạo đối tượng
VisionImage
bằngUIImage
hoặcCMSampleBufferRef
.Cách sử dụng
UIImage
:- Nếu cần, hãy xoay hình ảnh để thuộc tính
imageOrientation
của hình ảnh là.up
. - Tạo đối tượng
VisionImage
bằngUIImage
xoay chính xác. Không chỉ định bất kỳ siêu dữ liệu nào về chế độ xoay – bạn phải sử dụng giá trị mặc định,.topLeft
.Swift
let image = VisionImage(image: uiImage)
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Cách sử dụng
CMSampleBufferRef
:-
Tạo một đối tượng
VisionImageMetadata
chỉ định hướng của dữ liệu hình ảnh có trong vùng đệmCMSampleBufferRef
.Cách lấy hướng ảnh:
Swift
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> VisionDetectorImageOrientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftTop : .rightTop case .landscapeLeft: return cameraPosition == .front ? .bottomLeft : .topLeft case .portraitUpsideDown: return cameraPosition == .front ? .rightBottom : .leftBottom case .landscapeRight: return cameraPosition == .front ? .topRight : .bottomRight case .faceDown, .faceUp, .unknown: return .leftTop } }
Objective-C
- (FIRVisionDetectorImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationLeftTop; } else { return FIRVisionDetectorImageOrientationRightTop; } case UIDeviceOrientationLandscapeLeft: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationBottomLeft; } else { return FIRVisionDetectorImageOrientationTopLeft; } case UIDeviceOrientationPortraitUpsideDown: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationRightBottom; } else { return FIRVisionDetectorImageOrientationLeftBottom; } case UIDeviceOrientationLandscapeRight: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationTopRight; } else { return FIRVisionDetectorImageOrientationBottomRight; } default: return FIRVisionDetectorImageOrientationTopLeft; } }
Sau đó, hãy tạo đối tượng siêu dữ liệu:
Swift
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Objective-C
FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init]; AVCaptureDevicePosition cameraPosition = AVCaptureDevicePositionBack; // Set to the capture device you used. metadata.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
- Tạo đối tượng
VisionImage
bằng cách sử dụng đối tượngCMSampleBufferRef
và siêu dữ liệu xoay:Swift
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Nếu cần, hãy xoay hình ảnh để thuộc tính
Truyền
VisionImage
đến một trong các phương thức xử lý hình ảnh của trình phát hiện đối tượng. Bạn có thể sử dụng phương thứcprocess(image:)
không đồng bộ hoặc phương thứcresults()
đồng bộ.Cách phát hiện đối tượng không đồng bộ:
Swift
objectDetector.process(image) { detectedObjects, error in guard error == nil else { // Error. return } guard let detectedObjects = detectedObjects, !detectedObjects.isEmpty else { // No objects detected. return } // Success. Get object info here. // ... }
Objective-C
[objectDetector processImage:image completion:^(NSArray<FIRVisionObject *> * _Nullable objects, NSError * _Nullable error) { if (error == nil) { return; } if (objects == nil | objects.count == 0) { // No objects detected. return; } // Success. Get object info here. // ... }];
Cách phát hiện đối tượng một cách đồng bộ:
Swift
var results: [VisionObject]? = nil do { results = try objectDetector.results(in: image) } catch let error { print("Failed to detect object with error: \(error.localizedDescription).") return } guard let detectedObjects = results, !detectedObjects.isEmpty else { print("Object detector returned no results.") return } // ...
Objective-C
NSError *error; NSArray<FIRVisionObject *> *objects = [objectDetector resultsInImage:image error:&error]; if (error == nil) { return; } if (objects == nil | objects.count == 0) { // No objects detected. return; } // Success. Get object info here. // ...
Nếu lệnh gọi đến trình xử lý hình ảnh thành công, lệnh gọi sẽ chuyển danh sách
VisionObject
đến trình xử lý hoàn thành hoặc trả về danh sách, tuỳ thuộc vào việc bạn đã gọi phương thức không đồng bộ hay đồng bộ.Mỗi
VisionObject
chứa các thuộc tính sau:frame
CGRect
cho biết vị trí của đối tượng trong hình ảnh.trackingID
Số nguyên xác định đối tượng trên các hình ảnh. Nil ở chế độ một hình ảnh. classificationCategory
Danh mục tương đối của đối tượng. Nếu trình phát hiện đối tượng chưa bật tính năng phân loại, thì giá trị này luôn là .unknown
.confidence
Giá trị tin cậy của việc phân loại đối tượng. Nếu trình phát hiện đối tượng chưa bật tính năng phân loại hoặc đối tượng được phân loại là không xác định, thì đó là nil
.Swift
// detectedObjects contains one item if multiple object detection wasn't enabled. for obj in detectedObjects { let bounds = obj.frame let id = obj.trackingID // If classification was enabled: let category = obj.classificationCategory let confidence = obj.confidence }
Objective-C
// The list of detected objects contains one item if multiple // object detection wasn't enabled. for (FIRVisionObject *obj in objects) { CGRect bounds = obj.frame; if (obj.trackingID) { NSInteger id = obj.trackingID.integerValue; } // If classification was enabled: FIRVisionObjectCategory category = obj.classificationCategory; float confidence = obj.confidence.floatValue; }
Cải thiện khả năng hữu dụng và hiệu suất
Để có trải nghiệm người dùng tốt nhất, hãy làm theo các nguyên tắc sau trong ứng dụng của bạn:
- Việc phát hiện được đối tượng có thành công hay không còn phụ thuộc vào độ phức tạp trực quan của đối tượng. Các đối tượng có ít đặc điểm trực quan có thể cần chiếm phần lớn hơn của hình ảnh mới được phát hiện. Bạn nên cung cấp cho người dùng hướng dẫn về cách ghi lại dữ liệu đầu vào hoạt động hiệu quả với loại đối tượng bạn muốn phát hiện.
- Khi sử dụng tính năng phân loại, nếu bạn muốn phát hiện các đối tượng không thuộc danh mục được hỗ trợ một cách rõ ràng, hãy triển khai cách xử lý đặc biệt cho các đối tượng không xác định.
Ngoài ra, hãy xem bộ sưu tập [ứng dụng giới thiệu Material Design trong Bộ công cụ học máy][showcase-link]{: .external } và bộ sưu tập Mẫu thiết kế cho các tính năng dựa trên công nghệ học máy.
Khi dùng chế độ phát trực tuyến trong một ứng dụng theo thời gian thực, hãy làm theo các nguyên tắc sau để đạt được tốc độ khung hình tốt nhất:
Đừng dùng tính năng phát hiện nhiều đối tượng ở chế độ phát trực tuyến, vì hầu hết các thiết bị sẽ không thể tạo ra đủ tốc độ khung hình.
Hãy tắt tính năng phân loại nếu bạn không cần.
- Điều tiết lệnh gọi đến trình phát hiện. Nếu có một khung hình video mới trong khi trình phát hiện đang chạy, hãy bỏ khung hình đó.
- Nếu bạn đang dùng đầu ra của trình phát hiện để phủ đồ hoạ lên hình ảnh đầu vào, trước tiên hãy lấy kết quả từ Bộ công cụ học máy, sau đó kết xuất hình ảnh và lớp phủ trong một bước duy nhất. Nhờ vậy, bạn chỉ kết xuất lên giao diện hiển thị một lần cho mỗi khung nhập. Hãy xem các lớp previewOverlayView và FIRDetectionOverlayView trong ứng dụng mẫu giới thiệu để làm ví dụ.