ZBLOG

设置采集的到图像是YUV420p

要在 iOS 中设置相机采集的图像为 YUV 420P 格式(也称为 YUV420 Planar),需要注意,AVCaptureVideoDataOutput 默认支持的一些格式并不直接暴露 YUV 420P 的选项。虽然它可以提供 YUV 数据,但它通常是以不同的方式组织(例如交错或双平面形式)。

不过,我们可以使用 Core Video 框架中的 CVPixelBuffer 来手动处理和转换数据,以便达到 YUV 420P 格式。下面是一个示例代码,展示如何通过相机采集视频数据,并在接收到样本缓冲区后,将其转换为 YUV 420P。

import SwiftUI
import UIKit
import AVFoundation

struct ContentView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> CameraViewController {
        return CameraViewController()
    }

    func updateUIViewController(_ uiViewController: CameraViewController, context: Context) {}
}

class CameraViewController: UIViewController {

    var captureSession: AVCaptureSession!
    var videoOutput: AVCaptureVideoDataOutput!

    override func viewDidLoad() {
        super.viewDidLoad()
        setupCamera()
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // 停止会话
        captureSession?.stopRunning()
    }

    func setupCamera() {
        captureSession = AVCaptureSession()

        guard let camera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {
            print("无法找到摄像头")
            return
        }

        do {
            let input = try AVCaptureDeviceInput(device: camera)
            if captureSession.canAddInput(input) {
                captureSession.addInput(input)
            }

            videoOutput = AVCaptureVideoDataOutput()
            videoOutput.videoSettings = [
                kCVPixelBufferPixelFormatTypeKey as String : kCVPixelFormatType_420YpCbCr8BiPlanarFullRange // 使用双平面格式接收YUV数据
            ]

            videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "videoQueue"))
            
            if captureSession.canAddOutput(videoOutput) {
                captureSession.addOutput(videoOutput)
            }
            
            // 启动会话
            captureSession.startRunning()

        } catch {
            print("Error setting up camera input: \(error)")
        }
    }
}

extension CameraViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
    
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        
        guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }

        // 转换到 YUV420P (planar format),此处简化逻辑,仅作为示例。
        if CVPixelBufferGetPlaneCount(imageBuffer) >= 3 { 
            
            let width = CVPixelBufferGetWidth(imageBuffer)
            let height = CVPixelBufferGetHeight(imageBuffer)

            // 获取Y分量
            let yPlane = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0)!
            
            // 获取U分量 (第二平面)
            let uPlane = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 1)!
            
            // 获取V分量 (第三平面)
            let vPlane = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 2)!

			// 示例:处理 Y、U、V 数据。你可以把它们复制到一个新的内存区域来实现标准的 YUV420P 数据结构

			print("Captured frame of size \(width)x\(height)")
			// 在这里可以进行其他处理,例如将数据发送到某个地方或者保存等操作
		}
	}
}

@main
struct MyApp : App {
	var body: some Scene {
		WindowGroup {
			ContentView()
				.edgesIgnoringSafeArea(.all)
		}
	}
}

注意事项:

  1. YUV 格式:iOS 中,捕获图像时常用的是双平面格式 (kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) 或者其他类似格式。在处理时,你需要确保从每个 plane 中提取出正确的数据,并按照你的需求进行处理。

  2. 内存管理:在实际应用中,你可能还需要考虑对采集到的图像进行缓存、转码或显示等操作,因此务必做好内存管理与性能优化。

  3. 测试设备兼容性:不同型号的 iPhone/iPad 对于相机功能和支持的输出格式可能存在差异,请在实际设备上进行测试。

  4. 进一步处理:如果需要更复杂的转换(比如将数据显示成RGB或其他色彩空间),可能还需要借助 Core Image 或 Metal 等高级框架进行后续处理。


    内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=21257

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?