如何在Apple Vision框架中拍摄检测到的矩形照片

den*_*631 3 rectangles computer-vision ios

如何从成功的VNRectangleObservation对象拍摄照片(获取CIImage)?

我有一个视频捕获会话正在运行,func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)我正在处理,即

func captureOutput(_ output: AVCaptureOutput,
                   didOutput sampleBuffer: CMSampleBuffer,
                   from connection: AVCaptureConnection) {
    guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }

    do {
        try handler.perform([request], on: pixelBuffer)
    } catch {
        print(error)
    }
}
Run Code Online (Sandbox Code Playgroud)

我应该在哪里保存我传递给处理程序并在该缓冲区上操作的像素缓冲区?遗憾的是,我无法从观察对象访问图像作为属性:(

有任何想法吗?

ric*_*ter 9

因此,您正在使用生成VNRectangleObservations 的Vision请求,并且您想要拉出由这些观察所识别的主题图像的区域?也许透视 - 投射它们,以便它们在图像平面中是矩形的?(在WWDC17的Vision会议中有一个演示.)

您可以使用CIPerspectiveCorrectionCore Image中的过滤器提取和纠正该区域.要设置它,您需要从图像观察中传递点,转换为像素坐标.看起来像这样:

func extractPerspectiveRect(_ observation: VNRectangleObservation, from buffer: CVImageBuffer) -> CIImage {
    // get the pixel buffer into Core Image
    let ciImage = CIImage(cvImageBuffer: buffer)

    // convert corners from normalized image coordinates to pixel coordinates
    let topLeft = observation.topLeft.scaled(to: ciImage.extent.size)
    let topRight = observation.topRight.scaled(to: ciImage.extent.size)
    let bottomLeft = observation.bottomLeft.scaled(to: ciImage.extent.size)
    let bottomRight = observation.bottomRight.scaled(to: ciImage.extent.size)

    // pass those to the filter to extract/rectify the image
    return ciImage.applyingFilter("CIPerspectiveCorrection", parameters: [
        "inputTopLeft": CIVector(cgPoint: topLeft),
        "inputTopRight": CIVector(cgPoint: topRight),
        "inputBottomLeft": CIVector(cgPoint: bottomLeft),
        "inputBottomRight": CIVector(cgPoint: bottomRight),
    ])
}
Run Code Online (Sandbox Code Playgroud)

旁白:scaled上面的函数是一个方便的扩展CGPoint,使调用站点的坐标数学更小:

extension CGPoint {
   func scaled(to size: CGSize) -> CGPoint {
       return CGPoint(x: self.x * size.width,
                      y: self.y * size.height)
   }
}
Run Code Online (Sandbox Code Playgroud)

现在,这会让你成为一个CIImage对象 - 那些不是真正可显示的图像本身,只是如何处理和显示图像的指令,可以通过许多不同的方式完成.显示图像的许多方法都涉及CIContext- 您可以将其渲染到另一个像素缓冲区中,或者如果您尝试实时进行此处理,则可能是金属纹理 - 但不是全部.另一方面,如果您只是不经常显示静态图像,可以直接从CIImage创建UIImage并将其显示在a中UIImageView,UIKit将管理底层CIContext和渲染过程.