ML Kit를 사용하여 바코드를 인식하고 디코딩할 수 있습니다.
시작하기 전에
- 앱에 Firebase를 아직 추가하지 않았다면 시작 가이드의 단계에 따라 추가합니다.
- Podfile에 ML Kit 라이브러리를 포함합니다.
pod 'Firebase/MLVision' pod 'Firebase/MLVisionBarcodeModel'
프로젝트의 포드를 설치하거나 업데이트한 후.xcworkspace
를 사용하여 Xcode 프로젝트를 열어야 합니다. - 앱에서 Firebase를 가져옵니다.
Swift
import Firebase
Objective-C
@import Firebase;
입력 이미지 가이드라인
-
ML Kit가 바코드를 정확하게 읽으려면 입력 이미지에 충분한 픽셀 데이터로 표시된 바코드가 있어야 합니다.
대부분의 바코드가 가변 길이 페이로드를 지원하므로 특정 픽셀 데이터 요구사항은 바코드 유형 및 바코드에 인코딩된 데이터 양에 따라 다릅니다. 일반적으로 바코드의 의미 있는 최소 단위는 가로 2픽셀 이상이어야 합니다(2차원 코드의 경우 세로 2픽셀 이상).
예를 들어 EAN-13 바코드는 가로 1, 2, 3 또는 4단위의 바와 공간으로 구성됩니다. 따라서 이상적인 EAN-13 바코드 이미지는 가로 2, 4, 6, 8픽셀 이상의 바와 공간으로 이루어집니다. EAN-13 바코드는 가로가 총 95단위이므로 바코드는 가로 190픽셀 이상이어야 합니다.
PDF417 등의 밀집 형식을 사용하려면 ML Kit에서 확실히 읽을 수 있도록 더 큰 픽셀 크기가 필요합니다. 예를 들어 PDF417 코드는 한 행에 가로 17단위 '단어'를 34개까지 사용할 수 있으므로 가로 1,156 픽셀 이상이어야 합니다.
-
이미지 초점이 잘 맞지 않으면 스캔의 정확도가 저하될 수 있습니다. 허용 가능한 수준의 결과를 얻지 못하는 경우 사용자에게 이미지를 다시 캡처하도록 요청합니다.
-
일반적인 애플리케이션의 경우 카메라로부터 먼 거리에 놓인 바코드도 감지할 수 있도록 더 높은 해상도의 이미지(예: 1280x720 또는 1920x1080)를 제공하는 것이 좋습니다.
그러나 지연 시간이 중요한 요소인 애플리케이션에서는 낮은 해상도로 이미지를 캡처하되 바코드 영역이 입력 이미지의 대부분을 차지하도록 하여 성능을 개선할 수 있습니다 또한 실시간 성능 향상을 위한 팁도 참조하세요.
1. 바코드 인식기 구성
읽으려는 바코드 형식을 알고 있는 경우 해당 형식만 인식하도록 구성하여 바코드 인식기의 속도를 높일 수 있습니다.예를 들어 Aztec 코드와 QR 코드만 인식하려면 다음 예시와 같이 VisionBarcodeDetectorOptions
객체를 빌드합니다.
Swift
let format = VisionBarcodeFormat.all let barcodeOptions = VisionBarcodeDetectorOptions(formats: format)
지원되는 형식은 다음과 같습니다.
- Code128
- Code39
- Code93
- CodaBar
- EAN13
- EAN8
- ITF
- UPCA
- UPCE
- QRCode
- PDF417
- Aztec
- DataMatrix
Objective-C
FIRVisionBarcodeDetectorOptions *options = [[FIRVisionBarcodeDetectorOptions alloc] initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];
지원되는 형식은 다음과 같습니다.
- Code 128(
FIRVisionBarcodeFormatCode128
) - Code 39(
FIRVisionBarcodeFormatCode39
) - Code 93(
FIRVisionBarcodeFormatCode93
) - Codabar(
FIRVisionBarcodeFormatCodaBar
) - EAN-13(
FIRVisionBarcodeFormatEAN13
) - EAN-8(
FIRVisionBarcodeFormatEAN8
) - ITF(
FIRVisionBarcodeFormatITF
) - UPC-A(
FIRVisionBarcodeFormatUPCA
) - UPC-E(
FIRVisionBarcodeFormatUPCE
) - QR 코드(
FIRVisionBarcodeFormatQRCode
) - PDF417(
FIRVisionBarcodeFormatPDF417
) - Aztec(
FIRVisionBarcodeFormatAztec
) - Data Matrix(
FIRVisionBarcodeFormatDataMatrix
)
2. 바코드 인식기 실행
이미지 속 바코드를 스캔하려면 이미지를UIImage
또는 CMSampleBufferRef
로 VisionBarcodeDetector
의 detect(in:)
메서드에 전달합니다.
VisionBarcodeDetector
의 인스턴스를 가져옵니다.Swift
lazy var vision = Vision.vision() let barcodeDetector = vision.barcodeDetector(options: barcodeOptions)
Objective-C
FIRVision *vision = [FIRVision vision]; FIRVisionBarcodeDetector *barcodeDetector = [vision barcodeDetector]; // Or, to change the default settings: // FIRVisionBarcodeDetector *barcodeDetector = // [vision barcodeDetectorWithOptions:options];
-
UIImage
또는CMSampleBufferRef
를 사용하여VisionImage
객체를 만듭니다.UIImage
를 사용하는 방법은 다음과 같습니다.- 필요한 경우
imageOrientation
속성이.up
이 되도록 이미지를 회전합니다. - 올바르게 회전된
UIImage
를 사용하여VisionImage
객체를 만듭니다. 회전 메타데이터를 지정하지 마세요. 기본값인.topLeft
를 사용해야 합니다.Swift
let image = VisionImage(image: uiImage)
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
CMSampleBufferRef
를 사용하는 방법은 다음과 같습니다.-
CMSampleBufferRef
버퍼에 포함된 이미지 데이터의 방향을 지정하는VisionImageMetadata
객체를 만듭니다.이미지 방향을 가져오는 방법은 다음과 같습니다.
Swift
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> VisionDetectorImageOrientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftTop : .rightTop case .landscapeLeft: return cameraPosition == .front ? .bottomLeft : .topLeft case .portraitUpsideDown: return cameraPosition == .front ? .rightBottom : .leftBottom case .landscapeRight: return cameraPosition == .front ? .topRight : .bottomRight case .faceDown, .faceUp, .unknown: return .leftTop } }
Objective-C
- (FIRVisionDetectorImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationLeftTop; } else { return FIRVisionDetectorImageOrientationRightTop; } case UIDeviceOrientationLandscapeLeft: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationBottomLeft; } else { return FIRVisionDetectorImageOrientationTopLeft; } case UIDeviceOrientationPortraitUpsideDown: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationRightBottom; } else { return FIRVisionDetectorImageOrientationLeftBottom; } case UIDeviceOrientationLandscapeRight: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationTopRight; } else { return FIRVisionDetectorImageOrientationBottomRight; } default: return FIRVisionDetectorImageOrientationTopLeft; } }
그런 다음 메타데이터 객체를 만듭니다.
Swift
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Objective-C
FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init]; AVCaptureDevicePosition cameraPosition = AVCaptureDevicePositionBack; // Set to the capture device you used. metadata.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
CMSampleBufferRef
객체 및 회전 메타데이터를 사용하여VisionImage
객체를 만듭니다.Swift
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- 필요한 경우
- 이제 이미지를
detect(in:)
메서드에 전달합니다.Swift
barcodeDetector.detect(in: visionImage) { features, error in guard error == nil, let features = features, !features.isEmpty else { // ... return } // ... }
Objective-C
[barcodeDetector detectInImage:image completion:^(NSArray<FIRVisionBarcode *> *barcodes, NSError *error) { if (error != nil) { return; } else if (barcodes != nil) { // Recognized barcodes // ... } }];
3. 바코드에서 정보 가져오기
바코드 인식 작업이 성공하면 인식기는VisionBarcode
객체의 배열을 반환합니다. 각 VisionBarcode
객체는 이미지에서 인식된 바코드를 나타냅니다. 바코드별로 입력 이미지의 경계 좌표 및 바코드로 인코딩된 원시 데이터를 가져올 수 있습니다. 또한 바코드 인식기가 바코드로 인코딩된 데이터 유형을 결정할 수 있는 경우,
파싱된 데이터가 포함된 객체를 가져올 수 있습니다.
예를 들면 다음과 같습니다.
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 (FIRVisionBarcode *barcode in barcodes) { NSArray *corners = barcode.cornerPoints; NSString *displayValue = barcode.displayValue; NSString *rawValue = barcode.rawValue; FIRVisionBarcodeValueType valueType = barcode.valueType; switch (valueType) { case FIRVisionBarcodeValueTypeWiFi: // ssid = barcode.wifi.ssid; // password = barcode.wifi.password; // encryptionType = barcode.wifi.type; break; case FIRVisionBarcodeValueTypeURL: // url = barcode.URL.url; // title = barcode.URL.title; break; // ... default: break; } }
실시간 성능 향상을 위한 팁
실시간 애플리케이션에서 바코드를 스캔하려는 경우 최상의 프레임 속도를 얻으려면 다음 안내를 따르세요.
-
카메라의 기본 해상도로 입력을 캡처하지 마세요. 기기에 따라 기본 해상도로 입력을 캡처할 경우 매우 큰(10메가픽셀 이상) 이미지가 생성되므로 정확성 측면에서 아무런 효과 없이 지연 시간만 길어질 수 있습니다. 대신 카메라에서 바코드를 인식하는 데 필요한 크기만 요청하세요. 이 크기는 일반적으로 2메가픽셀 이하입니다.
그러나 이름이 지정된 캡처 세션 미리 설정(
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
등)은 기기에 따라 부적합한 해상도로 매핑될 수 있으므로 사용하지 않는 것이 좋습니다. 대신AVCaptureSessionPreset1280x720
같은 특정 사전 설정을 사용하세요.스캔 속도가 중요한 경우에는 이미지 캡처 해상도를 더 낮추면 됩니다. 단, 위에서 설명한 바코드 크기 최소 요구사항에 유의해야 합니다.
- 인식기 호출을 제한합니다. 인식기가 실행 중일 때 새 동영상 프레임이 제공되는 경우 해당 프레임을 삭제합니다.
- 인식기 출력을 사용해서 입력 이미지에서 그래픽을 오버레이하는 경우 먼저 ML Kit에서 결과를 가져온 후 이미지를 렌더링하고 단일 단계로 오버레이합니다. 이렇게 하면 입력 프레임별로 한 번만 디스플레이 표면에 렌더링됩니다. 관련 예시는 쇼케이스 샘플 앱에서 previewOverlayView 및 FIRDetectionOverlayView 클래스를 참조하세요.