I am following a tutorial about how to use the Vision framework to scan a barcode, and I want to scan a barcode only with a specific square in the center of the screen like this.
This is my code setting capture output add output and output.
import UIKit
import Vision
import AVFoundation
class ViewController: UIViewController {
// MARK: - Private Variables
var captureSession = AVCaptureSession()
// TODO: Make VNDetectBarcodesRequest variable
lazy var detectBarcodeRequest = VNDetectBarcodesRequest { request, error in
guard error == nil else {
print("Barcode error \(error?.localizedDescription ?? "")")
return
}
self.processClassification(request)
}
// MARK: - Override Functions
override func viewDidLoad() {
super.viewDidLoad()
checkPermissions()
setupCameraLiveView()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// TODO: Stop Session
captureSession.stopRunning()
}
}
handle output
extension ViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
// TODO: Live Vision
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
let imageRequestHandler = VNImageRequestHandler(
cvPixelBuffer: pixelBuffer,
orientation: .right)
do {
try imageRequestHandler.perform([detectBarcodeRequest])
} catch {
print(error)
}
}
}
Check permission, add input output
extension ViewController {
// MARK: - Camera
private func checkPermissions() {
// TODO: Checking permissions
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { granted in
if !granted {
print("Please open Settings and grant permission for this app to use your camera.")
}
}
case .denied, .restricted:
print("Please open Settings and grant permission for this app to use your camera.")
default:
return
}
}
private func setupCameraLiveView() {
// TODO: Setup captureSession
captureSession.sessionPreset = .hd1280x720
// TODO: Add input
let videoDevice = AVCaptureDevice
.default(.builtInWideAngleCamera, for: .video, position: .back)
guard
let device = videoDevice,
let videoDeviceInput = try? AVCaptureDeviceInput(device: device),
captureSession.canAddInput(videoDeviceInput) else {
print("There seems to be a problem with the camera on your device.")
return
}
captureSession.addInput(videoDeviceInput)
// TODO: Add output
let captureOutput = AVCaptureVideoDataOutput()
// TODO: Set video sample rate
captureOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32BGRA)]
captureOutput.setSampleBufferDelegate(self, queue: DispatchQueue.global(qos: DispatchQoS.QoSClass.default))
captureSession.addOutput(captureOutput)
configurePreviewLayer()
// TODO: Run session
captureSession.startRunning()
}
// MARK: - Vision
func processClassification(_ request: VNRequest) {
// TODO: Main logic
guard let barcodes = request.results else { return }
DispatchQueue.main.async { [self] in
if captureSession.isRunning {
view.layer.sublayers?.removeSubrange(1...)
for barcode in barcodes {
guard
// TODO: Check for QR Code symbology and confidence score
let potentialQRCode = barcode as? VNBarcodeObservation,
potentialQRCode.symbology == .QR
else { return }
print("your value: \(potentialQRCode.payloadStringValue ?? "")")
}
}
}
}
}
config preview layer
extension ViewController {
private func configurePreviewLayer() {
let cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
cameraPreviewLayer.videoGravity = .resizeAspectFill
cameraPreviewLayer.connection?.videoOrientation = .portrait
cameraPreviewLayer.frame = view.frame
view.layer.insertSublayer(cameraPreviewLayer, at: 0)
}
}