当前位置: 首页 > 面试题库 >

如何将实时摄像机预览添加到UIView

纪枫
2023-03-14
问题内容

我遇到问题,我想在UIView边界内解决,有什么
办法可以将Camera Preview添加到UIView吗?并在
UIView 顶部添加其他内容(按钮,标签等)?

我尝试使用AVFoundation框架,但没有足够的文档
的斯威夫特。


问题答案:

更新为SWIFT 5
您可以尝试如下操作:

import UIKit
import AVFoundation

class ViewController: UIViewController{
    var previewView : UIView!
    var boxView:UIView!
    let myButton: UIButton = UIButton()

    //Camera Capture requiered properties
    var videoDataOutput: AVCaptureVideoDataOutput!
    var videoDataOutputQueue: DispatchQueue!
    var previewLayer:AVCaptureVideoPreviewLayer!
    var captureDevice : AVCaptureDevice!
    let session = AVCaptureSession()

    override func viewDidLoad() {
        super.viewDidLoad()
        previewView = UIView(frame: CGRect(x: 0,
                                           y: 0,
                                           width: UIScreen.main.bounds.size.width,
                                           height: UIScreen.main.bounds.size.height))
        previewView.contentMode = UIView.ContentMode.scaleAspectFit
        view.addSubview(previewView)

        //Add a view on top of the cameras' view
        boxView = UIView(frame: self.view.frame)

        myButton.frame = CGRect(x: 0, y: 0, width: 200, height: 40)
        myButton.backgroundColor = UIColor.red
        myButton.layer.masksToBounds = true
        myButton.setTitle("press me", for: .normal)
        myButton.setTitleColor(UIColor.white, for: .normal)
        myButton.layer.cornerRadius = 20.0
        myButton.layer.position = CGPoint(x: self.view.frame.width/2, y:200)
        myButton.addTarget(self, action: #selector(self.onClickMyButton(sender:)), for: .touchUpInside)

        view.addSubview(boxView)
        view.addSubview(myButton)

        self.setupAVCapture()
    }

    override var shouldAutorotate: Bool {
        if (UIDevice.current.orientation == UIDeviceOrientation.landscapeLeft ||
        UIDevice.current.orientation == UIDeviceOrientation.landscapeRight ||
        UIDevice.current.orientation == UIDeviceOrientation.unknown) {
            return false
        }
        else {
            return true
        }
    }

    @objc func onClickMyButton(sender: UIButton){
        print("button pressed")
    }
}


// AVCaptureVideoDataOutputSampleBufferDelegate protocol and related methods
extension ViewController:  AVCaptureVideoDataOutputSampleBufferDelegate{
     func setupAVCapture(){
        session.sessionPreset = AVCaptureSession.Preset.vga640x480
        guard let device = AVCaptureDevice
        .default(AVCaptureDevice.DeviceType.builtInWideAngleCamera, 
                 for: .video,
                 position: AVCaptureDevice.Position.back) else {
                            return
        }
        captureDevice = device
        beginSession()
    }

    func beginSession(){
        var deviceInput: AVCaptureDeviceInput!

        do {
            deviceInput = try AVCaptureDeviceInput(device: captureDevice)
            guard deviceInput != nil else {
                print("error: cant get deviceInput")
                return
            }

            if self.session.canAddInput(deviceInput){
                self.session.addInput(deviceInput)
            }

            videoDataOutput = AVCaptureVideoDataOutput()
            videoDataOutput.alwaysDiscardsLateVideoFrames=true
            videoDataOutputQueue = DispatchQueue(label: "VideoDataOutputQueue")
            videoDataOutput.setSampleBufferDelegate(self, queue:self.videoDataOutputQueue)

            if session.canAddOutput(self.videoDataOutput){
                session.addOutput(self.videoDataOutput)
            }

            videoDataOutput.connection(with: .video)?.isEnabled = true

            previewLayer = AVCaptureVideoPreviewLayer(session: self.session)
            previewLayer.videoGravity = AVLayerVideoGravity.resizeAspect

            let rootLayer :CALayer = self.previewView.layer
            rootLayer.masksToBounds=true
            previewLayer.frame = rootLayer.bounds
            rootLayer.addSublayer(self.previewLayer)
            session.startRunning()
        } catch let error as NSError {
            deviceInput = nil
            print("error: \(error.localizedDescription)")
        }
    }

    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        // do stuff here
    }

    // clean up AVCapture
    func stopCamera(){
        session.stopRunning()
    }

}

在这里,我使用一个UIView称为PreviewView的相机来启动摄像机,然后在PreviewView上方添加一个名为boxView 的
新UIView控件。我添加一个UIButton到
boxView

重要

请记住,在iOS 10及更高版本中,您需要先征求用户的
许可才能访问相机。您可以通过向应用程序中添加
用途密钥Info.plist以及目的字符串来完成此操作,
因为如果您未能声明用途,则应用程序在首次
进行访问时将崩溃。



 类似资料:
  • 问题内容: 我是Python和Matplotlib的新手。我的计算机连接到两个USB摄像机,我打算使用matplotlib中的subplot(1,2,1)和subplot(1,2,2)来按时间序列绘制来自两个摄像机的帧。当我用代码执行此操作时,我要么只绘制一帧,要么在绘制区域中出现黑屏。 我的代码如下所示 问题答案: 互动模式 在matplotlib中更新图的一种方法是使用交互模式()。然后,您不

  • 主要内容:摄像机弹簧臂组件在这一节中,我们需要添加两个组件分别是摄像机弹簧臂组件和摄像机组件。 摄像机弹簧臂组件 摄像机弹簧臂组件,可以想象成是我们的手臂和手。手拿着摄像机,当我们想移动摄像机的时候,我们移动的是我们的手臂而不是摄像机。 1) 打开VS编辑器,在PlayingCharacter.h文件添加摄像机弹簧组件和摄像机组件。 2) 在CPP文件中,添加两个头文件和在构造函数中注册这两个组件。 3) 由于我们的骨骼模

  • 我正在为我的Android应用程序使用此相机预览应用程序。 我想要全屏幕的相机预览。因此,我使用Android API中的示例尝试将预览设置为全屏。这就是我试图做到的: 我使用相对布局作为我的布局。我的布局设置如下: 我仍然无法在整个屏幕上预览我的相机。我想知道如何预览整个屏幕。

  • 可以在 Adobe Bridge 的“预览”面板中,以全屏预览和审阅模式预览图像。“预览”面板会显示多达九张缩览图图像供您快速比较。全屏预览会以全屏方式显示图像。审阅模式以全屏视图显示图像,允许您在图像中导航,优化选择,标记、旋转图像和给图像评级,以及在 Camera Raw 中打开图像。 以幻灯片放映的方式查看图像 使用“幻灯片放映”命令可以全屏幕幻灯片放映的方式查看缩览图。在处理一个文件夹中所

  • 我一直在开发一个摄像头应用程序,所有的工作都是拍摄和保存照片。但我希望在拍摄照片时显示的Imageview能够保存在实际拍摄的照片中。可能吗? 现在,我一直试图让图像视图与我绘制相机预览的布局相同。 我想,也许如果它画在与相机相同的视图上,那么它也会看到图像和照片。 有没有人知道这是否可能,或者我必须采取另一种方法?如果是这样,链接到其他解决方案如何做到这一点将不胜感激:) 谢谢 编辑:我一直遵循

  • 我正在准备一个小的Android应用程序,捕捉照片和录音从用户。类似用户会用他的相机拍一张照片,然后在观看该照片时添加音频评论。