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
相关产品推荐
相关产品推荐

