Converting CMSampleBuffer to Data and Data To UIImage 不起作用,为什么
Converting CMSampleBuffer to Data and Data To UIImage does not work, why
为了测试,我们尝试使用 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
}
}
您应该检查 UIImage
构造函数的文档和数据。我很确定你不能简单地用你正在做的原始像素数据来构造它。此构造函数可能需要 png 或 jpeg 数据。 UIImage
实例上类似 pngData()
方法的反转。要从原始数据构建图像,您可以使用低一点 API。 This 看起来很有希望,但您需要将其从 objective C 移植到 Swift 或找到类似的解决方案。
您会看到在原始数据旁边需要多个参数,例如宽度、高度和像素格式。图像数据并不那么简单。因此,要重建它,您还需要附加此数据。由于您想将其发送到另一台设备,这可能并不容易。
也许一开始最好将其转换为 JSON。只需使用 base 64 编码的字符串来转换 to/from 字符串和数据:
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
我希望这能解决您的问题,但问题是您实际上可能需要的数据不仅仅是宽度和高度。
好吧,我找到了一种方法,虽然有点粗糙。
我用
创建了数据
let data = testImage.pngData() as Data?
并流式传输此数据并使用
将其转换为 UIImage
let image = UIImage(data:Data)
但是为了做到这一点,我首先将 CMSampleBuffer 转换为 UIImage。
为了测试,我们尝试使用 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
}
}
您应该检查 UIImage
构造函数的文档和数据。我很确定你不能简单地用你正在做的原始像素数据来构造它。此构造函数可能需要 png 或 jpeg 数据。 UIImage
实例上类似 pngData()
方法的反转。要从原始数据构建图像,您可以使用低一点 API。 This 看起来很有希望,但您需要将其从 objective C 移植到 Swift 或找到类似的解决方案。
您会看到在原始数据旁边需要多个参数,例如宽度、高度和像素格式。图像数据并不那么简单。因此,要重建它,您还需要附加此数据。由于您想将其发送到另一台设备,这可能并不容易。
也许一开始最好将其转换为 JSON。只需使用 base 64 编码的字符串来转换 to/from 字符串和数据:
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
我希望这能解决您的问题,但问题是您实际上可能需要的数据不仅仅是宽度和高度。
好吧,我找到了一种方法,虽然有点粗糙。
我用
创建了数据 let data = testImage.pngData() as Data?
并流式传输此数据并使用
将其转换为 UIImage let image = UIImage(data:Data)
但是为了做到这一点,我首先将 CMSampleBuffer 转换为 UIImage。