因此,您正在使用产生VNRectangleObservation
s 的 Vision 请求,并且您想提取由这些观察结果识别的主题图像的区域?也许也可以透视投影它们,以便它们在图像平面上是矩形的?( WWDC17 的 Vision session 中有一个演示。)
CIPerspectiveCorrection
您可以使用Core 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),
])
}
旁白:scaled
上面的函数是一个方便的扩展,CGPoint
可以使调用站点的坐标数学更小一些:
extension CGPoint {
func scaled(to size: CGSize) -> CGPoint {
return CGPoint(x: self.x * size.width,
y: self.y * size.height)
}
}
现在,这为您提供了一个CIImage
对象——它们本身并不是真正可显示的图像,只是有关如何处理和显示图像的说明,可以通过许多不同的可能方式来完成。显示图像的许多方法都涉及CIContext
——您可以将其渲染到另一个像素缓冲区,或者如果您尝试实时进行此处理,也可以将其渲染到金属纹理中——但不是全部。另一方面,如果您只是不太频繁地显示静态图像,您可以直接从 CIImage 创建一个 UIImage并将其显示在 aUIImageView
中,UIKit 将管理底层CIContext
和渲染过程。