Cropping CGRect from AVCapturePhotoOutput (resizeAspectFill)(从AVCapturePhotoOutput(SizeAspectFill)裁剪CGRect)
问题描述
我发现了以下问题,不幸的是,其他帖子并没有帮助我找到有效的解决方案。
我有一个简单的应用程序,可以显示摄像头预览(AVCaptureVideoPreviewLayer),其中视频重力已设置为sizeAspectFill(videoGravity = .resizeAspectFill
)。
据我所知,这只会使图像在宽度上产生条纹,以填满屏幕。
在我的预览层上,我还应用了CGRect作为具有固定x、y、宽度和高度的蒙版。
现在,一旦我拍了一张照片,我就会试着从图像中剪裁出那个确切的矩形。据我所知,我应该使用某种数学方法将CGRect转换为与从AVCapturePhotoOutput方法获得的图像相同的纵横比,但它似乎从未正确裁剪过宽度。
private func cropImage(image: UIImage) {
let rect = CGRect(x: 25, y: 150, width: 325, height: 230)
let scale = CGAffineTransform(scaleX: 1/self.view.frame.width, y: 1/self.view.frame.height)
let flip = CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: -1)
let bounds = rect.applying(scale).applying(flip)
let topLeft = bounds.topLeft.scaled(to: image.size)
let topRight = bounds.topRight.scaled(to: image.size)
let bottomLeft = bounds.bottomLeft.scaled(to: image.size)
let bottomRight = bounds.bottomRight.scaled(to: image.size)
var ciImage = CIImage(image: image.forceSameOrientation())!
ciImage = ciImage.applyingFilter("CIPerspectiveCorrection", parameters: [
"inputTopLeft": CIVector(cgPoint: bottomLeft),
"inputTopRight": CIVector(cgPoint: bottomRight),
"inputBottomLeft": CIVector(cgPoint: topLeft),
"inputBottomRight": CIVector(cgPoint: topRight)
])
let context = CIContext()
let cgImage = context.createCGImage(ciImage, from: ciImage.extent)
let output = UIImage(cgImage: cgImage!)
let vc = PreviewViewController()
vc.imageView.image = output
self.present(vc, animated: true, completion: nil)
}
再说一遍,基本上它确实在正确的高度裁剪,但它的宽度似乎不太好。
我要捕获的内容的图像示例。
https://imgur.com/a/8GryEgX
如您所见,左上角的边框在";Q";按钮之后停止。
结果:
https://imgur.com/FwKRWxK
正如您在此图中看到的,它确实在高度上正确裁剪,但如果我们查看左上角,它还包括";q";(选项卡按钮)左侧的半个按钮
如对解决方案有任何帮助,我们将不胜感激!
推荐答案
我设法用此代码解决了该问题。
private func cropToPreviewLayer(from originalImage: UIImage, toSizeOf rect: CGRect) -> UIImage? {
guard let cgImage = originalImage.cgImage else { return nil }
// This previewLayer is the AVCaptureVideoPreviewLayer which the resizeAspectFill and videoOrientation portrait has been set.
let outputRect = previewLayer.metadataOutputRectConverted(fromLayerRect: rect)
let width = CGFloat(cgImage.width)
let height = CGFloat(cgImage.height)
let cropRect = CGRect(x: (outputRect.origin.x * width), y: (outputRect.origin.y * height), width: (outputRect.size.width * width), height: (outputRect.size.height * height))
if let croppedCGImage = cgImage.cropping(to: cropRect) {
return UIImage(cgImage: croppedCGImage, scale: 1.0, orientation: originalImage.imageOrientation)
}
return nil
}
我的案例中这段代码的用法:
let rect = CGRect(x: 25, y: 150, width: 325, height: 230)
let croppedImage = self.cropToPreviewLayer(from: image, toSizeOf: rect)
self.imageView.image = croppedImage
这篇关于从AVCapturePhotoOutput(SizeAspectFill)裁剪CGRect的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:从AVCapturePhotoOutput(SizeAspectFill)裁剪CGRect
基础教程推荐
- Kivy Buildozer 无法构建 apk,命令失败:./distribute.sh -m “kivy"d 2022-01-01
- android 应用程序已发布,但在 google play 中找不到 2022-01-01
- 在 gmail 中为 ios 应用程序检索朋友的朋友 2022-01-01
- UIWebView 委托方法 shouldStartLoadWithRequest:在 WKWebView 中等效? 2022-01-01
- Android:对话框关闭而不调用关闭 2022-01-01
- 如何在 UIImageView 中异步加载图像? 2022-01-01
- 如何在没有IB的情况下将2个按钮添加到右侧的UINavigationbar? 2022-01-01
- 当从同一个组件调用时,两个 IBAction 触发的顺序是什么? 2022-01-01
- 如何让对象对 Cocos2D 中的触摸做出反应? 2022-01-01
- 如何在 iPhone 上显示来自 API 的 HTML 文本? 2022-01-01