【问题标题】:iOS Vision: Drawing Detected Rectangles on Live Camera Preview Works on iPhone But Not on iPadiOS 视觉:在实时摄像头预览上绘制检测到的矩形适用于 iPhone,但不适用于 iPad
【发布时间】:2022-08-23 21:25:03
【问题描述】:

我正在使用 iOS Vision 框架通过 iPhone 上的摄像头实时检测矩形,效果很好。实时预览会在检测到的形状周围显示一个移动的黄色矩形。

但是,当在 iPad 上运行相同的代码时,黄色矩形准确地沿着 X 轴跟踪,但在 Y 轴上它总是稍微偏离中心并且没有正确缩放。包含的图像显示两个设备跟踪相同的测试方块以更好地说明。在这两种情况下,在我捕获图像并在整个相机帧 (1920 x 1080) 上绘制矩形后,一切看起来都很好。只是 iPad 上的实时预览无法正确跟踪。

我相信这个问题是由 iPad 屏幕的 4:3 纵横比引起的。 iPhone 的全屏预览将其 1920 x 1080 原始帧缩小到 414 x 718,其中 X 和 Y 暗淡按相同的比例缩小(约 2.6)。但是,iPad 将 1920 x 1080 帧缩小到 810 x 964,这会扭曲图像并导致沿 Y 轴的误差。

一个粗略的解决方案可能是设置一个小于全屏的预览层大小,并以匹配 1920 x 1080 的 16:9 比例均匀缩小,但我更喜欢使用全屏。这里有没有人遇到过这个问题并找到了一个可以正确地将矩形观察转换和缩放到 iPad 屏幕上的转换?

示例测试图像和代码 sn-p 如下。

let rect: VNRectangleObservation

//Camera preview (live) image dimensions
let previewWidth = self.previewLayer!.bounds.width
let previewHeight = self.previewLayer!.bounds.height

//Dimensions of raw captured frames from the camera (1920 x 1080)
let frameWidth = self.frame!.width
let frameHeight = self.frame!.height

//Transform to change detected rectangle from Vision framework\'s coordinate system to SwiftUI
let transform = CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: -(previewHeight))
let scale = CGAffineTransform.identity.scaledBy(x: previewWidth, y: previewHeight)

//Convert the detected rectangle from normalized [0, 1] coordinates with bottom left origin to SwiftUI top left origin
//and scale the normalized rect to preview window dimensions.
var bounds: CGRect = rect.boundingBox.applying(scale).applying(transform)

//Rest of code draws the bounds CGRect in yellow onto the preview window, as shown in the image.
  • 好吧,这真的取决于您如何呈现和缩放相机(在 UIViewRepreaentable 中)是 .scaledToFill 吗?
  • 好问题——我没有想到预览层的属性。在不粘贴整个 UIRepresentable 的情况下,我可以确认我已将其设置为:view.videoPreviewLayer.videoGravity = .resizeAspectFill,我只是将其更改为:view.videoPreviewLayer.videoGravity = .resizeAspect,现在矩形正确地在 Y 上跟踪,但不是在 X 上,并且它的框架正确在 Y 上,但在 X 上伸展得太远了。我会再研究一下 - 谢谢你的想法!
  • 只是为了跟进这一点:解决方案最终是将预览层更改为缩放为 .resizeAspect 的组合,保留原始帧的比例,然后将矩形绘制为帧视图上的 .overlay,这样矩形\的坐标是相对于图像的原点调整后的原点与父视图的原点计算的。这修复了矩形的翘曲及其定位偏移。
  • 是的,很高兴您找到了解决问题的方法。您可以制作并回答并接受它。
  • @lepapillon 我无法在 previewLayer 顶部绘制叠加层(我正在使用额外的 CAShapeLayer),你能分享你正在使用的实际绘图代码吗?

标签: ios swift ipad apple-vision


【解决方案1】:

如果它对其他人有帮助,根据 Mr.SwiftOak 的评论发布的信息,我能够通过将预览图层更改为 .resizeAspect 而不是 .resizeAspectFill 的组合来解决问题,保留原始的比例预览中的框架。这导致预览不再占据整个 iPad 屏幕,但更容易准确地叠加。

然后,我将矩形作为 .overlay 绘制到预览窗口,以便绘图坐标相对于图像的原点(左上角)而不是视图本身,其原点位于 (0, 0) 的左上角整个屏幕。

为了澄清我是如何绘制矩形的,有两个部分:

  1. 将检测矩形边界框转换为 CAShapeLayers 上的路径: ` 让 boxPath = CGPath(rect: bounds, transform: nil)

    让 boxShapeLayer = CAShapeLayer()

    boxShapeLayer.path = boxPath boxShapeLayer.fillColor = UIColor.clear.cgColor boxShapeLayer.strokeColor = UIColor.yellow.cgColor

    boxLayers.append(boxShapeLayer) `

  2. 在预览 UIRpresentable 的 updateUIView 中附加图层:

    func updateUIView(_ uiView: VideoPreviewView, context: Context) { 如果让矩形 = self.viewModel.rectangleDrawings { 对于矩形矩形{ uiView.videoPreviewLayer.addSublayer(rect) //print("pvw 中的图像大小: (String(describing: viewModel.previewLayer?.preferredFrameSize()))") } } }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多