Jak wyodrębnić tekst z obrazów za pomocą Google Machine Learning SDK

Autor: John Stephens
Data Utworzenia: 27 Styczeń 2021
Data Aktualizacji: 5 Lipiec 2024
Anonim
Jak wyodrębnić tekst z obrazów za pomocą Google Machine Learning SDK - Aplikacje
Jak wyodrębnić tekst z obrazów za pomocą Google Machine Learning SDK - Aplikacje

Zawartość


Możesz także użyć interfejsu API rozpoznawania tekstu jako podstawy aplikacji do tłumaczenia lub usług ułatwień dostępu, w których użytkownik może skierować aparat na dowolny tekst, z którym się zmaga, i odczytać go na głos.

W tym samouczku położymy podstawy dla szerokiej gamy innowacyjnych funkcji, tworząc aplikację, która może wyodrębniać tekst z dowolnego obrazu w galerii użytkownika. Chociaż nie będziemy omawiać tego w tym samouczku, możesz również przechwytywać tekst z otoczenia użytkownika w czasie rzeczywistym, podłączając tę ​​aplikację do aparatu urządzenia.

Na urządzeniu czy w chmurze?

Niektóre interfejsy API zestawu ML Kit są dostępne tylko na urządzeniu, ale niektóre są dostępne na urządzeniu i w chmurze, w tym interfejs API rozpoznawania tekstu.

Oparty na chmurze Text API może identyfikować szerszy zakres języków i znaków i zapewnia większą dokładność niż jego odpowiednik na urządzeniu. Jednakże to robi wymagają aktywnego połączenia z Internetem i jest dostępne tylko dla projektów na poziomie Blaze.


W tym artykule uruchomimy interfejs API rozpoznawania tekstu lokalnie, dzięki czemu możesz śledzić, niezależnie od tego, czy uaktualniono Cię do Blaze, czy korzystasz z bezpłatnego planu Firebase Spark.

Tworzenie aplikacji do rozpoznawania tekstu za pomocą ML Kit

Utwórz aplikację z wybranymi ustawieniami, ale po wyświetleniu monitu wybierz szablon „Pusta aktywność”.

Zestaw ML Kit SDK jest częścią Firebase, więc musisz połączyć swój projekt z Firebase, używając jego certyfikatu do podpisywania SHA-1. Aby uzyskać SHA-1 swojego projektu:

  • Wybierz kartę „Gradle” w Android Studio.
  • W panelu „Gradle projects” kliknij dwukrotnie, aby rozwinąć „root” swojego projektu, a następnie wybierz „Tasks> Android> Signing Report”.
  • Panel u dołu okna Android Studio powinien się zaktualizować, aby wyświetlić informacje o tym projekcie - w tym certyfikat podpisu SHA-1.


Aby połączyć swój projekt z Firebase:

  • W przeglądarce internetowej uruchom konsolę Firebase.
  • Wybierz „Dodaj projekt”.
  • Nadaj nazwę swojemu projektowi; Używam „testu ML”.
  • Przeczytaj warunki i jeśli chcesz kontynuować, wybierz „Akceptuję…”, a następnie „Utwórz projekt”.
  • Wybierz „Dodaj Firebase do swojej aplikacji na Androida”.
  • Wpisz nazwę pakietu swojego projektu, który znajdziesz na górze pliku MainActivity i w Manifeście.
  • Wprowadź certyfikat podpisywania SHA-1 swojego projektu.
  • Kliknij „Zarejestruj aplikację”.
  • Wybierz „Pobierz google-services.json”. Ten plik zawiera wszystkie niezbędne metadane Firebase dla twojego projektu, w tym klucz API.
  • W Android Studio przeciągnij i upuść plik google-services.json do katalogu „aplikacji” swojego projektu.

  • Otwórz plik build.gradle na poziomie projektu i dodaj ścieżkę klasy usług Google:

classpath com.google.gms: usługi Google: 4.0.1

  • Otwórz plik build.gradle na poziomie aplikacji i dodaj zależności dla Firebase Core, Firebase ML Vision i interpretera modelu, a także wtyczki usług Google:

