0

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

视频层

这是我的捕获代码。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)
}

这就是我不断得到的东西。

在此处输入图像描述

我在搞什么鬼?

4

2 回答 2

0

UIKit 世界的左上角为 0,0。

AVFoundation 世界中的 0,0 点是左下角。

所以你必须通过旋转 90 度来平移。

这就是为什么你的形象是疯狂的。

还要记住,由于原始翻译,以下规则适用:

  • X实际上是上下
  • Y其实是左右
  • 宽度和高度交换

另请注意,UIImageView 内容模式设置将影响您的图像缩放方式。如果您真的想查看图像在 UIView 中的外观,您可能需要使用 .scaleAspectFill 而不是 AspectFit。

我使用此代码片段来查看幕后的内容:

// figure out how to cut/crop this
let realImageRect = AVMakeRect(aspectRatio: image.size, insideRect: (self.cameraPreview?.frame)!)
NSLog("real image rectangle = \(realImageRect.debugDescription)")

上面的“cameraPreview”参考是您用于 AV 捕获会话的控件。

祝你好运!

于 2021-03-29T20:54:41.400 回答
0

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

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
于 2021-10-07T07:02:04.370 回答