首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从AVCapturePhotoOutput裁剪CGRect (resizeAspectFill)

从AVCapturePhotoOutput裁剪CGRect (resizeAspectFill)
EN

Stack Overflow用户
提问于 2021-09-25 17:15:54
回答 1查看 106关注 0票数 2

我发现了以下问题,不幸的是,其他帖子并没有帮助我找到一个有效的解决方案。

我有一个简单的应用程序,显示相机预览(AVCaptureVideoPreviewLayer),其中视频重力已设置为resizeAspectFill (videoGravity = .resizeAspectFill)。

据我所知,这只是在宽度上划痕图像,以使其充满屏幕。

在我的预览层上,我也应用了一个CGRect作为一个固定x,y,宽和高的蒙版。

现在,一旦我拍了一张照片,我就会试着从图像中裁剪出那个确切的矩形。根据我的理解,我应该使用某种数学方法将CGRect转换为与我从AVCapturePhotoOutput方法获得的图像相同的纵横比,但它似乎从来没有正确地裁剪宽度。

代码语言:javascript
复制
    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“左边的半个按钮(Tab按钮)。

任何对解决方案的帮助都将不胜感激!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-27 09:54:59

我设法用这段代码解决了这个问题。

代码语言:javascript
复制
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
}

我的案例中这段代码的用法:

代码语言:javascript
复制
let rect = CGRect(x: 25, y: 150, width: 325, height: 230)
let croppedImage = self.cropToPreviewLayer(from: image, toSizeOf: rect)
self.imageView.image = croppedImage
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69328405

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档