Za pomocą ML Kit możesz rozpoznawać i dekodować kody kreskowe.
Zanim zaczniesz
- Jeśli nie dodałeś jeszcze Firebase do swojej aplikacji, zrób to, wykonując czynności opisane w przewodniku wprowadzającym .
- Dołącz biblioteki ML Kit do swojego Podfile:
pod 'Firebase/MLVision' pod 'Firebase/MLVisionBarcodeModel'
Po zainstalowaniu lub zaktualizowaniu Podów swojego projektu pamiętaj o otwarciu projektu Xcode przy użyciu jego.xcworkspace
. - W swojej aplikacji zaimportuj Firebase:
Szybki
import Firebase
Cel C
@import Firebase;
Wytyczne dotyczące obrazu wejściowego
Aby zestaw ML Kit mógł dokładnie odczytywać kody kreskowe, obrazy wejściowe muszą zawierać kody kreskowe reprezentowane przez wystarczającą ilość danych w pikselach.
Konkretne wymagania dotyczące danych pikselowych zależą zarówno od typu kodu kreskowego, jak i ilości danych w nim zakodowanych (ponieważ większość kodów kreskowych obsługuje ładunek o zmiennej długości). Ogólnie rzecz biorąc, najmniejsza znacząca jednostka kodu kreskowego powinna mieć co najmniej 2 piksele szerokości (a w przypadku kodów dwuwymiarowych – 2 piksele wysokości).
Na przykład kody kreskowe EAN-13 składają się z kresek i spacji o szerokości 1, 2, 3 lub 4 jednostek, więc obraz kodu kreskowego EAN-13 w idealnym przypadku zawiera kreski i spacje o długości co najmniej 2, 4, 6 i Szerokość 8 pikseli. Ponieważ kod kreskowy EAN-13 ma łącznie 95 jednostek szerokości, kod kreskowy powinien mieć szerokość co najmniej 190 pikseli.
Gęstsze formaty, takie jak PDF417, wymagają większych wymiarów w pikselach, aby ML Kit mógł je niezawodnie odczytać. Na przykład kod PDF417 może zawierać do 34 „słów” o szerokości 17 jednostek w jednym wierszu, co w idealnym przypadku powinno mieć co najmniej 1156 pikseli szerokości.
Słaba ostrość obrazu może obniżyć dokładność skanowania. Jeśli wyniki nie są akceptowalne, spróbuj poprosić użytkownika o ponowne wykonanie zdjęcia.
Do typowych zastosowań zaleca się podanie obrazu o wyższej rozdzielczości (np. 1280x720 lub 1920x1080), dzięki której kody kreskowe będą wykrywalne z większej odległości od kamery.
Jednakże w zastosowaniach, w których opóźnienie jest krytyczne, można poprawić wydajność, przechwytując obrazy w niższej rozdzielczości, ale wymagając, aby kod kreskowy stanowił większość obrazu wejściowego. Zobacz także Wskazówki dotyczące poprawy wydajności w czasie rzeczywistym .
1. Skonfiguruj detektor kodów kreskowych
Jeśli wiesz, jakich formatów kodów kreskowych chcesz czytać, możesz zwiększyć szybkość detektora kodów kreskowych, konfigurując go tak, aby wykrywał tylko te formaty. Na przykład, aby wykryć tylko kod Azteków i kody QR, zbuduj obiekt VisionBarcodeDetectorOptions
jak w poniższym przykładzie:
Szybki
let format = VisionBarcodeFormat.all let barcodeOptions = VisionBarcodeDetectorOptions(formats: format)
Obsługiwane są następujące formaty:
- Kod128
- Kod39
- Kod93
- KodaBar
- EAN13
- EAN8
- ITF
- UPCA
- UPCE
- Kod QR
- PDF417
- Aztek
- DataMatrix
Cel C
FIRVisionBarcodeDetectorOptions *options = [[FIRVisionBarcodeDetectorOptions alloc] initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];
Obsługiwane są następujące formaty:
- Kod 128 (
FIRVisionBarcodeFormatCode128
) - Kod 39 (
FIRVisionBarcodeFormatCode39
) - Kod 93 (
FIRVisionBarcodeFormatCode93
) - Codabar (
FIRVisionBarcodeFormatCodaBar
) - EAN-13 (
FIRVisionBarcodeFormatEAN13
) - EAN-8 (
FIRVisionBarcodeFormatEAN8
) - ITF (
FIRVisionBarcodeFormatITF
) - UPC-A (
FIRVisionBarcodeFormatUPCA
) - UPC-E (
FIRVisionBarcodeFormatUPCE
) - Kod QR (
FIRVisionBarcodeFormatQRCode
) - PDF417 (
FIRVisionBarcodeFormatPDF417
) - Aztek (
FIRVisionBarcodeFormatAztec
) - Macierz danych (
FIRVisionBarcodeFormatDataMatrix
)
2. Uruchom detektor kodów kreskowych
Aby zeskanować kody kreskowe na obrazie, przekaż obraz jakoUIImage
lub CMSampleBufferRef
do metody detect(in:)
klasy VisionBarcodeDetector
:- Pobierz instancję
VisionBarcodeDetector
:Szybki
lazy var vision = Vision.vision() let barcodeDetector = vision.barcodeDetector(options: barcodeOptions)
Cel C
FIRVision *vision = [FIRVision vision]; FIRVisionBarcodeDetector *barcodeDetector = [vision barcodeDetector]; // Or, to change the default settings: // FIRVisionBarcodeDetector *barcodeDetector = // [vision barcodeDetectorWithOptions:options];
Utwórz obiekt
VisionImage
przy użyciuUIImage
lubCMSampleBufferRef
.Aby użyć
UIImage
:- W razie potrzeby obróć obraz tak, aby jego właściwość
imageOrientation
miała.up
. - Utwórz obiekt
VisionImage
przy użyciu poprawnie obróconegoUIImage
. Nie określaj żadnych metadanych rotacji — należy użyć wartości domyślnej.topLeft
.Szybki
let image = VisionImage(image: uiImage)
Cel C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Aby użyć
CMSampleBufferRef
:Utwórz obiekt
VisionImageMetadata
, który określa orientację danych obrazu zawartych w buforzeCMSampleBufferRef
.Aby uzyskać orientację obrazu:
Szybki
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 } }
Cel 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; } }
Następnie utwórz obiekt metadanych:
Szybki
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Cel 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];
- Utwórz obiekt
VisionImage
przy użyciu obiektuCMSampleBufferRef
i metadanych rotacji:Szybki
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Cel C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- W razie potrzeby obróć obraz tak, aby jego właściwość
- Następnie przekaż obraz do metody
detect(in:)
:Szybki
barcodeDetector.detect(in: visionImage) { features, error in guard error == nil, let features = features, !features.isEmpty else { // ... return } // ... }
Cel C
[barcodeDetector detectInImage:image completion:^(NSArray<FIRVisionBarcode *> *barcodes, NSError *error) { if (error != nil) { return; } else if (barcodes != nil) { // Recognized barcodes // ... } }];
3. Uzyskaj informacje z kodów kreskowych
Jeśli operacja rozpoznawania kodu kreskowego zakończy się pomyślnie, detektor zwróci tablicę obiektówVisionBarcode
. Każdy obiekt VisionBarcode
reprezentuje kod kreskowy wykryty na obrazie. Dla każdego kodu kreskowego można uzyskać jego współrzędne graniczne na obrazie wejściowym, a także surowe dane zakodowane w kodzie kreskowym. Ponadto, jeśli detektor kodów kreskowych był w stanie określić typ danych zakodowanych w kodzie kreskowym, można uzyskać obiekt zawierający przeanalizowane dane.Na przykład:
Szybki
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 } }
Cel 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; } }
Wskazówki, jak poprawić wydajność w czasie rzeczywistym
Jeśli chcesz skanować kody kreskowe w aplikacji działającej w czasie rzeczywistym, postępuj zgodnie z poniższymi wskazówkami, aby uzyskać najlepszą liczbę klatek na sekundę:
Nie przechwytuj sygnału wejściowego w natywnej rozdzielczości kamery. Na niektórych urządzeniach przechwytywanie danych wejściowych w natywnej rozdzielczości powoduje powstanie niezwykle dużych obrazów (ponad 10 megapikseli), co skutkuje bardzo niskimi opóźnieniami bez korzyści w zakresie dokładności. Zamiast tego żądaj od aparatu tylko rozmiaru wymaganego do wykrywania kodów kreskowych: zwykle nie więcej niż 2 megapiksele.
Nazwane ustawienia wstępne sesji przechwytywania —
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
itd.) — nie są jednak zalecane, ponieważ na niektórych urządzeniach mogą być mapowane na nieodpowiednie rozdzielczości. Zamiast tego użyj określonych ustawień wstępnych, takich jakAVCaptureSessionPreset1280x720
.Jeśli szybkość skanowania jest ważna, możesz jeszcze bardziej obniżyć rozdzielczość przechwytywania obrazu. Należy jednak pamiętać o wymaganiach dotyczących minimalnego rozmiaru kodu kreskowego opisanych powyżej.
- Przepustnica wzywa do detektora. Jeżeli w trakcie działania detektora pojawi się nowa klatka wideo, usuń ją.
- Jeśli używasz wyjścia detektora do nakładania grafiki na obraz wejściowy, najpierw uzyskaj wynik z ML Kit, a następnie wyrenderuj obraz i nakładkę w jednym kroku. W ten sposób renderujesz na powierzchnię wyświetlacza tylko raz dla każdej klatki wejściowej. Zobacz przykładowe klasy PreviewOverlayView i FIRDetectionOverlayView w przykładowej aplikacji prezentacyjnej.