使用实时摄像头预览的iOS对象检测(六)

目录

介绍

应用布局

捕获相机反馈

相机反馈预览

完成相机预览配置

结论


总目录 

将ONNX对象检测模型转换为iOS Core ML(一)

在这里,我们将开始在我们的iOS应用程序上工作。在此应用中实施对象检测之前,我们需要处理视频捕获。

介绍

本系列假定您熟悉PythonCondaONNX,并且具有使用Xcode开发iOS应用程序的经验。我们将使用macOS 10.15 +Xcode 11.7+iOS 13+运行代码。

iOS应用程序中处理实时摄像头可能有点让人不知所措。我们将尝试使事情变得尽可能简单,更多地关注代码的可读性而不是性能。另外,为了减少要考虑的缩放选项的数量,我们将使用固定的纵向方向。

本文的代码最初是受此应用程序启发的。您也可以查看上一篇文章

该演示应用程序是使用Xcode 11.7编写的,应该可以在iOS 7或更高版本,iOS 13或更高版本的任何iPhone上正常运行。

应用布局

从故事板的角度来看,我们的应用程序非常简单。它包含一个视图控制器,上面只有一个预览视图控件。我们将使用此视图作为实时摄像机馈送。

捕获相机反馈

负责处理摄像机输入和视频预览的所有代码都在Controllers/VideoCapture类中,它实现了AVCaptureVideoDataOutputSampleBufferDelegate

以下成员存储其设置:

private let captureSession = AVCaptureSession()
private var videoPreviewLayer: AVCaptureVideoPreviewLayer! = nil
private let videoDataOutput = AVCaptureVideoDataOutput()
private let videoDataOutputQueue = DispatchQueue(label: "VideoDataOutput", qos: .userInitiated, attributes: [], autoreleaseFrequency: .workItem)
private var videoFrameSize: CGSize = .zero

由类构造函数调用的setupPreview方法将所有元素绑定在一起。

首先,它获得第一个可用的后置摄像头作为输入设备:

var deviceInput: AVCaptureDeviceInput!
        
let videoDevice = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .back).devices.first
do {

接下来,它开始配置过程,从相机强制640 x 480帧。对于我们的YOLO v2模型而言,这样的分辨率就足够了,因为它始终使用缩放为416 x 416像素的图像。请注意,由于固定的纵向方向,我们将48 x 640作为输入尺寸存储在videoFrameSize 变量中,以备将来使用:

captureSession.beginConfiguration()
captureSession.sessionPreset = .vga640x480
self.videoFrameSize = CGSize(width: 480, height: 640)

配置继续为要处理的帧建立单个元素队列(alwaysDiscardLateVideoFrames标志)。这意味着在完成当前帧的处理之前,后续帧将被丢弃。

captureSession.addInput(deviceInput)
if captureSession.canAddOutput(videoDataOutput) {
    captureSession.addOutput(videoDataOutput)
    videoDataOutput.alwaysDiscardsLateVideoFrames = true
    videoDataOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)]
    videoDataOutput.setSampleBufferDelegate(self, queue: videoDataOutputQueue)
} else {
    print("Could not add video data output to the session")
    captureSession.commitConfiguration()
    return
}

let captureConnection = videoDataOutput.connection(with: .video)
captureConnection?.isEnabled = true
captureConnection?.videoOrientation = .portrait
captureSession.commitConfiguration()

固定的肖像方向将使处理和绘制对象检测的预测更加容易。

相机反馈预览

在接下来的步骤中,setup方法将创建一个videoPreviewLayer实例并将其作为子层添加到我们的应用程序视图中(如下viewLayer所示):

self.videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
self.videoPreviewLayer.videoGravity = .resizeAspectFill
        
videoPreviewLayer.frame = viewLayer.bounds
viewLayer.addSublayer(videoPreviewLayer)

videoGravity使用.resizeAspectFill值可确保视频填满整个可用屏幕。由于没有iPhone的屏幕比例等于1,331(由640 x 480分辨率推断),因此在纵向视图中,每一帧都将在两侧被裁剪。如果我们改用.resizeAspect,整个框架将是可见的,但在其上方和下方都带有空条。

完成相机预览配置

VideoCapture类中,我们还需要三种方法:

public func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    // We will handle frame(s) here
}

public func captureOutput(_ captureOutput: AVCaptureOutput, didDrop didDropSampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    // Dropped frame(s) can be handled here
}

public func startCapture() {
    if !captureSession.isRunning {
        captureSession.startRunning()
    }
}

前两种方法是必须的,因为它们在AVCaptureVideoDataOutputSampleBufferDelegate中定义,而我们的VideoCapture 类实现了它。现在,空的实现是可以的。我们需要最后一种方法,startCapture,开始处理视频反馈。

使用完整的VideoCapture实现从我们的Main.storyboard链接到cameraView,并用实例变量来存储所创建的VideoCapture实例,我们在主ViewControllerviewDidLoad方法中创建一个新的VideoCapture实例:

self.videoCapture = VideoCapture(self.cameraView.layer)
self.videoCapture.startCapture()

结论

现在,我们有一个简单的iOS应用程序,该应用程序配置为捕获和预览实时摄像机流。在本系列的下一篇(也是最后一篇)中,我们将扩展应用程序以使用我们的YOLO v2模型进行对象检测。

https://www.codeproject.com/Articles/5286804/iOS-Object-Detection-with-Live-Camera-Preview

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值