错误"Exceeded maximum allowed number of Trackers"是什么意思?



我将按照本教程在iOS11上实现对象跟踪。我能够完美地跟踪对象,直到某个点,然后这个错误出现在控制台中。

Throws:Error Domain=com.apple.vis Code=9"内部错误:超出跟踪器类型的最大允许跟踪器数量:VNObjectTrackerType"UserInfo={NSLocalizedDescription=内部错误:超过跟踪器类型的允许跟踪器最大数量:VNObjectTrackerType}

是我使用API不正确,还是Vision在处理太多连续的对象跟踪任务时遇到问题?很好奇是否有人了解为什么会发生这种情况。

似乎达到了系统中可激活跟踪器数量的限制。首先要注意的是,每次使用带有new-uuid属性的新观察时,都会创建一个新的跟踪器。你应该通过将你从时间T的"结果"中得到的信息输入到你对时间T+1的后续请求中,来回收你在启动跟踪器时使用的初始观察结果,直到你不再想使用它。当你不再想使用该跟踪器时(可能置信度得分太低(,可以设置一个"lastFrame"属性,让Vision框架知道你已经使用完该跟踪器。当序列请求处理程序被释放时,跟踪器也会被释放。

要跟踪矩形,您可以将结果观察结果馈送到同一个VNSequenceRequestHandler实例,例如handler。当矩形丢失时,即处理程序函数/回调中的新观察是nil,或者您遇到了其他跟踪错误,只需重新实例化handler并继续,例如(显示想法的示例代码(:

private var handler = VNSequenceRequestHandler()
// <...>
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
guard
let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer),
let lastObservation = self.lastObservation
else { 
self.handler = VNSequenceRequestHandler()
return
}
let request = VNTrackObjectRequest(detectedObjectObservation: lastObservation, completionHandler: self.handleVisionRequestUpdate)
request.trackingLevel = .accurate
do {
try self.handler.perform([request], on: pixelBuffer)
} catch {
print("Throws: (error)")
}
}

注意,handlervar,而不是常数。

此外,您可以在实际的处理程序函数(如func handleVisionRequestUpdate(_ request: VNRequest, error: Error?)(中重新实例化handler,以防新的观察对象无效。

我的问题是我有一个函数调用perform。。。在跟踪也调用的同一VNSequenceRequestHandler上执行,因为我同时处理了太多try self.visionSequenceHandler.perform(trackRequests, on: ciimage)。确保VNSequenceRequestHandler不会同时被多个执行命中。。。。

为了避免"超过跟踪器的最大允许数量";错误,您必须停止所有跟踪对象的跟踪器。您必须将isLastFrame设置为true,然后再次在handler上执行此request

extension VNTrackingRequest {
func completeTracking(
with handler: VNSequenceRequestHandler,
on sampleBuffer: CMSampleBuffer
) {
isLastFrame = true
try? handler.perform([self], on: sampleBuffer)
}
}

下面是一个处理示例。如果没有observation,则ObjectTracker尝试定位新对象。但是,如果已经检测到一个对象(observation(,它将跟踪它的位置。

class ObjectTracker: CameraViewControllerOutputDelegate {
var observation: VNDetectedObjectObservation?
private lazy var objectDetectRequest: VNCoreMLRequest = newObjectDetectRequest()
private var objectTrackingRequest: VNTrackObjectRequest?
private func newObjectDetectRequest() -> VNCoreMLRequest {
do {
let mlModel = try YourMLModel(configuration: .init()).model
let model = try VNCoreMLModel(for: mlModel)
let request = VNCoreMLRequest(model: model)
return request
} catch {
fatalError("Failed to load ML Model. Error: (error)")
}
}
private func newObjectTrackingRequest(
for observation: VNDetectedObjectObservation
) -> VNTrackObjectRequest {
let request = VNTrackObjectRequest(detectedObjectObservation: observation)
request.trackingLevel = .fast
return request
}

func cameraViewController(
_ controller: CameraViewController,
didReceiveBuffer buffer: CMSampleBuffer,
orientation: CGImagePropertyOrientation
) {
if let oldObservation = observation {
objectTrackingRequest = objectTrackingRequest ?? newObjectTrackingRequest(for: oldObservation)
let visionHandler = VNSequenceRequestHandler()
try? visionHandler.perform([objectTrackingRequest!], on: buffer, orientation: orientation)
if let newObservation = objectTrackingRequest?.results?.first as? VNDetectedObjectObservation {
observation = newObservation
objectTrackingRequest?.inputObservation = newObservation
} else {
observation = nil
objectTrackingRequest?.completeTracking(with: visionHandler, on: buffer)
objectTrackingRequest = nil
}

} else {
objectDetectRequest = newObjectDetectRequest()
let visionHandler = VNImageRequestHandler(cmSampleBuffer: buffer, orientation: orientation, options: [:] )
try? visionHandler.perform([objectDetectRequest])

if let newObservation = objectDetectRequest.results?.first as? VNRecognizedObjectObservation {
observation = newObservation
}
}
}
}

isLastFrame属性的跟踪观察被认为不再有用时,您必须释放请求的跟踪器。

guard let processedRequest = processedRequest as? VNTrackObjectRequest
else { continue }

guard let results = processedRequest.results,
let observation = results.first as? VNDetectedObjectObservation,
observation.confidence > 0.1
else {
// Tells Vision that we want to release the tracker reserved for this request, freeing resources
processedRequest.isLastFrame = true

// Feed the request again into Vision, effectively taking into account the new isLastFrame value
do {
try trackingRequestHandler.perform([processedRequest], on: frame, orientation: .up)
} catch {
print(error)
}
continue
}

在设置isLastFrame属性后再次执行请求非常重要,这样Vision就可以读取它。

最新更新