当前位置: 首页 > 面试题库 >

如何获取AVCaptureVideoPreviewLayer的UIImage而不是AVCapturePhotoOutput捕获

庞修贤
2023-03-14
问题内容

我想将预览层“流式传输”到我的服务器,但是,我只希望发送特定的帧。基本上,我想拍摄AVCaptureVideoPreviewLayer的快照,将其缩放到28 * 28,将其转换为强度数组,然后将其发送到我的python后端处理其余部分的套接字层。

这里的问题是AVCapturePhotoOutput的捕获功能异常缓慢。我不能重复调用该函数。更不用说它总是使相机的快门声哈哈。

另一个问题是拍摄AVCaptureVideoPreviewLayer的快照确实很困难。使用UIGraphicsBeginImageContext几乎总是返回空白/清晰图像。

帮兄弟出去,谢谢!


问题答案:

基本上,应该使用AVCaptureVideoDataOutputSampleBufferDelegate而不是使用AVCaptureVideoPreviewLayer来捕获帧。这是示例:

import Foundation
import UIKit
import AVFoundation

protocol CaptureManagerDelegate: class {
    func processCapturedImage(image: UIImage)
}

class CaptureManager: NSObject {
    internal static let shared = CaptureManager()
    weak var delegate: CaptureManagerDelegate?
    var session: AVCaptureSession?

    override init() {
        super.init()
        session = AVCaptureSession()

        //setup input
        let device =  AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
        let input = try! AVCaptureDeviceInput(device: device)
        session?.addInput(input)

        //setup output
        let output = AVCaptureVideoDataOutput()
        output.videoSettings = [kCVPixelBufferPixelFormatTypeKey as AnyHashable: kCVPixelFormatType_32BGRA]
        output.setSampleBufferDelegate(self, queue: DispatchQueue.main)
        session?.addOutput(output)
    }

    func statSession() {
        session?.startRunning()
    }

    func stopSession() {
        session?.stopRunning()
    }

    func getImageFromSampleBuffer(sampleBuffer: CMSampleBuffer) ->UIImage? {
        guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
            return nil
        }
        CVPixelBufferLockBaseAddress(pixelBuffer, .readOnly)
        let baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer)
        let width = CVPixelBufferGetWidth(pixelBuffer)
        let height = CVPixelBufferGetHeight(pixelBuffer)
        let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue)
        guard let context = CGContext(data: baseAddress, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) else {
            return nil
        }
        guard let cgImage = context.makeImage() else {
            return nil
        }
        let image = UIImage(cgImage: cgImage, scale: 1, orientation:.right)
        CVPixelBufferUnlockBaseAddress(pixelBuffer, .readOnly)
        return image
    }
}

extension CaptureManager: AVCaptureVideoDataOutputSampleBufferDelegate {
    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
        guard let outputImage = getImageFromSampleBuffer(sampleBuffer: sampleBuffer) else {
            return
        }
        delegate?.processCapturedImage(image: outputImage)
    }
}

更新:
要处理图像,您应该在所需的任何其他类中实现CaptureManagerDelegate协议的processCapturedImage方法,例如:

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var imageView: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()
        CaptureManager.shared.statSession()
        CaptureManager.shared.delegate = self
    }
}

extension ViewController: CaptureManagerDelegate {
    func processCapturedImage(image: UIImage) {
        self.imageView.image = image
    }
}


 类似资料:
  • 问题内容: 我正在使用自定义相机应用程序,本教程使用的是iOS 10弃用的AVCaptureStillImageOutput。我已经设置了相机,现在只能使用如何拍照了。 这是我有相机的全景 这是我需要帮助的地方 我已经在这里回答了如何使用AVCapturePhotoOutput,但是我不明白如何在该代码中合并该代码,因为它涉及到声明一个新类。 问题答案: 你快到了。 查看 文档以获取更多帮助。 这

  • 问题内容: 我试图获取从Swift中的Library导入的图像的URL,以将其发送到Apple Watch,但出现两个错误。 这是我的代码: 我在 imageName和 localPath上遇到错误,因为它说: “ lastPathComponent”不可用:在NSURL上使用lastPathComponent。’stringByAppendingPathComponent’不可用:在NSURL上

  • 我有一个方法,它应该从JSON返回不同的对象,这取决于参数中的类类型。我试着根据参数返回一个对象列表,但是我只把LinkedHashMap放入ArrayList。 我搜索了很多,但是在解决方案中,类类型的所有地方都是硬编码的。 有没有一种不用硬代码就能解决这个问题的方法? 我只想传递类类型并通过一个方法获取对象。 当我的对象有关系时,我得到这个例外 无法识别的字段"字段"(类model.orm.部

  • 问题内容: 我对Eli Bendersky提供的示例感到有些惊讶(http://eli.thegreenplace.net/2015/the-scope-of- index-variables-in-pythons-for-loops/ ) 但是,当我想到它时,这是有道理的-Lambda捕获的是对i的引用,而不是i的价值。 因此,解决此问题的方法如下: 看来这样做的原因是,当将i提供给外部lamb

  • 问题内容: 我一直在使用自定义相机,最近我与Swift 3一起升级到了Xcode 8 beta。 但是,我现在收到警告: iOS 10.0中不推荐使用“ AVCaptureStillImageOutput”:改用AVCapturePhotoOutput 由于这是相当新的内容,因此我没有看到太多信息。这是我当前的代码: 我尝试查看,但是我不确定如何使用它。有人知道如何使用吗?谢谢。 问题答案: 更新

  • 这里有一个正则表达式。试试下面的字符串,我面临的问题是,在第一个组之后,每个捕获组的开头都有一个额外的空格。我需要匹配空白,但不需要捕捉它们。 正则表达式: 在上面的链接上查看它会使理解变得更简单。 这些是您可以一个接一个地粘贴到测试字符串区域中的一些字符串: 查看匹配组区域,注意在第1组之后,组之间的前1个空格被捕获。 我想做的是: 对于第一个和第二个捕获组,我希望他们检测到一个后续空间并吸收它