You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中通过摄像头扫描数字的实现方法求指导(非条码扫描)

当然有办法!我之前帮不少开发者解决过类似需求——不用局限在条码扫描库上,下面给你几个Swift开发里实用的方案:

方案一:苹果原生Core ML + Vision框架(首推)

这是最贴合iOS生态的方案,不需要依赖第三方库,性能稳定还能享受苹果的系统优化,不管是印刷体还是手写数字都能搞定。

  • 第一步:准备数字识别模型
    如果你要识别印刷体数字,Vision框架自带的文字识别能力就够用;如果是手写数字,你可以用苹果的Create ML工具自己训练模型——上手超简单,导入MNIST这类手写数字数据集,点几下就能生成Core ML格式的模型,不用写复杂的训练代码。

  • 第二步:用Vision处理摄像头流
    核心是通过AVFoundation获取摄像头的实时帧,再交给Vision做识别。这里给你一段针对印刷体数字的示例代码:

    import UIKit
    import AVFoundation
    import Vision
    
    class CameraDigitScanner: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
        private let captureSession = AVCaptureSession()
        private var previewLayer: AVCaptureVideoPreviewLayer!
        private let textRecognitionRequest = VNRecognizeTextRequest(completionHandler: handleTextRecognition)
    
        override func viewDidLoad() {
            super.viewDidLoad()
            setupCameraSession()
        }
    
        private func setupCameraSession() {
            // 配置后置摄像头输入
            guard let cameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {
                fatalError("无法访问后置摄像头")
            }
            guard let cameraInput = try? AVCaptureDeviceInput(device: cameraDevice) else {
                fatalError("无法创建摄像头输入")
            }
            captureSession.addInput(cameraInput)
    
            // 配置视频输出,实时处理每一帧
            let videoOutput = AVCaptureVideoDataOutput()
            videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "camera-processing-queue"))
            captureSession.addOutput(videoOutput)
    
            // 添加预览层,让用户看到摄像头画面
            previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
            previewLayer.frame = view.bounds
            previewLayer.videoGravity = .resizeAspectFill
            view.layer.addSublayer(previewLayer)
    
            // 启动会话
            captureSession.startRunning()
        }
    
        func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
            guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
    
            // 配置识别请求:只识别数字,提升速度和准确率
            textRecognitionRequest.recognitionLevel = .fast
            textRecognitionRequest.recognitionLanguages = ["en-US"]
            textRecognitionRequest.customWords = ["0","1","2","3","4","5","6","7","8","9"]
            let requestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:])
    
            do {
                try requestHandler.perform([textRecognitionRequest])
            } catch {
                print("识别出错:\(error.localizedDescription)")
            }
        }
    
        private static func handleTextRecognition(request: VNRequest, error: Error?) {
            guard let results = request.results as? [VNRecognizedTextObservation] else { return }
    
            // 提取识别结果并过滤出纯数字
            for result in results {
                guard let topMatch = result.topCandidates(1).first else { continue }
                let recognizedText = topMatch.string
                if recognizedText.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil {
                    // 回到主线程更新UI或处理结果
                    DispatchQueue.main.async {
                        print("识别到数字:\(recognizedText)")
                        // 这里可以把结果传给UI组件,比如UILabel
                    }
                }
            }
        }
    }
    

    如果是手写数字,只需要把VNRecognizeTextRequest换成VNCoreMLRequest,传入你用Create ML生成的手写识别模型就行。

方案二:第三方OCR库(快速落地)

如果不想折腾模型训练,可以用成熟的第三方OCR库,比如Tesseract的Swift封装版本。它的优势是开箱即用,缺点是体积略大,不过你可以只加载数字相关的语言包来减小体积。

示例代码(以TesseractOCRiOS为例):

import UIKit
import TesseractOCRiOS

// 假设你已经获取到摄像头的UIImage
func scanDigitFromImage(_ image: UIImage) {
    guard let tesseract = G8Tesseract(language: "eng") else { return }
    tesseract.engineMode = .tesseractOnly
    tesseract.pageSegmentationMode = .singleChar // 如果是单个数字场景
    // 白名单:只识别0-9
    tesseract.setVariableValue("0123456789", forKey: "tessedit_char_whitelist")
    tesseract.image = image.g8_blackAndWhite() // 预处理图像提升准确率
    tesseract.recognize()
    
    if let result = tesseract.recognizedText, !result.isEmpty {
        print("识别到数字:\(result)")
    }
}
关键注意事项
  • 必须在Info.plist中添加NSCameraUsageDescription字段,说明摄像头的使用用途,否则App会崩溃。
  • 实时扫描时,一定要在后台队列处理图像识别逻辑,避免阻塞主线程导致UI卡顿。
  • 如果识别准确率不够,可以对图像做预处理:比如灰度化、二值化、裁剪出感兴趣区域(ROI),这些都能大幅提升识别效果。

内容的提问来源于stack exchange,提问作者Mehdi Gilanpour

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:04:32