iOS系统自带的扫码功能(二维码+条形码+识别本地图片)

扫码采用类库:AVFoundation

1、相关权限

1)、需要在info.plist中添加以下权限:Privacy - Camera Usage Description(使用摄像机的权限说明)

2)、权限申请与判断:

查询权限:AVCaptureDevice.authorizationStatus(for: .video)

申请权限:AVCaptureDevice.requestAccess(for: .video)

2、初始化摄像头

// 查找广角摄像头
let deviceDiscovery = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera],
                                                       mediaType: .video,
                                                       position: .back)
guard let device = deviceDiscovery.devices.last else {
    return
}
guard let deviceInput = try? AVCaptureDeviceInput(device: device) else {
    return
}
if sesson.canAddInput(deviceInput) {
    sesson.addInput(deviceInput)
}
// 初始化元数据输出管道,用于识别条码,二维码
let metaDataOutput = AVCaptureMetadataOutput()
metaDataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
if sesson.canAddOutput(metaDataOutput) {
    sesson.addOutput(metaDataOutput)
}

// 设置元数据识别类型 qr:二维码;其他:条形码
metaDataOutput.metadataObjectTypes = [.qr, .ean13, .ean8, .upce, .code39, .code39Mod43, .code93, .code128, .pdf417]

// 初始化视频预览图层
let previewLayer = AVCaptureVideoPreviewLayer(session: sesson)
previewLayer.videoGravity = .resizeAspectFill
previewLayer.frame = view.bounds
view.layer.insertSublayer(previewLayer, at: 0)
// 设置元数据识别区域(只有在该区域内的内容才会被识别)
metaDataOutput.rectOfInterest = scanRect
sesson.startRunning()

3、添加二维码与条形码识别输出管道:

// 初始化元数据输出管道,用于识别条码,二维码
let metaDataOutput = AVCaptureMetadataOutput()
metaDataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
if sesson.canAddOutput(metaDataOutput) {
    sesson.addOutput(metaDataOutput)
}

// 设置元数据识别类型 qr:二维码;其他:条形码
metaDataOutput.metadataObjectTypes = [.qr, .ean13, .ean8, .upce, .code39, .code39Mod43, .code93, .code128, .pdf417]

// 设置元数据识别区域(只有在该区域内的内容才会被识别)
metaDataOutput.rectOfInterest = scanRect

管道回调代理:

extension ScannerViewController: AVCaptureMetadataOutputObjectsDelegate {
    
    public func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        guard metadataObjects.count > 0 else {
            return
        }
        let texts = metadataObjects.compactMap { data -> String? in
            guard let code = data as? AVMetadataMachineReadableCodeObject else {
                return nil
            }
            return code.stringValue // 识别结果
        }
    }
}

以上就是一个完整的扫码功能。

 

接下来就是识别本地的条形码和二维码图片

系统提供两种方法识别二维码:其中用到了Vision库->VNDetectBarcodesRequest

/// 仅仅识别二维码图片
public static func parseQRCode(img: UIImage) -> String? {
    guard let ciimg = CIImage(image: img) else {
        return nil
    }
    let detector = CIDetector(ofType: CIDetectorTypeQRCode,
                              context: nil,
                              options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
    guard let features = detector?.features(in: ciimg) else {
        return nil
    }
    guard let feature = features.first(where: { $0.type == CIFeatureTypeQRCode }) as? CIQRCodeFeature else {
        return nil
    }
    return feature.messageString // 识别结果
}

/// 识别二维码和条形码
public static func parseBarCode(img: UIImage) {
    guard let cgimg = img.cgImage else {
        return
    }
    let request = VNDetectBarcodesRequest { req, err in
        if let error = err {
            print("parseBarCode error: \(error)")
            return
        }
        guard let results = req.results, results.count > 0 else {
            return
        }
        for result in results {
            if let barcode = result as? VNBarcodeObservation, let value = barcode.payloadStringValue {
                
                if barcode.symbology == .qr { // 二维码
                    print("qrcode: \(value)")
                }else { // 条形码
                    print("barcode: \(value), \(barcode.symbology.rawValue)")
                }
                break
            }
        }
    }
    let handler = VNImageRequestHandler(cgImage: cgimg)
    do {
        try handler.perform([request])
    } catch {
        print("parseBarCode error: \(error)")
    }
}

 

posted @ 2022-09-28 16:55  zbblogs  阅读(1929)  评论(0编辑  收藏  举报