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

时间:2018-01-09 14:59:14

标签: ios computer-vision rectangles

如何从成功的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)
    }
}

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

有什么想法吗?

1 个答案:

答案 0 :(得分:8)

您是否正在使用生成VNRectangleObservation s的Vision请求,并且您想要拉出这些观察所标识的主题图像的区域?也许透视 - 投射它们,以便它们在图像平面中呈矩形? (这是in the Vision session from WWDC17的演示。)

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

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),
    ])
}
  

除此之外:上面的scaled函数是CGPoint上的便捷扩展,可以使呼叫站点的坐标数学变小:

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

现在,它会为您提供一个CIImage对象 - 这些对象本身并不是真正可显示的图像,只是如何处理和显示图像的说明,可以通过多种不同的方式完成。许多显示图像的方法都涉及CIContext - 您可以将其渲染到另一个像素缓冲区中,或者如果您尝试实时进行此处理,则可能是金属纹理 - 但不是全部。另一方面,如果您只是不那么频繁地显示静态图像,可以create a UIImage directly from the CIImage并将其显示在UIImageView中,UIKit将管理基础CIContext和渲染过程