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

问题描述

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

videoLayer

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

这是我不断得到的东西。

enter image description here

我在搞什么鬼?

解决方法

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 捕获会话的控件。

祝你好运!

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...