zastosuj wtyczkę: com.google.gms.google-services ... ... ... zależności {implement fileTree (reż: libs, include:) implementacja com.google.firebase: firebase-core: com implementacji 16.0.1. google.firebase: firebase-ml-vision: implementacja 16.0.0 com.google.firebase: firebase-ml-model-interpreter: 16.0.0

W tym momencie musisz uruchomić swój projekt, aby mógł połączyć się z serwerami Firebase:

  • Zainstaluj aplikację na fizycznym smartfonie lub tablecie z Androidem lub urządzeniu wirtualnym Android (AVD).
  • W konsoli Firebase wybierz „Uruchom aplikację, aby zweryfikować instalację”.
  • Po kilku chwilach powinieneś zobaczyć „Gratulacje”; wybierz „Przejdź do konsoli”.

Pobierz wstępnie przeszkolone modele uczenia maszynowego Google

Domyślnie ML Kit pobiera modele tylko wtedy, gdy są potrzebne, więc nasza aplikacja pobierze model OCR, gdy użytkownik spróbuje wyodrębnić tekst po raz pierwszy.

Może to potencjalnie mieć negatywny wpływ na wrażenia użytkownika - wyobraź sobie, że próbujesz uzyskać dostęp do funkcji, ale tylko po to, aby odkryć, że aplikacja musi pobrać więcej zasobów, zanim będzie mogła faktycznie dostarczyć tę funkcję. W najgorszym przypadku Twoja aplikacja może nawet nie być w stanie pobrać potrzebnych zasobów, kiedy ich potrzebuje, na przykład, jeśli urządzenie nie ma połączenia z Internetem.

Aby upewnić się, że tak się nie stanie z naszą aplikacją, pobierzę niezbędny model OCR podczas instalacji, co wymaga pewnych zmian w Maniest.

Chociaż mamy otwarty Manifest, dodam również uprawnienie WRITE_EXTERNAL_STORAGE, którego będziemy używać w dalszej części tego samouczka.

// Dodaj uprawnienie WRITE_EXTERNAL_STORAGE // // Dodaj następujący //

Budowanie układu

Usuńmy proste rzeczy i stwórz układ składający się z:

  • ImageView. Początkowo wyświetli to symbol zastępczy, ale zaktualizuje się, gdy użytkownik wybierze obraz ze swojej galerii.
  • Przycisk, który uruchamia ekstrakcję tekstu.
  • TextView, w którym wyświetlimy wyodrębniony tekst.
  • ScrollView. Ponieważ nie ma gwarancji, że wyodrębniony tekst będzie dobrze pasował na ekranie, zamierzam umieścić TextView wewnątrz ScrollView.

Oto gotowy plik activity_main.xml:

Ten układ odwołuje się do rysunku „ic_placeholder”, więc utwórzmy go teraz:

  • Wybierz „Plik> Nowy> Zasób obrazu” z paska narzędzi Android Studio.
  • Otwórz menu rozwijane „Typ ikony” i wybierz „Pasek akcji i ikony kart”.
  • Upewnij się, że przycisk radiowy „Clip Art” jest zaznaczony.
  • Kliknij przycisk „Clip Art”.
  • Wybierz obraz, którego chcesz użyć jako symbolu zastępczego; Używam „Dodaj do zdjęć”.
  • Kliknij OK."
  • Otwórz menu „Motyw” i wybierz „HOLO_LIGHT”.
  • W polu „Nazwa” wpisz „ic_placeholder”.
  • Kliknij „Dalej”. Przeczytaj informacje, a jeśli chcesz kontynuować, kliknij „Zakończ”.

Ikony paska akcji: Uruchamianie aplikacji Galeria

Następnie utworzę element paska akcji, który uruchomi galerię użytkownika, gotowy do wybrania obrazu.

Ikony paska działań definiuje się w pliku zasobów menu, który znajduje się w katalogu „res / menu”. Jeśli twój projekt nie zawiera tego katalogu, musisz go utworzyć:

  • Kliknij z wciśniętym klawiszem Control w folder „res” swojego projektu i wybierz „Nowy> Katalog zasobów Androida”.
  • Otwórz menu „Typ zasobu” i wybierz „menu”.
  • „Nazwa katalogu” powinna zostać automatycznie zaktualizowana do „menu”, ale jeśli tak nie jest, musisz zmienić nazwę ręcznie.
  • Kliknij OK."

Teraz możesz utworzyć plik zasobów menu:

  • Kliknij z wciśniętym klawiszem Control w folder „menu” projektu i wybierz „Nowy> Plik zasobów menu”.
  • Nazwij ten plik „my_menu”.
  • Kliknij OK."
  • Otwórz plik „my_menu.xml” i dodaj następujące elementy:

//Stworzyć element dla każdej akcji //

Plik menu odwołuje się do ciągu „action_gallery”, więc otwórz plik res / wartości / strings.xml swojego projektu i utwórz ten zasób. Będąc tutaj, definiuję również inne ciągi, których będziemy używać w tym projekcie.

Galeria Ta aplikacja musi mieć dostęp do plików na Twoim urządzeniu. Nie znaleziono tekstu

Następnie użyj Image Asset Studio, aby utworzyć ikonę „ic_gallery” na pasku działań:

  • Wybierz „Plik> Nowy> Zasób obrazu”.
  • Ustaw menu rozwijane „Typ ikony” na „Pasek akcji i ikony kart”.
  • Kliknij przycisk „Clip Art”.
  • Wybierz rozkładaną; Używam „obrazu”.
  • Kliknij OK."
  • Aby upewnić się, że ikona jest wyraźnie widoczna na pasku akcji, otwórz menu „Motyw” i wybierz „HOLO_DARK”.
  • Nazwij tę ikonę „ic_gallery”.
  • „Kliknij„ Dalej ”, a następnie„ Zakończ ”.

Obsługa wniosków o uprawnienia i zdarzeń kliknięć

Zamierzam wykonać wszystkie zadania niezwiązane bezpośrednio z interfejsem API rozpoznawania tekstu w osobnej klasie BaseActivity, w tym utworzyć instancję menu, obsługiwać zdarzenia kliknięcia paska akcji i poprosić o dostęp do pamięci urządzenia.

  • Wybierz „Plik> Nowy> Klasa Java” z paska narzędzi Android Studio.
  • Nazwij tę klasę „BaseActivity”.
  • Kliknij OK."
  • Otwórz BaseActivity i dodaj:

import android.app.Activity; import android.support.v4.app.ActivityCompat; import android.support.v7.app.ActionBar; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.content.DialogInterface; import android.content.Intent; import android.Manifest; import android.provider.MediaStore; import android.view.Menu; import android.view.MenuItem; import android.content.pm.PackageManager; import android.net.Uri; import android.provider.Settings; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import java.io.File; Klasa Public BaseActivity rozszerza AppCompatActivity {public static final int WRITE_STORAGE = 100; public static final int SELECT_PHOTO = 102; public static final String ACTION_BAR_TITLE = "action_bar_title"; publiczne zdjęcie pliku; @Override chronione void onCreate (@Nullable Bundle saveInstanceState) {super.onCreate (saveInstanceState); ActionBar actionBar = getSupportActionBar (); if (actionBar! = null) {actionBar.setDisplayHomeAsUpEnabled (true); actionBar.setTitle (getIntent (). getStringExtra (ACTION_BAR_TITLE)); }} @Override public boolean onCreateOptionsMenu (menu Menu) {getMenuInflater (). Inflate (R.menu.my_menu, menu); zwróć prawdę; } @Override public boolean onOptionsItemSelected (element MenuItem) {switch (item.getItemId ()) {// Jeśli wybrana jest opcja „gallery współdziałanie”, to ... // case R.id.gallery współdziałanie: //... sprawdź uprawnienie WRITE_STORAGE // checkPermission (WRITE_STORAGE); złamać; } return super.onOptionsItemSelected (item); } @Override public void onRequestPermissionsResult (int codeCode, @NonNull Ciąg uprawnień, @NonNull int grantResults) {super.onRequestPermissionsResult (requestCode, uprawnienia, grantResults); switch (requestCode) {case WRITE_STORAGE: // Jeśli prośba o pozwolenie zostanie udzielona, ​​to ... // if (grantResults.length> 0 && grantResults == PackageManager.PERMISSION_GRANTED) {//...call selectPicture // selectPicture ( ); // Jeśli wniosek o pozwolenie zostanie odrzucony, to ... //} else {//...display the „pozwolenie_wymagania” // żądaniePermission (this, requestCode, R.string.permission_request); } przerwa; }} // Wyświetl okno dialogowe żądania uprawnień // public static void requestPermission (final Activity activity, final int requestCode, int msg) {AlertDialog.Builder alert = new AlertDialog.Builder (aktywność); alert.set (msg); alert.setPositiveButton (android.R.string.ok, nowy DialogInterface.OnClickListener () {@Override public void onClick (DialogInterface dialogInterface, int i) {dialogInterface.dismiss (); Intent permissonIntent = nowy zamiar (Ustawienia.ACTION_ETLS) .setData (Uri.parse ("package:" + activity.getPackageName ())); activity.startActivityForResult (permissonIntent, requestCode);}}); alert.setNegativeButton (android.R.string.cancel, nowy DialogInterface.OnClickListener () {@Override public void onClick (DialogInterface dialogInterface, int i) {dialogInterface.dismiss ();}}); alert.setCancelable (false); alert.show (); } // Sprawdź, czy użytkownik udzielił uprawnienia WRITE_STORAGE // public void checkPermission (int requestCode) {switch (requestCode) {case WRITE_STORAGE: int hasWriteExternalStoragePermission = ActivityCompat.checkSelfPermission (this, Manifest.permission.WRITE_EXTERNAL_STORAGE); // Jeśli mamy dostęp do pamięci zewnętrznej ... // if (hasWriteExternalStoragePermission == PackageManager.PERMISSION_GRANTED) {//...call selectPicture, który uruchamia działanie, w którym użytkownik może wybrać obraz // selectPicture (); // Jeśli pozwolenie nie zostało udzielone, wtedy ... //} else {//...zaproś o pozwolenie // ActivityCompat.requestPermissions (ten nowy ciąg {Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode); } przerwa; }} private void selectPicture () {photo = MyHelper.createTempFile (zdjęcie); Intent intent = new Intent (Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); // Rozpocznij działanie, w którym użytkownik może wybrać obraz // startActivityForResult (intent, SELECT_PHOTO); }}

W tym momencie Twój projekt powinien narzekać, że nie może rozwiązać MyHelper.createTempFile. Zaimplementujmy to teraz!

Zmiana rozmiaru obrazów za pomocą createTempFile

Utwórz nową klasę „MyHelper”. W tej klasie zmienimy rozmiar obrazu wybranego przez użytkownika, gotowego do przetworzenia przez interfejs API rozpoznawania tekstu.

import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.content.Context; import android.database.Cursor; import android.os.Environment; import android.widget.ImageView; import android.provider.MediaStore; import android.net.Uri; import statyczny android.graphics.BitmapFactory.decodeFile; import statyczny android.graphics.BitmapFactory.decodeStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class MyHelper {public static String getPath (kontekst kontekstowy, Uri uri) {String path = ""; Projekcja ciągu = {MediaStore.Images.Media.DATA}; Kursor = kontekst.getContentResolver (). Query (uri, projection, null, null, null); int kolumna_indeks; if (kursor! = null) {kolumna_indeks = kursor.getColumnIndexOrThrow (MediaStore.Images.Media.DATA); kursor.moveToFirst (); ścieżka = kursor.getString (indeks_kolumny); kursor.close (); } ścieżka powrotna; } public static File createTempFile (plik pliku) {Katalog plików = nowy plik (Environment.getExternalStorageDirectory (). getPath () + "/com.jessicathornsby.myapplication"); if (! directory.exists () ||! directory.isDirectory ()) {directory.mkdirs (); } if (file == null) {file = new File (directory, "orig.jpg"); } plik zwrotny; } public static bitmap resizePhoto (Plik imageFile, kontekst kontekstowy, Uri uri, widok ImageView) {BitmapFactory.Options newOptions = new BitmapFactory.Options (); spróbuj {decodeStream (context.getContentResolver (). openInputStream (uri), null, newOptions); int photoHeight = newOptions.outHeight; int photoWidth = newOptions.outWidth; newOptions.inSampleSize = Math.min (photoWidth / view.getWidth (), photoHeight / view.getHeight ()); zwraca kompresorPhoto (imageFile, BitmapFactory.decodeStream (context.getContentResolver (). openInputStream (uri), null, newOptions)); } catch (wyjątek FileNotFoundException) {wyjątek.printStackTrace (); zwraca null; }} public static bitmap resizePhoto (Plik imageFile, ścieżka ciągu, widok ImageView) {BitmapFactory.Options options = new BitmapFactory.Options (); decodeFile (ścieżka, opcje); int photoHeight = options.outHeight; int photoWidth = options.outWidth; options.inSampleSize = Math.min (photoWidth / view.getWidth (), photoHeight / view.getHeight ()); zwraca kompresjęPhoto (imageFile, BitmapFactory.decodeFile (ścieżka, opcje)); } private static Bitmap compressPhoto (File photoFile, Bitmap bitmap) {try {FileOutputStream fOutput = nowy FileOutputStream (photoFile); bitmap.compress (Bitmap.CompressFormat.JPEG, 70, fOutput); fOutput.close (); } catch (wyjątek IOException) {wyjątek.printStackTrace (); } zwraca mapę bitową; }}

Ustaw obraz na ImageView

Następnie musimy zaimplementować onActivityResult () w naszej klasie MainActivity i ustawić wybrany przez użytkownika obraz na nasz ImageView.

import android.graphics.Bitmap; import android.os.Bundle; import android.widget.ImageView; import android.content.Intent; import android.widget.TextView; import android.net.Uri; klasa publiczna MainActivity rozszerza BaseActivity {private Bitmap myBitmap; prywatny ImageView myImageView; prywatny TextView myTextView; @Override chronione void onCreate (pakiet saveInstanceState) {super.onCreate (saveInstanceState); setContentView (R.layout.activity_main); myTextView = findViewById (R.id.textView); myImageView = findViewById (R.id.imageView); } @Override protected void onActivityResult (int requestCode, int resultCode, Intent data) {super.onActivityResult (requestCode, resultCode, dane); if (resultCode == RESULT_OK) {switch (requestCode) {case WRITE_STORAGE: checkPermission (requestCode); złamać; case SELECT_PHOTO: Uri dataUri = data.getData (); Ścieżka ciągu = MyHelper.getPath (this, dataUri); if (ścieżka == null) {myBitmap = MyHelper.resizePhoto (zdjęcie, to, dataUri, myImageView); } else {myBitmap = MyHelper.resizePhoto (zdjęcie, ścieżka, myImageView); } if (myBitmap! = null) {myTextView.setText (null); myImageView.setImageBitmap (myBitmap); } przerwa; }}}}

Uruchom ten projekt na fizycznym urządzeniu z Androidem lub AVD i kliknij ikonę paska akcji. Po wyświetleniu monitu udziel uprawnienia WRITE_STORAGE i wybierz obraz z galerii; ten obraz powinien być teraz wyświetlany w interfejsie aplikacji.

Teraz położyliśmy podwaliny, jesteśmy gotowi, aby rozpocząć wydobywanie tekstu!

Uczenie aplikacji rozpoznawania tekstu

Chcę uruchomić rozpoznawanie tekstu w odpowiedzi na zdarzenie click, dlatego musimy zaimplementować OnClickListener:

import android.graphics.Bitmap; import android.os.Bundle; import android.widget.ImageView; import android.content.Intent; import android.widget.TextView; import android.view.View; import android.net.Uri; klasa publiczna MainActivity rozszerza BaseActivity implementuje View.OnClickListener {private Bitmap myBitmap; prywatny ImageView myImageView; prywatny TextView myTextView; @Override chronione void onCreate (pakiet saveInstanceState) {super.onCreate (saveInstanceState); setContentView (R.layout.activity_main); myTextView = findViewById (R.id.textView); myImageView = findViewById (R.id.imageView); findViewById (R.id.checkText) .setOnClickListener (this); } @Override public void onClick (Wyświetl widok) {switch (view.getId ()) {case R.id.checkText: if (myBitmap! = Null) {// W następnym kroku zaimplementujemy runTextRecog // runTextRecog (); } przerwa; }}

ML Kit może przetwarzać obrazy tylko w formacie FirebaseVisionImage, dlatego musimy przekonwertować nasz obraz na obiekt FirebaseVisionImage. Możesz utworzyć FirebaseVisionImage z mapy bitowej, media.Image, ByteBuffer lub tablicy bajtów. Ponieważ pracujemy z Bitmapami, musimy wywołać metodę narzędziową fromBitmap () klasy FirebaseVisionImage i przekazać ją do naszej Bitmapy.

private void runTextRecog () {FirebaseVisionImage image = FirebaseVisionImage.fromBitmap (myBitmap);

ML Kit ma różne klasy detektorów dla każdej operacji rozpoznawania obrazu. W przypadku tekstu musimy użyć klasy FirebaseVisionTextDetector, która wykonuje optyczne rozpoznawanie znaków (OCR) na obrazie.

Tworzymy instancję FirebaseVisionTextDetector, używając getVisionTextDetector:

Detektor FirebaseVisionTextDetector = FirebaseVision.getInstance (). GetVisionTextDetector ();

Następnie musimy sprawdzić tekst FirebaseVisionImage, wywołując metodę wykrywaniaInInSage () i przekazując jej obiekt FirebaseVisionImage. Musimy również zaimplementować wywołania zwrotne onSuccess i onFailure, a także odpowiednie nasłuchiwania, aby nasza aplikacja była powiadamiana, gdy tylko wyniki będą dostępne.

detektor.detectInImage (obraz) .addOnSuccessListener (nowy OnSuccessListener() {@Override // To //}}). AddOnFailureListener (new OnFailureListener () {@Override public void onFailure (wyjątek @NonNull) {// Zadanie nie powiodło się z wyjątkiem //}}); }

Jeśli ta operacja się nie powiedzie, wyświetlę toast, ale jeśli operacja się powiedzie, wywołam proces processExtractedText z odpowiedzią.

W tym momencie mój kod wykrywania tekstu wygląda następująco:

// Utwórz FirebaseVisionImage // private void runTextRecog () {FirebaseVisionImage image = FirebaseVisionImage.fromBitmap (myBitmap); // Utwórz instancję FirebaseVisionCloudTextDetector // FirebaseVisionTextDetector czujka = FirebaseVision.getInstance (). GetVisionTextDetector (); // Zarejestruj OnSuccessListener // detektor.detectInImage (obraz) .addOnSuccessListener (nowy OnSuccessListener() {@Override // Zaimplementuj wywołanie zwrotne onSuccess // public void onSuccess (teksty FirebaseVisionText) {// Wywołaj processExtractedText z odpowiedzią // processExtractedText (teksty); }}). addOnFailureListener (nowy OnFailureListener () {@Override // Zaimplementuj calback onFailure // public void onFailure (wyjątek @NonNull) {Toast.makeText (MainActivity.this, „Wyjątek”, Toast.LENGTH_LONG). pokaż ( );}}); }

Ilekroć nasza aplikacja otrzyma powiadomienie onSuccess, musimy przeanalizować wyniki.

Obiekt FirebaseVisionText może zawierać elementy, linie i bloki, przy czym każdy blok zazwyczaj odpowiada jednemu akapitowi tekstu. Jeśli FirebaseVisionText zwróci 0 bloków, wówczas wyświetlimy ciąg „no_text”, ale jeśli zawiera jeden lub więcej bloków, wyświetli pobrany tekst jako część naszego TextView.

private void processExtractedText (FirebaseVisionText firebaseVisionText) {myTextView.setText (null); if (firebaseVisionText.getBlocks (). size () == 0) {myTextView.setText (R.string.no_text); powrót; } for (FirebaseVisionText.Block block: firebaseVisionText.getBlocks ()) {myTextView.append (block.getText ()); }}}

Oto wypełniony kod MainActivity:

import android.graphics.Bitmap; import android.os.Bundle; import android.widget.ImageView; import android.content.Intent; import android.widget.TextView; import android.widget.Toast; import android.view.View; import android.net.Uri; import android.support.annotation.NonNull; import com.google.firebase.ml.vision.common.FirebaseVisionImage; import com.google.firebase.ml.vision.text.FirebaseVisionText; import com.google.firebase.ml.vision.text.FirebaseVisionTextDetector; import com.google.firebase.ml.vision.FirebaseVision; import com.google.android.gms.tasks.OnSuccessListener; import com.google.android.gms.tasks.OnFailureListener; klasa publiczna MainActivity rozszerza BaseActivity implementuje View.OnClickListener {private Bitmap myBitmap; prywatny ImageView myImageView; prywatny TextView myTextView; @Override chronione void onCreate (pakiet saveInstanceState) {super.onCreate (saveInstanceState); setContentView (R.layout.activity_main); myTextView = findViewById (R.id.textView); myImageView = findViewById (R.id.imageView); findViewById (R.id.checkText) .setOnClickListener (this); } @Override public void onClick (Wyświetl widok) {switch (view.getId ()) {case R.id.checkText: if (myBitmap! = Null) {runTextRecog (); } przerwa; }} @Override protected void onActivityResult (int requestCode, int resultCode, Intent data) {super.onActivityResult (requestCode, resultCode, dane); if (resultCode == RESULT_OK) {switch (requestCode) {case WRITE_STORAGE: checkPermission (requestCode); złamać; case SELECT_PHOTO: Uri dataUri = data.getData (); Ścieżka ciągu = MyHelper.getPath (this, dataUri); if (ścieżka == null) {myBitmap = MyHelper.resizePhoto (zdjęcie, to, dataUri, myImageView); } else {myBitmap = MyHelper.resizePhoto (zdjęcie, ścieżka, myImageView); } if (myBitmap! = null) {myTextView.setText (null); myImageView.setImageBitmap (myBitmap); } przerwa; }}} private void runTextRecog () {FirebaseVisionImage image = FirebaseVisionImage.fromBitmap (myBitmap); Detektor FirebaseVisionTextDetector = FirebaseVision.getInstance (). GetVisionTextDetector (); detektor.detectInImage (obraz) .addOnSuccessListener (nowy OnSuccessListener() {@Override public void onSuccess (teksty FirebaseVisionText) {processExtractedText (teksty); }}). addOnFailureListener (nowy OnFailureListener () {@Override public void onFailure (wyjątek @NonNull Exception) {Toast.makeText (MainActivity.this, „Exception”, Toast.LENGTH_LONG) .show ();}}); } private void processExtractedText (FirebaseVisionText firebaseVisionText) {myTextView.setText (null); if (firebaseVisionText.getBlocks (). size () == 0) {myTextView.setText (R.string.no_text); powrót; } for (FirebaseVisionText.Block block: firebaseVisionText.getBlocks ()) {myTextView.append (block.getText ()); }}}

Testowanie projektu

Czas zobaczyć Rozpoznawanie tekstu ML Kit w akcji! Zainstaluj ten projekt na urządzeniu z Androidem lub AVD, wybierz obraz z galerii, a następnie stuknij przycisk „Sprawdź tekst”. Aplikacja powinna odpowiedzieć, wyodrębniając cały tekst z obrazu, a następnie wyświetlając go w TextView.

Pamiętaj, że w zależności od rozmiaru obrazu i ilości zawartego w nim tekstu konieczne może być przewinięcie, aby zobaczyć cały wyodrębniony tekst.

Możesz także pobrać ukończony projekt z GitHub.

Podsumowując

Teraz wiesz, jak wykrywać i wyodrębniać tekst z obrazu za pomocą ML Kit.

Interfejs API rozpoznawania tekstu to tylko jedna część zestawu ML. Ten zestaw SDK oferuje również skanowanie kodów kreskowych, wykrywanie twarzy, oznaczanie obrazów i rozpoznawanie punktów orientacyjnych, z planami dodania kolejnych interfejsów API dla typowych przypadków użycia na urządzeniach mobilnych, w tym Smart Reply i interfejs API konturów twarzy o dużej gęstości.

Który interfejs API ML Kit najbardziej Cię interesuje? Daj nam znać w komentarzach poniżej!

Żyjemy w erze cyfrowej wzytkiego. To, co kiedyś trzymaliśmy w ręce, jet teraz przechowywane w nazym telefonie i chociaż jet to o wiele wygodniejze niż oldkulowa metoda zbierania i udotępniania zdjęć, ...

Każdy potrzebuje od czau do czau kilku dodatkowych dolarów. Nie jeteśmy jednak tak głupi, aby próbować prawić, że uwierzyz, że zarobiz na życie iedząc w domu, nie robiąc nic. Nie ma aplikac...

Zyskuje Popularność