ML Kit를 사용하여 바코드를 인식하고 디코딩할 수 있습니다.
사용해 보기
- 샘플 앱을 사용하여 이 API의 사용 예를 참조하세요.
시작하기 전에
- Podfile에 다음 ML Kit 포드를 포함합니다.
pod 'GoogleMLKit/BarcodeScanning', '3.2.0'
- 프로젝트의 포드를 설치하거나 업데이트한 후 포드를 사용하여 Xcode 프로젝트를 엽니다.
.xcworkspace
ML Kit는 Xcode 버전 12.4 이상에서 지원됩니다.
입력 이미지 가이드라인
-
ML Kit가 바코드를 정확하게 읽으려면 입력 이미지에 충분한 픽셀 데이터로 표현된 바코드입니다.
구체적인 픽셀 데이터 요구사항은 많은 바코드가 가변 크기 페이로드를 지원해야 합니다 일반적으로 가장 작은 규모의 의미 있는 바코드의 단위는 가로 2픽셀 이상이어야 하며 높이가 2픽셀인 2차원 코드
예를 들어 EAN-13 바코드는 2, 3 또는 4단위이므로 EAN-13 바코드 이미지에는 막대와 최소 너비가 2, 4, 6, 8픽셀 이상인 공백을 포함합니다. EAN-13이 바코드의 너비가 총 95단위이면 바코드는 최소 190이어야 합니다. 지정할 수 있습니다.
PDF417과 같은 밀도가 높은 형식은 ML Kit를 사용하여 올바르게 읽습니다. 예를 들어 PDF417 코드는 34개의 17단위 가로 '단어' 표시할 수 있으며, 이 형식은 최소한 1156픽셀
-
이미지 초점이 잘 맞지 않으면 스캔 정확성에 영향을 줄 수 있습니다. 앱이 수신되지 않는 경우 사용자에게 이미지를 다시 캡처하도록 요청합니다.
-
일반적인 애플리케이션의 경우 해상도 이미지(예: 1280x720 또는 1920x1080)로 카메라에서 더 먼 거리에서 스캔할 수 있어야 합니다.
그러나 지연 시간이 중요한 애플리케이션에서는 더 낮은 해상도에서 이미지를 캡처하기 때문에 성능을 향상할 수 있지만 바코드가 입력 이미지의 대부분을 구성합니다. 참고 항목 실시간 성능 향상을 위한 팁
1. 바코드 스캐너 구성
읽을 바코드 형식을 알고 있으면 바코드 스캐너를 스캔하도록 구성합니다.예를 들어 Aztec 코드와 QR 코드만 스캔하려면
BarcodeScannerOptions
객체(예:
다음 예를 참고하세요.
Swift
let format = .all let barcodeOptions = BarcodeScannerOptions(formats: format)
지원되는 형식은 다음과 같습니다.
- code128
- code39
- code93
- codaBar
- dataMatrix
- EAN13
- EAN8
- ITF
- qrCode
- UPCA
- UPCE
- PDF417
- Aztec
Objective-C
MLKBarcodeScannerOptions *options = [[MLKBarcodeScannerOptions alloc] initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];
지원되는 형식은 다음과 같습니다.
- Code-128 (
MLKBarcodeFormatCode128
) - Code-39 (
MLKBarcodeFormatCode39
) - Code-93 (
MLKBarcodeFormatCode93
) - Codabar (
MLKBarcodeFormatCodaBar
) - Data Matrix (
MLKBarcodeFormatDataMatrix
) - EAN-13 (
MLKBarcodeFormatEAN13
) - EAN-8 (
MLKBarcodeFormatEAN8
) - ITF (
MLKBarcodeFormatITF
) - QR 코드 (
MLKBarcodeFormatQRCode
) - UPC-A (
MLKBarcodeFormatUPCA
) - UPC-E (
MLKBarcodeFormatUPCE
) - PDF-417 (
MLKBarcodeFormatPDF417
) - Aztec 코드 (
MLKBarcodeFormatAztec
)
2. 입력 이미지 준비
이미지 속 바코드를 스캔하려면 이미지를UIImage
또는
BarcodeScanner
의 process()
또는 results(in:)
에 대한 CMSampleBufferRef
메서드를 사용하여 축소하도록 요청합니다.
VisionImage
객체를 UIImage
또는
CMSampleBuffer
입니다.
UIImage
를 사용하는 경우 다음 단계를 따르세요.
UIImage
로VisionImage
객체를 만듭니다. 올바른.orientation
를 지정해야 합니다.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
CMSampleBuffer
를 사용하는 경우 다음 단계를 따르세요.
-
CMSampleBuffer
이미지 방향을 가져오는 방법은 다음과 같습니다.
Swift
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> UIImage.Orientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftMirrored : .right case .landscapeLeft: return cameraPosition == .front ? .downMirrored : .up case .portraitUpsideDown: return cameraPosition == .front ? .rightMirrored : .left case .landscapeRight: return cameraPosition == .front ? .upMirrored : .down case .faceDown, .faceUp, .unknown: return .up } }
Objective-C
- (UIImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored : UIImageOrientationRight; case UIDeviceOrientationLandscapeLeft: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored : UIImageOrientationUp; case UIDeviceOrientationPortraitUpsideDown: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored : UIImageOrientationLeft; case UIDeviceOrientationLandscapeRight: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored : UIImageOrientationDown; case UIDeviceOrientationUnknown: case UIDeviceOrientationFaceUp: case UIDeviceOrientationFaceDown: return UIImageOrientationUp; } }
- 다음을 사용하여
VisionImage
객체를 만듭니다.CMSampleBuffer
객체 및 방향:Swift
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
Objective-C
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. BarcodeScanner 인스턴스 가져오기
BarcodeScanner
의 인스턴스를 가져옵니다.
Swift
let barcodeScanner = BarcodeScanner.barcodeScanner() // Or, to change the default settings: // let barcodeScanner = BarcodeScanner.barcodeScanner(options: barcodeOptions)
Objective-C
MLKBarcodeScanner *barcodeScanner = [MLKBarcodeScanner barcodeScanner]; // Or, to change the default settings: // MLKBarcodeScanner *barcodeScanner = // [MLKBarcodeScanner barcodeScannerWithOptions:options];
4. 이미지 처리
그런 다음 이미지를process()
메서드에 전달합니다.
Swift
barcodeScanner.process(visionImage) { features, error in guard error == nil, let features = features, !features.isEmpty else { // Error handling return } // Recognized barcodes }
Objective-C
[barcodeScanner processImage:image completion:^(NSArray<MLKBarcode *> *_Nullable barcodes, NSError *_Nullable error) { if (error != nil) { // Error handling return; } if (barcodes.count > 0) { // Recognized barcodes } }];
5. 바코드에서 정보 가져오기
바코드 스캔 작업이 성공하면 스캐너는Barcode
객체 각 Barcode
객체는
감지된 바코드입니다. 각 바코드에 대해
경계 좌표 및
없습니다. 또한 바코드 스캐너가
또는 파싱된 데이터가 포함된 객체를 가져올 수 있습니다.
예를 들면 다음과 같습니다.
Swift
for barcode in barcodes { let corners = barcode.cornerPoints let displayValue = barcode.displayValue let rawValue = barcode.rawValue let valueType = barcode.valueType switch valueType { case .wiFi: let ssid = barcode.wifi?.ssid let password = barcode.wifi?.password let encryptionType = barcode.wifi?.type case .URL: let title = barcode.url!.title let url = barcode.url!.url default: // See API reference for all supported value types } }
Objective-C
for (MLKBarcode *barcode in barcodes) { NSArray *corners = barcode.cornerPoints; NSString *displayValue = barcode.displayValue; NSString *rawValue = barcode.rawValue; MLKBarcodeValueType valueType = barcode.valueType; switch (valueType) { case MLKBarcodeValueTypeWiFi: ssid = barcode.wifi.ssid; password = barcode.wifi.password; encryptionType = barcode.wifi.type; break; case MLKBarcodeValueTypeURL: url = barcode.URL.url; title = barcode.URL.title; break; // ... default: break; } }
실시간 성능 개선을 위한 팁
실시간 애플리케이션에서 바코드를 스캔하려면 다음 가이드라인을 참조하세요.
-
카메라의 기본 해상도에서 입력을 캡처하지 않습니다. 일부 기기에서는 기본 해상도에서 입력을 캡처하면 크기가 매우 큽니다 (10+ 메가픽셀) 이미지이므로 지연 시간이 매우 짧지만 있습니다. 대신 카메라에서 필요한 크기만 요청하세요. 2메가픽셀 이하입니다.
이름이 지정된 캡처 세션 사전 설정:
AVCaptureSessionPresetDefault
AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
등)는 일부 기기에서 부적절한 해상도로 설정될 수 있습니다. 대신 특정 사전 설정을 사용하세요.AVCaptureSessionPreset1280x720
등).스캔 속도가 중요한 경우 이미지 캡처 속도를 더 낮출 수 있습니다. 있습니다. 단, 최소 바코드 크기 요구사항에 유의해야 합니다. 참조하세요.
스트리밍 시퀀스에서 바코드를 인식하려는 경우 인식기는 프레임마다 다른 결과를 생성할 수 있으며 있습니다. 동일한 결과가 연이어 나올 때까지 기다려야 합니다. 값을 사용하여 좋은 결과를 반환할 것이라는 확신을 가질 수 있습니다.
ITF 및 CODE-39에는 체크섬 숫자가 지원되지 않습니다.
- 동영상 프레임을 처리하려면 감지기의
results(in:)
동기 API를 사용하세요. 전화걸기AVCaptureVideoDataOutputSampleBufferDelegate
님의 <ph type="x-smartling-placeholder"></ph>captureOutput(_, didOutput:from:)
함수를 사용하여 특정 동영상에서 동기식으로 결과를 가져옵니다. 있습니다. 유지AVCaptureVideoDataOutput
님의alwaysDiscardsLateVideoFrames
를true
로 설정하여 감지기 호출을 제한합니다. 새 동영상 프레임은 감지기가 실행되는 동안 사용할 수 있게 되면 삭제됩니다. - 감지기 출력을 사용하여 그래픽 이미지를 먼저 ML Kit에서 결과를 가져온 후 이미지를 하나의 단계로 오버레이할 수 있습니다. 이렇게 하면 처리되어야 합니다 자세한 내용은 updatePreviewOverlayViewWithLastFrame을 를 참조하세요.