Możesz używać ML Kit do rozpoznawania tekstu na obrazach lub w filmach, na przykład na znakach drogowych. Główne cechy tej funkcji:
Interfejs API rozpoznawania tekstu | |
---|---|
Opis | Rozpoznawaj tekst w alfabecie łacińskim na obrazach lub w filmach. |
Nazwa pakietu SDK | Google |
Wdrażanie | Zasoby są statycznie połączone z aplikacją podczas tworzenia. |
Wpływ na rozmiar aplikacji | Około 20 MB |
Wydajność | W czasie rzeczywistym na większości urządzeń. |
Wypróbuj
- Przetestuj przykładową aplikację, aby zobaczyć przykładowe użycie tego interfejsu API.
- Wypróbuj kod za pomocą laboratorium.
Zanim zaczniesz
- Uwzględnij w podfile te pody ML Kit:
pod 'GoogleMLKit/TextRecognition','2.2.0'
- Gdy zainstalujesz lub zaktualizujesz pody projektu, otwórz projekt Xcode, używając jego
.xcworkspace
. ML Kit jest obsługiwany w Xcode w wersji 12.4 lub nowszej.
1. Tworzenie instancji TextRecognizer
Utwórz instancję TextRecognizer
TextRecognizer
, wywołując metodę +textRecognizer
:
let textRecognizer = TextRecognizer.textRecognizer()
MLKTextRecognizer *textRecognizer = [MLKTextRecognizer textRecognizer];
2. Przygotuj obraz wejściowy
Przekaż obraz jakoUIImage
lub CMSampleBufferRef
do metody process(_:completion:)
TextRecognizer
:
Utwórz obiekt VisionImage
za pomocą właściwości UIImage
lub CMSampleBuffer
.
Jeśli używasz UIImage
, wykonaj te czynności:
- Utwórz obiekt
VisionImage
z elementemUIImage
. Pamiętaj o prawidłowej wartości.orientation
.let image = VisionImage(image: UIImage)
visionImage.orientation = image.imageOrientationMLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
visionImage.orientation = image.imageOrientation;
Jeśli używasz CMSampleBuffer
, wykonaj te czynności:
-
Określ orientację danych obrazu zawartych w elemencie
CMSampleBuffer
.Aby uzyskać orientację obrazu:
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
}
}
- (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;
}
}
- Utwórz obiekt
VisionImage
za pomocą obiektuCMSampleBuffer
i orientacji:let image = VisionImage(buffer: sampleBuffer)
image.orientation = imageOrientation(
deviceOrientation: UIDevice.current.orientation,
cameraPosition: cameraPosition)MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
image.orientation =
[self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
cameraPosition:cameraPosition];
3. Przetwórz obraz
Następnie przekaż obraz za pomocą metody process(_:completion:)
:
textRecognizer.process(visionImage) { result, error in
guard error == nil, let result = result else {
// Error handling
return
}
// Recognized text
}
[textRecognizer processImage:image
completion:^(MLKText *_Nullable result,
NSError *_Nullable error) {
if (error != nil || result == nil) {
// Error handling
return;
}
// Recognized text
}];
4. Wyodrębnij z bloków tekstu rozpoznanego tekstu
Jeśli operacja rozpoznawania tekstu zakończy się powodzeniem, zostanie zwrócony obiekt Text
. Obiekt Text
zawiera pełny tekst rozpoznany na obrazie i zero lub większą liczbę obiektów TextBlock
.
Każdy element TextBlock
reprezentuje prostokątny blok tekstu, który zawiera co najmniej 0 obiektów TextLine
. Każdy obiekt TextLine
zawiera 0 lub więcej obiektów TextElement
, które reprezentują słowa i elementy podobne do słów, takie jak daty i liczby.
W przypadku każdego obiektu TextBlock
, TextLine
i TextElement
możesz rozpoznać tekst w regionie i jego granicach.
Przykład:
let resultText = result.text
for block in result.blocks {
let blockText = block.text
let blockLanguages = block.recognizedLanguages
let blockCornerPoints = block.cornerPoints
let blockFrame = block.frame
for line in block.lines {
let lineText = line.text
let lineLanguages = line.recognizedLanguages
let lineCornerPoints = line.cornerPoints
let lineFrame = line.frame
for element in line.elements {
let elementText = element.text
let elementCornerPoints = element.cornerPoints
let elementFrame = element.frame
}
}
}
NSString *resultText = result.text;
for (MLKTextBlock *block in result.blocks) {
NSString *blockText = block.text;
NSArray<MLKTextRecognizedLanguage *> *blockLanguages = block.recognizedLanguages;
NSArray<NSValue *> *blockCornerPoints = block.cornerPoints;
CGRect blockFrame = block.frame;
for (MLKTextLine *line in block.lines) {
NSString *lineText = line.text;
NSArray<MLKTextRecognizedLanguage *> *lineLanguages = line.recognizedLanguages;
NSArray<NSValue *> *lineCornerPoints = line.cornerPoints;
CGRect lineFrame = line.frame;
for (MLKTextElement *element in line.elements) {
NSString *elementText = element.text;
NSArray<NSValue *> *elementCornerPoints = element.cornerPoints;
CGRect elementFrame = element.frame;
}
}
}
Wskazówki dotyczące obrazu wejściowego
-
Aby system ML Kit dokładnie rozpoznawał tekst, obrazy wejściowe muszą zawierać tekst reprezentowany przez wystarczającą ilość danych w pikselach. Najlepiej, gdyby każdy znak miał co najmniej 16 × 16 pikseli. Ogólnie nie ma korzyści, dzięki którym znaki będą większe niż 24 x 24 piksele.
Na przykład obraz o rozdzielczości 640 × 480 może sprawdzić się w przypadku skanu wizytówki zajmującej całą szerokość obrazu. Aby zeskanować dokument wydrukowany na papierze o rozmiarze litery, może być wymagany obraz o wymiarach 720 x 1280 pikseli.
-
Słaba ostrość obrazu może mieć wpływ na dokładność rozpoznawania tekstu. Jeśli nie widzisz odpowiednich wyników, poproś użytkownika, aby ponownie zrobił zdjęcie.
-
Jeśli rozpoznajesz tekst w aplikacji w czasie rzeczywistym, weź pod uwagę ogólne wymiary obrazów wejściowych. Mniejsze obrazy można przetwarzać szybciej. Aby skrócić czas oczekiwania, zadbaj o to, aby tekst zajmował jak największą część obrazu i robił zdjęcia w niższej rozdzielczości (z uwzględnieniem wymienionych powyżej wymagań dotyczących dokładności). Więcej informacji znajdziesz w artykule Wskazówki, jak zwiększyć skuteczność.
Wskazówki, jak zwiększyć skuteczność
- Aby przetworzyć ramki wideo, użyj synchronicznego interfejsu API detektora
results(in:)
. Wywołaj tę metodę za pomocą funkcjicaptureOutput(_, didOutput:from:)
AVCaptureVideoDataOutputSampleBufferDelegate
, aby synchronicznie uzyskać wyniki z danej klatki filmu. Aby ograniczyć liczbę wywołań wykrywania, zachowajalwaysDiscardsLateVideoFrames
AVCaptureVideoDataOutput
. Jeśli nowa reguła wideo stanie się dostępna podczas działania wzorca do wykrywania treści, zostanie usunięta. - Jeśli używasz danych wyjściowych wzorca do nakładania grafiki na obrazie wejściowym, najpierw pobierz wynik z ML Kit, a następnie wyrenderuj obraz i nakładkę w jednym kroku. Dzięki temu renderowanie każdej klatki będzie renderowane tylko raz dla każdej przetworzonej klatki wejściowej. Przykład znajdziesz w przykładzie updatepreviewOverlayViewWithLastFrame w przykładzie ML Kit.
- Rozważ robienie zdjęć w niższej rozdzielczości. Pamiętaj jednak o wymaganiach związanych z wymiarami dotyczącymi tego interfejsu API.