裁剪 AVCapturePhoto 以覆盖屏幕上显示的矩形

Sir*_*iss 0 camera ios avcapturesession swift avcapturephotooutput

我正在尝试拍摄一块薄金属的照片,并将其裁剪为屏幕上显示的轮廓。我几乎看过这里的所有其他帖子,但还没有任何东西适合我。然后该图像将被图书馆用于分析。我可以进行一些裁剪,但不能对显示的矩形进行裁剪。我尝试在裁剪之前旋转图像,并根据屏幕上的矩形计算矩形。

视频层

这是我的捕获代码。PreviewView是容器,videoLayer是AVCapture视频的容器。

    // Photo capture delegate
    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        guard let imgData = photo.fileDataRepresentation(), let uiImg = UIImage(data: imgData), let cgImg = uiImg.cgImage else {
            return
        }
        print("Original image size: ", uiImg.size, "\nCGHeight: ", cgImg.height, " width: ", cgImg.width)
        print("Orientation: ", uiImg.imageOrientation.rawValue)
        
        guard let img = cropImage(image: uiImg) else {
            return
        }
        
        showImage(image: img)
    }

    
    func cropImage(image: UIImage) -> UIImage? {
        print("Image size before crop: ", image.size)
        //Get the croppedRect from function below
        let croppedRect = calculateRect(image: image)
        guard let imgRet = image.cgImage?.cropping(to: croppedRect) else {
            return nil
        }
        return UIImage(cgImage: imgRet)
    }
    
    func calculateRect(image: UIImage) -> CGRect {
        let originalSize: CGSize
        let visibleLayerFrame = self.rectangleView.bounds

        // Calculate the rect from the rectangleview to translate to the image
        let metaRect = (self.videoLayer.metadataOutputRectConverted(fromLayerRect: visibleLayerFrame))
        print("MetaRect: ", metaRect)
        // check orientation
        if (image.imageOrientation == UIImage.Orientation.left || image.imageOrientation == UIImage.Orientation.right) {
            originalSize = CGSize(width: image.size.height, height: image.size.width)
        } else {
            originalSize = image.size
        }

        let cropRect: CGRect = CGRect(x: metaRect.origin.x * originalSize.width, y: metaRect.origin.y * originalSize.height, width: metaRect.size.width * originalSize.width, height: metaRect.size.height * originalSize.height).integral
        print("Calculated Rect: ", cropRect)
        return cropRect
    }

func showImage(image: UIImage) {
    if takenImage != nil {
        takenImage = nil
    }
    takenImage = UIImageView(image: image)
    takenImage.frame = CGRect(x: 10, y: 50, width: 400, height: 1080)
    takenImage.contentMode = .scaleAspectFit
    print("Cropped Image Size: ", image.size)
    self.previewView.addSubview(takenImage)
}
Run Code Online (Sandbox Code Playgroud)

这是我不断得到的信息。

在此输入图像描述

我搞砸了什么?

Rob*_*bin 5

我设法解决了我的用例的问题。

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
}
Run Code Online (Sandbox Code Playgroud)

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

let rect = CGRect(x: 25, y: 150, width: 325, height: 230)
let croppedImage = self.cropToPreviewLayer(from: image, toSizeOf: rect)
self.imageView.image = croppedImage
Run Code Online (Sandbox Code Playgroud)