ios - VNTrackObjectRequest 从前一帧返回被跟踪对象的位置
问题描述
我正在尝试使用VNTrackObjectRequest
跟踪 QR 码,但我无法弄清楚如何将结果映射回前一帧中的 QR 码。
我期望在移动 QR 码的图像上执行请求后,跟踪请求提供的boundingBox
QR 码与提供的图像中的 QR 码相同,并且与第一张图像中 QR 码的位置不同,而是反之亦然。
我想我遗漏了一些导致它无法按预期工作的基本信息?
import Foundation
import XCTest
import Vision
final class ObjectTrackingTests: XCTestCase {
func testQRCodeDisappearing() throws {
// Any image with a QR code
let imageWithQRCode = UIImage(named: "Tracked QR Code Position 1", in: Bundle(for: Self.self), compatibleWith: nil)!
let pixelBufferWithQRCode = try imageWithQRCode.pixelBuffer()
// Any image with the same QR code, but with the position shifted
let imageWithMovedQRCode = UIImage(named: "Tracked QR Code Position 2", in: Bundle(for: Self.self), compatibleWith: nil)!
let pixelBufferWithMovedQRCode = try imageWithMovedQRCode.pixelBuffer()
// Any image without a QR code
let imageWithoutQRCode = UIImage(named: "Tracked QR Code Off Screen", in: Bundle(for: Self.self), compatibleWith: nil)!
let pixelBufferWithoutQRCode = try imageWithoutQRCode.pixelBuffer()
let imageRequestHandler = VNSequenceRequestHandler()
let barcodeRequest = VNDetectBarcodesRequest()
// Check initial image with QR code
try imageRequestHandler.perform([barcodeRequest], on: pixelBufferWithQRCode, orientation: .up)
XCTAssertEqual(barcodeRequest.results?.count, 1)
let detectedBarcode = try XCTUnwrap(barcodeRequest.results?.first)
let trackRequest = VNTrackObjectRequest(detectedObjectObservation: detectedBarcode)
trackRequest.trackingLevel = .accurate
// Check image with QR code that has moved down
try imageRequestHandler.perform([barcodeRequest, trackRequest], on: pixelBufferWithMovedQRCode, orientation: .up)
XCTAssertEqual(barcodeRequest.results?.count, 1)
let detectedMovedBarcode = try XCTUnwrap(barcodeRequest.results?.first)
let trackedResult = try XCTUnwrap(trackRequest.results?.first as? VNDetectedObjectObservation)
XCTAssertEqual(trackedResult.boundingBox, detectedMovedBarcode.boundingBox) // This fails
XCTAssertNotEqual(trackedResult.boundingBox, detectedBarcode.boundingBox) // This fails
// Check image without a QR code
try imageRequestHandler.perform([barcodeRequest, trackRequest], on: pixelBufferWithoutQRCode, orientation: .up)
XCTAssertTrue(barcodeRequest.results?.isEmpty ?? true)
XCTAssertTrue(trackRequest.results?.isEmpty ?? true) // This fails
}
}
// This extension is required for the tests and is provided to make running this example easier.
extension UIImage {
fileprivate enum PixelBufferConversionError: Error {
case bufferCreationFailure(result: CVReturn)
}
fileprivate func pixelBuffer() throws -> CVPixelBuffer {
var pixelBuffer: CVPixelBuffer!
let width = Int(size.width)
let height = Int(size.height)
let createBufferResult = CVPixelBufferCreate(
kCFAllocatorDefault,
width,
height,
kCVPixelFormatType_32ARGB,
[
kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue
] as CFDictionary,
&pixelBuffer
)
guard createBufferResult == kCVReturnSuccess else {
throw PixelBufferConversionError.bufferCreationFailure(result: createBufferResult)
}
CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
defer {
CVPixelBufferUnlockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
}
let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer)
let context = CGContext(
data: pixelData,
width: width,
height: height,
bitsPerComponent: 8,
bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer),
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue
)!
context.translateBy(x: 0, y: size.height)
context.scaleBy(x: 1.0, y: -1.0)
UIGraphicsPushContext(context)
draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
UIGraphicsPopContext()
return pixelBuffer
}
}
使用的图像:
解决方案
推荐阅读
- python - Tkinter 帧自动缩放到最大帧大小,不是相对的
- css - React Inline Style:我将如何重构这种边框样式?
- amazon-web-services - 有没有办法将数据从 AWS EC2 流式传输到本地内存?
- python - python列表中的错误数据
- sql - 将 PERCENTILE_CONT 与百分位值表一起应用
- javascript - 句子中的有色元素在跨度时会失去颜色
- python - 在不使用内置函数的情况下在 python 上编写离散傅立叶变换
- c++ - 代码的时间复杂度(用于按排序(升序)顺序计算字符串后缀数组的递归函数)
- r - 使用 getCall() 在 R 中提取数据调用和更改
- json - 在 Scala 上保持 json