【问题标题】:Capturing still image from AVFoundation that matches viewfinder border on AVCaptureVideoPreviewLayer in Swift从 AVFoundation 捕获与 Swift 中 AVCaptureVideoPreviewLayer 上的取景器边框匹配的静止图像
【发布时间】:2018-01-30 12:53:59
【问题描述】:

拍照后尝试捕捉绿色取景器中的内容。

请看图片:

这是代码当前正在执行的操作:

拍照前:

拍照后(结果图像的比例不正确,因为它与绿色取景器中的不匹配):

如您所见,图像需要按比例放大以适合最初包含在绿色取景器中的内容。即使我计算出正确的缩放比例(对于 iPhone 6,我需要将捕获图像的尺寸乘以 1.334,它不起作用)

有什么想法吗?

【问题讨论】:

    标签: swift camera avfoundation overlay aspect-ratio


    【解决方案1】:

    解决这个问题的步骤:

    首先,获取完整尺寸的图像:我还使用了 UIImage 类的扩展名为“正确定向”。

    let correctImage = UIImage(data: imageData!)!.correctlyOriented()
    

    所有这一切都是取消旋转 iPhone 图像,因此纵向图像(使用 iPhone 底部的主页按钮拍摄)按预期定向。该扩展名如下:

    extension UIImage {
    
    func correctlyOriented() -> UIImage {
    
    if imageOrientation == .up {
        return self
    }
    
    // We need to calculate the proper transformation to make the image upright.
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
    var transform = CGAffineTransform.identity
    
    switch imageOrientation {
    case .down, .downMirrored:
        transform = transform.translatedBy(x: size.width, y: size.height)
        transform = transform.rotated(by: CGFloat.pi)
    case .left, .leftMirrored:
        transform = transform.translatedBy(x: size.width, y: 0)
        transform = transform.rotated(by:  CGFloat.pi * 0.5)
    case .right, .rightMirrored:
        transform = transform.translatedBy(x: 0, y: size.height)
        transform = transform.rotated(by:  -CGFloat.pi * 0.5)
    default:
        break
    }
    
    switch imageOrientation {
    case .upMirrored, .downMirrored:
        transform = transform.translatedBy(x: size.width, y: 0)
        transform = transform.scaledBy(x: -1, y: 1)
    case .leftMirrored, .rightMirrored:
        transform = transform.translatedBy(x: size.height, y: 0)
        transform = transform.scaledBy(x: -1, y: 1)
    default:
        break
    }
    
    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    guard
        let cgImage = cgImage,
        let colorSpace = cgImage.colorSpace,
        let context = CGContext(data: nil,
                                width: Int(size.width),
                                height: Int(size.height),
                                bitsPerComponent: cgImage.bitsPerComponent,
                                bytesPerRow: 0,
                                space: colorSpace,
                                bitmapInfo: cgImage.bitmapInfo.rawValue) else {
                                    return self
    }
    
    context.concatenate(transform)
    
    switch imageOrientation {
    case .left, .leftMirrored, .right, .rightMirrored:
        context.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.height, height: size.width))
    default:
        context.draw(cgImage, in: CGRect(origin: .zero, size: size))
    }
    
    // And now we just create a new UIImage from the drawing context
    guard let rotatedCGImage = context.makeImage() else {
        return self
    }
    
    return UIImage(cgImage: rotatedCGImage)
    }
    

    接下来,计算高度因子:

    let heightFactor = self.view.frame.height / correctImage.size.height
    

    根据高度因子创建一个新的CGSize,然后调整图像大小(使用resize image函数,未显示):

    let newSize = CGSize(width: correctImage.size.width * heightFactor, height: correctImage.size.height * heightFactor)
    
    let correctResizedImage = self.imageWithImage(image: correctImage, scaledToSize: newSize)
    

    现在,由于 iPhone 摄像头的纵横比为 4:3,而 iPhone 屏幕的纵横比为 16:9,因此我们的图像与我们的设备高度相同,但更宽。因此,将图像裁剪为与设备屏幕相同的大小:

    let screenCrop: CGRect = CGRect(x: (newSize.width - self.view.bounds.width) * 0.5,
                                                    y: 0,
                                                    width: self.view.bounds.width,
                                                    height: self.view.bounds.height)
    
    
    var correctScreenCroppedImage = self.crop(image: correctResizedImage, to: screenCrop)
    

    最后,我们需要复制绿色“取景器”创建的“裁剪”。因此,我们执行另一次裁剪以使最终图像匹配:

    let correctCrop: CGRect = CGRect(x: 0,
                                              y: (correctScreenCroppedImage!.size.height * 0.5) - (correctScreenCroppedImage!.size.width * 0.5),
                                              width: correctScreenCroppedImage!.size.width,
                                              height: correctScreenCroppedImage!.size.width)
    
    var correctCroppedImage = self.crop(image: correctScreenCroppedImage!, to: correctCrop)
    

    此答案归功于@damirstuhec

    【讨论】:

    • 谢谢,但我不知道 self.crop 和 self.imageWithImage 的功能如果可以,你能告诉我 self.crop 的功能吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多