如何在 SwiftUI 中显示 AVCaptureVideoPreviewLayer
How to show a AVCaptureVideoPreviewLayer in SwiftUI
在 swift 的早期版本中,您在 ViewController 中创建一个 AVCaptureVideoPreviewLayer 并使用 view.layer.addSublayer(previewLayer) 将其添加到默认视图。
这在 SwiftUI ContentView 中是如何完成的? None SwiftUI 中的视图类型似乎有一个 addSublayer。没有文字("Hello World").layer.addSublayer.....
我尝试将 previewLayer 添加到 ContentView 中的各种视图
import Foundation
import AVFoundation
import Combine
import SwiftUI
class Scanner: NSObject, AVCaptureMetadataOutputObjectsDelegate, ObservableObject {
@Published var captureSession: AVCaptureSession!
@Published var previewLayer: AVCaptureVideoPreviewLayer!
@Published var previewView: UIView
override init() {
captureSession = AVCaptureSession()
previewLayer = nil
//previewView = UIView()
super.init()
guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else { return }
let videoInput: AVCaptureDeviceInput
do {
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
} catch {
return
}
if (captureSession.canAddInput(videoInput)) {
captureSession.addInput(videoInput)
} else {
failed()
return
}
let metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput)) {
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = [.qr]
} else {
failed()
return
}
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.videoGravity = .resizeAspectFill
//previewView.layer.addSublayer(previewLayer)
}
import SwiftUI
import Combine
struct ContentView: View {
@ObservedObject var scanner = Scanner()
var body: some View {
//Text("Hello World").layer.addSublayer(scanner.previewLayer)
//Text("")
Text("HelloWorld")//.addSublayer(scanner.previewLayer))
//.previewLayout(scanner.previewLayer)
.layer.addSublayer(scanner.previewLayer)
//.previewLayout(scanner.previewLayer)
//.overlay(scanner.previewView)
scanner.captureSession.startRunning()
}
}
尝试添加 previewLayer 时出现编译错误
不能直接添加图层。这就是为什么人们目前像许多其他东西一样将整个东西装在 UIView(Controller)Representable
里面。
我设法将捕获的图像放到 SwiftUI 视图中
在视图组件中,简单的放一个
Image(uiImage: cameraManager.capturedImage)
而对于CameraManager
,使用帧捕获功能,将样本缓冲区转换为UIImage后,只需将capturedImage
设置为uiImage
。
(参考https://medium.com/ios-os-x-development/ios-camera-frames-extraction-d2c0f80ed05a)
class CameraManager: NSObject, ObservableObject{
...
@Published public var capturedImage: UIImage = UIImage()
...
}
extension CameraManager: AVCaptureVideoDataOutputSampleBufferDelegate {
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
// transforming sample buffer to UIImage
guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
let ciImage = CIImage(cvPixelBuffer: imageBuffer)
let context = CIContext()
guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else { return }
let uiImage = UIImage(cgImage: cgImage)
// publishing changes to the main thread
DispatchQueue.main.async {
self.capturedImage = uiImage
}
}
}
我本来打算把每一帧都抓下来做后期图像处理的,虽然现在可以预览了,但不知道加入计算机视觉算法后,会不会影响抓帧。到此为止,感觉运行模型会在另一个线程,所以...
嗯,欢迎评论
在 swift 的早期版本中,您在 ViewController 中创建一个 AVCaptureVideoPreviewLayer 并使用 view.layer.addSublayer(previewLayer) 将其添加到默认视图。
这在 SwiftUI ContentView 中是如何完成的? None SwiftUI 中的视图类型似乎有一个 addSublayer。没有文字("Hello World").layer.addSublayer.....
我尝试将 previewLayer 添加到 ContentView 中的各种视图
import Foundation
import AVFoundation
import Combine
import SwiftUI
class Scanner: NSObject, AVCaptureMetadataOutputObjectsDelegate, ObservableObject {
@Published var captureSession: AVCaptureSession!
@Published var previewLayer: AVCaptureVideoPreviewLayer!
@Published var previewView: UIView
override init() {
captureSession = AVCaptureSession()
previewLayer = nil
//previewView = UIView()
super.init()
guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else { return }
let videoInput: AVCaptureDeviceInput
do {
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
} catch {
return
}
if (captureSession.canAddInput(videoInput)) {
captureSession.addInput(videoInput)
} else {
failed()
return
}
let metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput)) {
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = [.qr]
} else {
failed()
return
}
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.videoGravity = .resizeAspectFill
//previewView.layer.addSublayer(previewLayer)
}
import SwiftUI
import Combine
struct ContentView: View {
@ObservedObject var scanner = Scanner()
var body: some View {
//Text("Hello World").layer.addSublayer(scanner.previewLayer)
//Text("")
Text("HelloWorld")//.addSublayer(scanner.previewLayer))
//.previewLayout(scanner.previewLayer)
.layer.addSublayer(scanner.previewLayer)
//.previewLayout(scanner.previewLayer)
//.overlay(scanner.previewView)
scanner.captureSession.startRunning()
}
}
尝试添加 previewLayer 时出现编译错误
不能直接添加图层。这就是为什么人们目前像许多其他东西一样将整个东西装在 UIView(Controller)Representable
里面。
我设法将捕获的图像放到 SwiftUI 视图中
在视图组件中,简单的放一个
Image(uiImage: cameraManager.capturedImage)
而对于CameraManager
,使用帧捕获功能,将样本缓冲区转换为UIImage后,只需将capturedImage
设置为uiImage
。
(参考https://medium.com/ios-os-x-development/ios-camera-frames-extraction-d2c0f80ed05a)
class CameraManager: NSObject, ObservableObject{
...
@Published public var capturedImage: UIImage = UIImage()
...
}
extension CameraManager: AVCaptureVideoDataOutputSampleBufferDelegate {
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
// transforming sample buffer to UIImage
guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
let ciImage = CIImage(cvPixelBuffer: imageBuffer)
let context = CIContext()
guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else { return }
let uiImage = UIImage(cgImage: cgImage)
// publishing changes to the main thread
DispatchQueue.main.async {
self.capturedImage = uiImage
}
}
}
我本来打算把每一帧都抓下来做后期图像处理的,虽然现在可以预览了,但不知道加入计算机视觉算法后,会不会影响抓帧。到此为止,感觉运行模型会在另一个线程,所以...
嗯,欢迎评论