因为图像来源是摄像头,所以需要将 CMSampleBuffer 转成 CVPixelBuffer。 我的转换流程是:CVPixelBuffer->CVPixelBuffer->CIImage->CIImage(resized)->CVPixelBuffer。 最后一步 CIImage 转 CVPixelBuffer 是通过 CIContext 渲染完成。 /// resize CVPixelBuffer /// /// - Parameter pixelBuffer: CVPixelBuffer by camera output /// - Returns : CVPixelBuffer with size (299, 299) func resize(pixelBuffer: CVPixelBuffer) -> CVPixelBuffer?
截屏2020-12-08 下午3.22.08.png 如图所示,左边的三帧视频帧是发送给编码器之前的数据,开发者必须将原始图像数据封装为CVPixelBuffer的数据结构,该数据结构是使用VideoToolbox 关于CVPixelBuffer的介绍可以去官方文档的了解。 Apple Developer CVPixelBuffer 官方文档 2、CVPixelBuffer 解析 在这个官方文档的介绍中,CVPixelBuffer的官方解释:是其主内存存储所有像素点数据的一个对象 在AVFoundation回调方法中,它有提供我们的数据其实就是CVPixelBuffer,只不过当时使用的是引用类型CVImageBufferRef,其实就是CVPixelBuffer的另外一个定义。 Camera返回的CVImageBuffer中存储的数据是一个CVPixelBuffer,而经过VideoToolbox编码输出的CMSampleBuffer中存储的数据是一个CMBlockBuffer
我们将演示如何结合使用 DisplayLink、CVPixelBuffer、Core Image,以及如何配合使用 CVMetalTextureCache、Metal。 在下面的示例代码中,我们来添加一个简单的滤镜效果: 后处理 另一种方式是使用 Metal 和自定义的 Metal shader 来处理和渲染 CVPixelBuffer。 我们来简单介绍一下将 CVPixelBuffer 转换为 Metal 纹理的过程: 从 CVPixelBuffer 中获取 IOSurface 对象; 创建一个 MetalTextureDescriptor 3)使用 CoreVideo 和 Metal CVMetalTextureCache 是一种将 CVPixelBuffer 与 Metal 结合使用的简单有效的方法。 CVMetalTextureCache 自动桥接 CVPixelBuffer 和 MetalTexture,从而既简化了代码,又保持了高效。
options: [:]) 请求的结果VNPixelBufferObservation中会封装蒙版图片CVPixelBuffer 如下: open class VNPixelBufferObservation : VNObservation { // 分析出的蒙版数据 open var pixelBuffer: CVPixelBuffer [] { // 创建CIImage实例 let ciImage = CIImage(cvPixelBuffer: result.pixelBuffer) [] { print(result.pixelBuffer) let ciImage = CIImage(cvPixelBuffer: result.pixelBuffer
编码后进行传输、本地预览CMSampleBuffer在开始之前,必须先了解 CMSampleBuffer 的概念,它可以简单理解为媒体数据之外加了一层封装,在视频相关场景下,其可以包含未编码的视频数据(CVPixelBuffer 也可以包含编码过的视频数据(CMBlockBuffer)CMSampleBuffer 组成部分CMTime:图像的时间CMVideoFormatDescription:图像格式的描述CMBlockBuffer or CVPixelBuffer 且该方法被调用的线程,就是之前我们创建的串行队列对应的线程采集到的原始视频数据,存放在 CMSampleBuffer 中,前面的章节也提到,CMSampleBuffer 可以包含未编码的视频数据,存放在 CVPixelBuffer 中,获取 CVPixelBuffer 的代码如下CVPixelBufferRef pixel_buffer = CMSampleBufferGetImageBuffer(sampleBuffer);拿到 CVPixelBuffer 之后,视频采集的环节基本可以告一段落了,CVPixelBuffer 可以拿来做硬件编码、渲染,也可以直接把视频数据提取出来做其他的逻辑从 CVPixelBuffer 中提取数据时需要额外注意
概念介绍 CVPixelBuffer 包含未压缩的像素数据,包括图像宽度、高度等; CVPixelBufferPool CVPixelBuffer的缓冲池,因为CVPixelBuffer的创建和销毁代价很大
2、相关类介绍 CVPixelBuffer: 包含未压缩的像素数据,包括图像宽度、高度等; CVPixelBufferPool: CVPixelBuffer的缓冲池,因为CVPixelBuffer的创建和销毁代价很大 可以包含已压缩数据(CMBlockBuffer)或未压缩数据(CVPixelBuffer)及相关描述信息 3、AVKit 使用AVSampleBufferDisplayLayer显示H.264码流 ?
VNCoreMLModel(for: mlModel) self.inputSize = inputSize } func encode(_ image: CVPixelBuffer request.imageCropAndScaleOption = .centerCrop // 执行请求 let handler = VNImageRequestHandler(cvPixelBuffer [request]) // 获取并返回特征向量 // ... } private func resize(_ image: CVPixelBuffer , to size: CGSize) -> CVPixelBuffer { // 硬件加速的图像缩放 // ... } private func normalize(_ image: CVPixelBuffer) -> CVPixelBuffer { // 图像归一化处理 // ... }
kCVPixelBufferMetalCompatibilityKey,无脑设置为 truekCVPixelBufferIOSurfacePropertiesKey 要设置成非 NULL 的值,简单来说能够让编码器更高效的读取 CVPixelBuffer kCFBooleanFalse);提前准备编码器status = VTCompressionSessionPrepareToEncodeFrames(encode_session_);进行编码每帧开始编码之前要准备参数数据源 CVPixelBuffer ,存储的是未编码的图像数据,有 2 种获取方式从摄像头采集流程可以直接拿到,可以参考文章:音视频基础能力之 iOS 视频篇(一):视频采集读取内存中的数据,然后构造 CVPixelBuffer,将数据拷入 CVPixelBuffer 的地址,读取本地文件时常用时间戳 CMTime,表示当前视频帧的展示时间,由 2 部分组成,value(时间值)和 timescale(时间刻度)timescale 表示把
CVPixelBuffer 获取地址需要先调用 CVPixelBufferLockBaseAddress 加锁,使用完成再调用 CVPixelBufferUnlockBaseAddress 解锁。 2、YUV(NV12) 转换为 BGRA 在 iOS 中要将 NV12 格式的 CVPixelBuffer 保存为 UIImage 时,例如视频抽帧等需求,需要先将 NV12 转换 BGRA。 CVPixelBuffer 获取地址需要先调用 CVPixelBufferLockBaseAddress 加锁,使用完成再调用 CVPixelBufferUnlockBaseAddress 解锁。 3、BGRA 转换为 YUV(NV12) 当 UIImage 转换为 NV12 格式的 CVPixelBuffer时,例如图片与视频混排需要将图片转换为 NV12 进行编码,需要先将 BGRA 转换 NV12 CVPixelBuffer 获取地址需要先调用 CVPixelBufferLockBaseAddress 加锁,使用完成再调用 CVPixelBufferUnlockBaseAddress 解锁。
// 从 CMSampleBuffer 获取 CVImageBuffer(也是 CVPixelBuffer)。 CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); // 锁定 CVPixelBuffer size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); // 获取 CVPixelBuffer 的宽高。 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); // 基于 CVPixelBuffer 的数据创建绘制 bitmap CGImageRef quartzImage = CGBitmapContextCreateImage(context); // 解锁 CVPixelBuffer。
: @available(iOS 11.0, *) open class VNImageRequestHandler : NSObject { // 构造方法 public init(cvPixelBuffer pixelBuffer: CVPixelBuffer, options: [VNImageOption : Any] = [:]) public init(cvPixelBuffer pixelBuffer : CVPixelBuffer, orientation: CGImagePropertyOrientation, options: [VNImageOption : Any] = [:]) public
func pixelBuffer(from image: UIImage) -> CVPixelBuffer? kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary var pixelBuffer : CVPixelBuffer 现在,我们将newImage转换成为CVPixelBuffer。如果你对CVPixelBuffer不熟悉,它基本上是一个图像缓冲区,用来将像素存于主要记忆体中。 let ciImage = CIImage(cvPixelBuffer: predictionOutput.stylizedImage) let tempContext =
此方法输入CVPixelBuffer(一个包含图像的对象)并返回一个TinyYOLOOutput对象。 这个类的相关部分是MLMultiArray对象。它包含13×13网格的边框预测。 这意味着我们需要将输入图像存入CVPixelBuffer这个缓冲区对象中,并将这个缓冲区的大小调整到416×416像素,否则Core ML将不会接受它。 ()功能是,把CMSampleBuffer(包含相机像素数据的缓冲区)对象,转换为CVPixelBuffer。 现在我们有一个CVPixelBuffer416×416的图像,我们可以预测这个图像了。 注意: 另一种调整图像大小的方法是,调用Accelerate框架中vImageScale_ARGB8888()。 步骤3:预测 使用Core ML,输入图像必须是一个CVPixelBuffer,但Metal需要MTLTexture。
63 var ciImage = CIImage(cvPixelBuffer:imgBuffer) 64 65 self.filter.setValue(ciImage, forKey: kCIInputImageKey
上面这两个类接口写完后,就可以整理输入数据为CvPixelBuffer,然后通过获取模型描述MLModelDescription得到输入名称,根据输入名称创建MLModelInput,预测,然后再根据MLModelOutput
kCVPixelBufferMetalCompatibilityKey,无脑设置为 truekCVPixelBufferIOSurfacePropertiesKey 要设置成非 NULL 的值,简单来说能够让解码器更高效的与 CVPixelBuffer block_buffer);进行解码,iOS 9 开始支持用 block 处理解码回调,比起静态函数方便了很多,解码后的数据存储在 CVImageBufferRef 当中,CVImageBufferRef 跟 CVPixelBuffer
kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary var pixelBuffer : CVPixelBuffer 第 18-23 行: 我们把 newImage 转换为 CVPixelBuffer。 给对于 CVPixelBuffer 不熟悉的人, CVPixelBuffers 是一个将像数(Pixcel)存在主记忆体里的图像缓冲器。
exifOrientation = exifOrientationFromDeviceOrientation() let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer
我们使用硬件采集到的数据就是CMSampleBufferRef,这个数据很特殊就如上面占比最大的快一样:CMBlockBuffer CVPixelBuffer 其中CMBlockBuffer CVPixelBuffer