【问题标题】:Converting CMSampleBuffer to Data and Data To UIImage does not work, why将 CMSampleBuffer 转换为 Data 和 Data To UIImage 不起作用,为什么
【发布时间】:2018-11-09 10:04:24
【问题描述】:

为了测试,我们尝试使用具有以下功能的 Swift 4 将 CMSampleBuffer 从捕获输出转换为数据。

获得数据后,我们将此帧数据转换为 UIImage,它返回 nil。我们无法获取 UIImage。

我们进行此测试是因为我们最终会将数据发送到其他设备以获取图像。

但我们还无法从数据中获取同一设备上的图像。

我们是否遗漏了什么。

PS:我们将此测试的 FPS 降低到 1。

func captureOutput(_ output: AVCaptureOutput,
                   didOutput sampleBuffer: CMSampleBuffer,
                   from connection: AVCaptureConnection) {

   func frameData() -> (Data) {

        let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)

        CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))

        let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!)
        let height = CVPixelBufferGetHeight(imageBuffer!)
        let src_buff = CVPixelBufferGetBaseAddress(imageBuffer!)

        let data = Data(bytes: src_buff!, count: bytesPerRow * height)


        CVPixelBufferUnlockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))


            return (data)

    }

       DispatchQueue.main.async {
         let data = frameData()
         guard let image = UIImage(data) else {return}
         self.myImageView.image = image
     }



 }    

【问题讨论】:

    标签: ios swift4


    【解决方案1】:

    您应该检查UIImage 构造函数的文档和数据。我很确定您不能像您正在做的那样简单地使用原始像素数据来构建它。此构造函数可能需要 png 或 jpeg 数据。与UIImage 实例上的pngData() 方法相反。要从原始数据构建图像,您可以使用更低的 API。 This 看起来很有希望,但您需要将其从 Objective C 移植到 Swift 或找到类似的解决方案。

    您会看到除了原始数据(如宽度、高度和像素格式)之外还需要多个参数。图像数据并非如此简单。因此,要重建它,您还需要附加这些数据。而且由于您想将其发送到另一台设备,这可能并不容易。

    也许一开始最好将其转换为 JSON。只需使用 base 64 编码的字符串来转换字符串和数据:

    let dataInstance = Data(base64Encoded: stringInstance)
    let stringInstance = dataInstance.base64EncodedString()
    

    所以现在你可以像这样构造一个字典:

    let imageJSONDescriptor: [String: Any] = [
        "width": imageWidth,
        "height": imageHeight,
        "rawRGBAData": stringInstance
    ]
    

    然后创建 JSON 数据

    let JSONData = try! JSONSerialization.data(withJSONObject: imageJSONDescriptor, options: .prettyPrinted
    

    另一方面,一旦您收到 JSON 数据,您需要将其转换回字典

    imageJSONDescriptor = (try! JSONSerialization.jsonObject(with: JSONData, options: .allowFragments)) as! [String: Any]
    

    并获取值

    let imageWidth = imageJSONDescriptor["width"] as! Int
    let imageHeight = imageJSONDescriptor["height"] as! Int
    stringInstance = imageJSONDescriptor["rawRGBAData"] as! String
    

    我希望这可以解决您的问题,但问题是您实际上可能需要更多的数据,而不仅仅是宽度和高度。

    【讨论】:

    • 在文档中它说 UIImage(data:Data) 可以返回图像或 nil。如果无法使用提供的数据初始化图像,则返回 nil。所以我们应该能够以某种方式在 Data 中获取图像信息。因此我们在数据创建方面遇到了问题?
    • 我还可以将图像转换为字符串数据并将其作为 JSON 发送到其他设备,然后在该远程设备上将字符串数据转换为 UIImage。目前我正在尝试直播。
    • @Hope 是的,您使用的数据不提供图像信息。图像信息是样本缓冲区的一部分,但您创建的数据仅包含原始像素数据,不足以重建图像。因此,你得到零。正如我所见,您已经发现可以使用一些标准格式,其中包括(像素数据和元数据),例如 png 或 jpeg。因此,数据创建没有问题,您只是缺少重建图像所需的信息。
    【解决方案2】:

    不过我找到了一种方法,它有点粗糙。

    我用

    创建了数据
      let data = testImage.pngData() as Data?
    

    并将这些数据流式传输并使用

    将其转换为 UIImage
      let image = UIImage(data:Data)
    

    但要做到这一点,我首先将 CMSampleBuffer 转换为 UIImage。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-02
      • 2011-05-28
      • 2020-03-04
      • 2022-01-14
      • 1970-01-01
      相关资源
      最近更新 更多