Google의 Machine Learning SDK를 사용하여 이미지에서 텍스트를 추출하는 방법

작가: John Stephens
창조 날짜: 27 1 월 2021
업데이트 날짜: 5 칠월 2024
Anonim
구글 Vision API로 이미지에서 문자 추출하는 OCR 앱 제작하기  - 인공지능 앱인벤터 안드로이드 앱 개발/제작 강의
동영상: 구글 Vision API로 이미지에서 문자 추출하는 OCR 앱 제작하기 - 인공지능 앱인벤터 안드로이드 앱 개발/제작 강의

콘텐츠


또한 텍스트 인식 API를 번역 앱 또는 사용자가 어려움을 겪고있는 텍스트를 카메라로 가리키고 소리내어 읽을 수있는 접근성 서비스의 기초로 사용할 수 있습니다.

이 자습서에서는 사용자 갤러리의 모든 이미지에서 텍스트를 추출 할 수있는 앱을 만들어 광범위한 혁신적인 기능의 토대를 마련합니다. 이 자습서에서는 다루지 않겠지 만이 응용 프로그램을 장치의 카메라에 연결하여 사용자 주변의 텍스트를 실시간으로 캡처 할 수도 있습니다.

기기에서 또는 클라우드에서?

일부 ML Kit API는 기기에서만 사용할 수 있지만 일부는 텍스트 인식 API를 포함하여 기기와 클라우드에서 사용할 수 있습니다.

클라우드 기반 텍스트 API는 더 넓은 범위의 언어와 문자를 식별 할 수 있으며, 장치에 비해 더 높은 정확도를 약속합니다. 그러나 그것은 않습니다 인터넷에 연결되어 있어야하며 Blaze 수준 프로젝트에만 사용할 수 있습니다.

이 도움말에서는 Text Recognition API를 로컬에서 실행하므로 Blaze로 업그레이드했는지 또는 무료 Firebase Spark 요금제를 사용 중인지 여부에 관계없이 따라갈 수 있습니다.

ML Kit로 텍스트 인식 앱 만들기

원하는 설정으로 응용 프로그램을 작성하지만 프롬프트가 표시되면 "빈 활동"템플리트를 선택하십시오.

ML Kit SDK는 Firebase의 일부이므로 SHA-1 서명 인증서를 사용하여 프로젝트를 Firebase에 연결해야합니다. 프로젝트의 SHA-1을 얻으려면 :

  • Android Studio의 'Gradle'탭을 선택하십시오.
  • "Gradle 프로젝트"패널에서 두 번 클릭하여 프로젝트의 "루트"를 펼친 다음 "작업> Android> 서명 보고서"를 선택하십시오.
  • SHA-1 서명 인증서를 포함하여이 프로젝트에 대한 일부 정보를 표시하도록 Android Studio 창의 맨 아래에있는 패널이 업데이트되어야합니다.


프로젝트를 Firebase에 연결하는 방법 :

  • 웹 브라우저에서 Firebase 콘솔을 시작하십시오.
  • "프로젝트 추가"를 선택하십시오.
  • 프로젝트 이름을 정하십시오. "ML Test"를 사용하고 있습니다.
  • 이용 약관을 읽고 계속 진행하려면 "동의합니다 ..."와 "프로젝트 만들기"를 차례로 선택하십시오.
  • 'Android 앱에 Firebase 추가'를 선택하십시오.
  • 프로젝트의 패키지 이름을 입력하십시오.이 이름은 MainActivity 파일 상단과 매니페스트 안에 있습니다.
  • 프로젝트의 SHA-1 서명 인증서를 입력하십시오.
  • "앱 등록"을 클릭하십시오.
  • 'google-services.json 다운로드'를 선택하십시오.이 파일에는 API 키를 포함하여 프로젝트에 필요한 모든 Firebase 메타 데이터가 포함되어 있습니다.
  • Android Studio에서 google-services.json 파일을 프로젝트의 "app"디렉토리로 끌어다 놓습니다.

  • 프로젝트 레벨 build.gradle 파일을 열고 Google 서비스 클래스 경로를 추가하십시오.

classpath com.google.gms : google-services : 4.0.1

  • 앱 수준 build.gradle 파일을 열고 Firebase Core, Firebase ML Vision 및 모델 인터프리터 및 Google 서비스 플러그인에 대한 종속성을 추가하십시오.

플러그인 적용 : com.google.gms.google-services ... ... ... 종속성 {구현 fileTree (dir : libs, include :) 구현 com.google.firebase : firebase-core : 16.0.1 implementation com. google.firebase : firebase-ml-vision : 16.0.0 구현 com.google.firebase : firebase-ml-model-interpreter : 16.0.0

이제 Firebase 서버에 연결할 수 있도록 프로젝트를 실행해야합니다.


  • 실제 Android 스마트 폰 또는 태블릿 또는 Android 가상 장치 (AVD)에 앱을 설치하십시오.
  • Firebase 콘솔에서 '앱을 실행하여 설치 확인'을 선택하십시오.
  • 잠시 후 "축하합니다"가 표시됩니다. "콘솔 계속"을 선택하십시오.

Google의 사전 훈련 된 머신 러닝 모델 다운로드

기본적으로 ML Kit는 필요할 때만 모델을 다운로드하므로 사용자가 처음 텍스트를 추출하려고하면 앱이 OCR 모델을 다운로드합니다.

이는 잠재적으로 사용자 경험에 부정적인 영향을 줄 수 있습니다. 기능에 액세스하려고하면 앱이 실제로이 기능을 제공하기 전에 더 많은 리소스를 다운로드해야한다는 것을 발견하기 만하면됩니다. 최악의 시나리오에서는 앱에 필요할 때 (예 : 기기에 인터넷이 연결되어 있지 않은 경우) 필요한 리소스를 다운로드하지 못할 수도 있습니다.

앱에서 이러한 일이 발생하지 않도록하기 위해 설치시 필요한 OCR 모델을 다운로드하려고합니다.이 과정에서 Maniest를 약간 변경해야합니다.

매니페스트가 열려있는 동안 WRITE_EXTERNAL_STORAGE 권한을 추가하여이 자습서의 뒷부분에서 사용할 것입니다.

// WRITE_EXTERNAL_STORAGE 권한 추가 // // 다음을 추가 //

레이아웃 구축

쉬운 방법을 찾아서 다음으로 구성된 레이아웃을 만들어 보겠습니다.

  • ImageView. 처음에는 자리 표시자가 표시되지만 사용자가 갤러리에서 이미지를 선택하면 업데이트됩니다.
  • 텍스트 추출을 트리거하는 버튼입니다.
  • 추출 된 텍스트를 표시 할 TextView
  • ScrollView. 추출 된 텍스트가 화면에 깔끔하게 맞는다는 보장이 없기 때문에 TextView를 ScrollView 안에 배치하겠습니다.

완성 된 activity_main.xml 파일은 다음과 같습니다.

이 레이아웃은 "ic_placeholder"드로어 블을 참조하므로 지금 만들어 보겠습니다.

  • Android Studio 도구 모음에서 "파일> 새로 만들기> 이미지 자산"을 선택하십시오.
  • "아이콘 유형"드롭 다운을 열고 "작업 표시 줄 및 탭 아이콘"을 선택하십시오.
  • "클립 아트"라디오 버튼이 선택되어 있는지 확인하십시오.
  • “클립 아트”버튼을 클릭하십시오.
  • 자리 표시 자로 사용할 이미지를 선택하십시오. “사진에 추가”를 사용하고 있습니다.
  • "확인"을 클릭하십시오.
  • "테마"드롭 다운을 열고 "HOLO_LIGHT"를 선택하십시오.
  • "이름"필드에 "ic_placeholder"를 입력하십시오.
  • "다음"을 클릭하십시오. 정보를 읽고, 계속 진행하려면 "마침"을 클릭하십시오.

작업 표시 줄 아이콘 : 갤러리 앱 시작

다음으로 사용자 갤러리를 시작하여 이미지를 선택할 수있는 작업 표시 줄 항목을 만들어 보겠습니다.

“res / menu”디렉토리 안에있는 메뉴 리소스 파일 내에 작업 표시 줄 아이콘을 정의합니다. 프로젝트에이 디렉토리가 없으면 다음을 만들어야합니다.

  • 프로젝트의 "res"디렉토리를 Control- 클릭하고 "New> Android Resource Directory"를 선택하십시오.
  • "리소스 유형"드롭 다운을 열고 "메뉴"를 선택하십시오.
  • "디렉토리 이름"은 "메뉴"로 자동 업데이트되지만 그렇지 않은 경우 수동으로 이름을 바꿔야합니다.
  • "확인"을 클릭하십시오.

이제 메뉴 리소스 파일을 만들 준비가되었습니다 :

  • 프로젝트의 "메뉴"디렉토리를 Control- 클릭하고 "신규> 메뉴 리소스 파일"을 선택하십시오.
  • 이 파일 이름을 "my_menu"로 지정하십시오.
  • "확인"을 클릭하십시오.
  • “my_menu.xml”파일을 열고 다음을 추가하십시오.

// 모든 행동 //

메뉴 파일은 "action_gallery"문자열을 참조하므로 프로젝트의 res / values ​​/ strings.xml 파일을 열고이 자원을 작성하십시오. 여기있는 동안이 프로젝트에서 사용할 다른 문자열도 정의하고 있습니다.

갱도 이 앱은 기기의 파일에 액세스해야합니다. 텍스트를 찾을 수 없습니다

다음으로 Image Asset Studio를 사용하여 작업 표시 줄의 "ic_gallery"아이콘을 만듭니다.

  • "파일> 새로 만들기> 이미지 자산"을 선택하십시오.
  • "아이콘 유형"드롭 다운을 "작업 표시 줄 및 탭 아이콘"으로 설정하십시오.
  • "클립 아트"버튼을 클릭하십시오.
  • 드로어 블을 선택하십시오. “이미지”를 사용하고 있습니다.
  • "확인"을 클릭하십시오.
  • 이 아이콘이 작업 표시 줄에 명확하게 표시되도록하려면 "테마"드롭 다운을 열고 "HOLO_DARK"를 선택하십시오.
  • 이 아이콘의 이름을 "ic_gallery"로 지정하십시오.
  • ““다음”을 클릭 한 후“마침”을 클릭하십시오.

권한 요청 및 클릭 이벤트 처리

메뉴 인스턴스화, 작업 표시 줄 클릭 이벤트 처리, 장치 스토리지 액세스 요청 등 별도의 BaseActivity 클래스에서 텍스트 인식 API와 직접 관련이없는 모든 작업을 수행하겠습니다.

  • Android Studio의 툴바에서 "파일> 새로 만들기> Java 클래스"를 선택하십시오.
  • 이 클래스의 이름을 "BaseActivity"로 지정하십시오.
  • "확인"을 클릭하십시오.
  • BaseActivity를 열고 다음을 추가하십시오.

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; android.os.Bundle 가져 오기; import android.content.DialogInterface; android.content.Intent 가져 오기; android.Manifest 가져 오기; import android.provider.MediaStore; import android.view.Menu; import android.view.MenuItem; import android.content.pm.PackageManager; android.net.Uri 가져 오기; android.provider.Settings 가져 오기; import android.support.annotation.NonNull; import android.support.annotation.Nullable; java.io.File 가져 오기; 공개 클래스 BaseActivity는 AppCompatActivity를 확장합니다. {public static final int WRITE_STORAGE = 100; public static final int SELECT_PHOTO = 102; 공개 정적 최종 문자열 ACTION_BAR_TITLE = "action_bar_title"; 공공 파일 사진; @Override protected void onCreate (@Nullable Bundle savedInstanceState) {super.onCreate (savedInstanceState); ActionBar actionBar = getSupportActionBar (); if (actionBar! = null) {actionBar.setDisplayHomeAsUpEnabled (true); actionBar.setTitle (getIntent (). getStringExtra (ACTION_BAR_TITLE)); }} @public boolean을 재정의 함 onCreateOptionsMenu (메뉴 메뉴) {getMenuInflater (). inflate (R.menu.my_menu, 메뉴); true를 반환; } @public public boolean 재정의 onOptionsItemSelected (MenuItem item) {switch (item.getItemId ()) {// "gallery_action"을 선택한 경우 ... // case R.id.gallery_action : // ... 확인했습니다 WRITE_STORAGE 권한 // checkPermission (WRITE_STORAGE); 단절; } return super.onOptionsItemSelected (item); } @void public void onRequestPermissionsResult (int requestCode, @NonNull String permissions, @NonNull int grantResults) {super.onRequestPermissionsResult (requestCode, permissions, grantResults); switch (requestCode) {case WRITE_STORAGE : // 권한 요청이 승인되면 ... // if (grantResults.length> 0 && grantResults == PackageManager.PERMISSION_GRANTED) {//...call selectPicture // selectPicture ( ); // 권한 요청이 거부되면 ... //} else {//...“permission_request”문자열을 표시합니다 .// requestPermission (this, requestCode, R.string.permission_request); } 휴식; }} // 권한 요청 대화 상자 표시 // public static void requestPermission (최종 활동 활동, 최종 int requestCode, int msg) {AlertDialog.Builder alert = new AlertDialog.Builder (activity); alert.set (msg); alert.setPositiveButton (android.R.string.ok, new DialogInterface.OnClickListener () {@ public void onClick (DialogInterface dialogInterface, int i) 재정의 {{InterInterface.dismiss (); 의도 permissonIntent = 새로운 의도 (Settings.ACTION_APPLICATION_DETAILS_SETTINGS); permissonIntent .setData (Uri.parse ( "package :"+ activity.getPackageName ())); activity.startActivityForResult (permissonIntent, requestCode);}}); alert.setNegativeButton (android.R.string.cancel, new DialogInterface.OnClickListener () {@ public void onClick (DialogInterface dialogInterface, int i) {dialogInterface.dismiss ();}}); alert.setCancelable (false); alert.show (); } // 사용자가 WRITE_STORAGE 권한을 부여했는지 확인합니다 ./ public void checkPermission (int requestCode) {switch (requestCode) {case WRITE_STORAGE : int hasWriteExternalStoragePermission = ActivityCompat.checkSelfPermission (this, Manifest.permission.WRITE_EXTERNAL_STORAGE); // 외부 저장소에 액세스 할 수있는 경우 ... // if (hasWriteExternalStoragePermission == PackageManager.PERMISSION_GRANTED) {// ... selectPicture를 호출하면 사용자가 이미지를 선택할 수있는 활동이 시작됩니다 .// selectPicture (); // 권한이 부여되지 않은 경우 ... //} else {// ... 권한 요청 // ActivityCompat.requestPermissions (this, new String {Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode); } 휴식; }} private void selectPicture () {photo = MyHelper.createTempFile (photo); 의도 의도 = 새로운 의도 (Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); // 사용자가 이미지를 선택할 수있는 활동을 시작합니다 .// startActivityForResult (intent, SELECT_PHOTO); }}

이 시점에서 프로젝트는 MyHelper.createTempFile을 해결할 수 없다고 불평해야합니다. 지금 구현해 봅시다!

createTempFile을 사용하여 이미지 크기 조정

새로운“MyHelper”클래스를 만듭니다. 이 클래스에서는 텍스트 인식 API로 처리 할 준비가 된 사용자가 선택한 이미지의 크기를 조정합니다.

android.graphics.Bitmap 가져 오기; import android.graphics.BitmapFactory; import android.content.Context; import android.database.Cursor; android.os.Environment 가져 오기; import android.widget.ImageView; import android.provider.MediaStore; android.net.Uri 가져 오기; 정적 android.graphics.BitmapFactory.decodeFile 가져 오기; 정적 android.graphics.BitmapFactory.decodeStream 가져 오기; java.io.File 가져 오기; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; 공개 클래스 MyHelper {공개 정적 문자열 getPath (컨텍스트 컨텍스트, URI) {문자열 경로 = ""; 문자열 투영 = {MediaStore.Images.Media.DATA}; 커서 커서 = context.getContentResolver (). query (uri, projection, null, null, null); int column_index; if (cursor! = null) {column_index = cursor.getColumnIndexOrThrow (MediaStore.Images.Media.DATA); cursor.moveToFirst (); 경로 = cursor.getString (열 _ 인덱스); cursor.close (); } 복귀 경로; } 공개 정적 파일 createTempFile (파일 파일) {파일 디렉토리 = 새 파일 (Environment.getExternalStorageDirectory (). getPath () + "/com.jessicathornsby.myapplication"); if (! directory.exists () ||! directory.isDirectory ()) {directory.mkdirs (); } if (file == null) {file = 새 파일 (디렉토리, "orig.jpg"); } 반환 파일; } 공개 정적 비트 맵 resizePhoto (파일 이미지 파일, 컨텍스트 컨텍스트, URI, ImageView보기) {BitmapFactory.Options newOptions = new BitmapFactory.Options (); try {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 ()); return compressPhoto (imageFile, BitmapFactory.decodeStream (context.getContentResolver (). openInputStream (uri), null, newOptions)); } catch (FileNotFoundException 예외) {exception.printStackTrace (); null을 돌려줍니다. }} public static Bitmap resizePhoto (파일 imageFile, 문자열 경로, ImageView보기) {BitmapFactory.Options 옵션 = 새 BitmapFactory.Options (); 디코드 파일 (경로, 옵션); int photoHeight = 옵션 .outHeight; int photoWidth = 옵션 .outWidth; options.inSampleSize = Math.min (photoWidth / view.getWidth (), photoHeight / view.getHeight ()); return compressPhoto (imageFile, BitmapFactory.decodeFile (경로, 옵션)); } 개인 정적 비트 맵 compressPhoto (파일 photoFile, 비트 맵 비트 맵) {try {FileOutputStream fOutput = new FileOutputStream (photoFile); bitmap.compress (Bitmap.CompressFormat.JPEG, 70, fOutput); fOutput.close (); } catch (IOException 예외) {exception.printStackTrace (); } 리턴 비트 맵; }}

이미지를 ImageView로 설정

다음으로 MainActivity 클래스에서 onActivityResult ()를 구현하고 사용자가 선택한 이미지를 ImageView로 설정해야합니다.

android.graphics.Bitmap 가져 오기; android.os.Bundle 가져 오기; import android.widget.ImageView; android.content.Intent 가져 오기; import android.widget.TextView; android.net.Uri 가져 오기; 공개 클래스 MainActivity 확장 BaseActivity {private Bitmap myBitmap; 개인 ImageView myImageView; 개인 TextView myTextView; @Override protected void onCreate (번들 저장 인스턴스 상태) {super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); myTextView = findViewById (R.id.textView); myImageView = findViewById (R.id.imageView); } @ protected protected void onActivityResult (int requestCode, int resultCode, Intent data) {super.onActivityResult (requestCode, resultCode, data); if (resultCode == RESULT_OK) {switch (requestCode) {경우 WRITE_STORAGE : checkPermission (requestCode); 단절; 경우 SELECT_PHOTO : Uri dataUri = data.getData (); 문자열 경로 = MyHelper.getPath (this, dataUri); if (path == null) {myBitmap = MyHelper.resizePhoto (사진, 이것, dataUri, myImageView); } else {myBitmap = MyHelper.resizePhoto (사진, 경로, myImageView); } if (myBitmap! = null) {myTextView.setText (null); myImageView.setImageBitmap (myBitmap); } 휴식; }}}}

실제 Android 디바이스 또는 AVD에서이 프로젝트를 실행하고 조치 표시 줄 아이콘에 클릭을 제공하십시오. 메시지가 표시되면 WRITE_STORAGE 권한을 부여하고 갤러리에서 이미지를 선택하십시오. 이 이미지는 이제 앱의 UI에 표시됩니다.

이제 기초 작업을 완료했으며 텍스트 추출을 시작할 준비가되었습니다!

텍스트 인식을위한 앱 교육

클릭 이벤트에 대한 응답으로 텍스트 인식을 트리거하고 싶습니다. 따라서 OnClickListener를 구현해야합니다.

android.graphics.Bitmap 가져 오기; android.os.Bundle 가져 오기; import android.widget.ImageView; android.content.Intent 가져 오기; import android.widget.TextView; import android.view.View; android.net.Uri 가져 오기; Public 클래스 MainActivity 확장 BaseActivity 구현 View.OnClickListener {private Bitmap myBitmap; 개인 ImageView myImageView; 개인 TextView myTextView; @Override protected void onCreate (번들 저장 인스턴스 상태) {super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); myTextView = findViewById (R.id.textView); myImageView = findViewById (R.id.imageView); findViewById (R.id.checkText) .setOnClickListener (this); } @void public void onClick (View view) 재정의 {switch (view.getId ()) {case R.id.checkText : if (myBitmap! = null) {// 다음 단계에서 runTextRecog를 구현합니다 // runTextRecog (); } 휴식; }}

ML Kit는 이미지가 FirebaseVisionImage 형식 일 때만 이미지를 처리 ​​할 수 ​​있으므로 이미지를 FirebaseVisionImage 객체로 변환해야합니다. 비트 맵, media.Image, ByteBuffer 또는 바이트 배열에서 FirebaseVisionImage를 생성 할 수 있습니다. 비트 맵을 사용하고 있으므로 FirebaseVisionImage 클래스의 fromBitmap () 유틸리티 메소드를 호출하여 비트 맵에 전달해야합니다.

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

ML Kit에는 각 이미지 인식 작업에 대해 서로 다른 검출기 등급이 있습니다. 텍스트의 경우 이미지에서 광학 문자 인식 (OCR)을 수행하는 FirebaseVisionTextDetector 클래스를 사용해야합니다.

getVisionTextDetector를 사용하여 FirebaseVisionTextDetector의 인스턴스를 만듭니다.

FirebaseVisionTextDetector 감지기 = FirebaseVision.getInstance (). getVisionTextDetector ();

다음으로 detectInImage () 메소드를 호출하고 FirebaseVisionImage 객체를 전달하여 텍스트의 FirebaseVisionImage를 확인해야합니다. 또한 onSuccess 및 onFailure 콜백과 해당 리스너를 구현하여 결과가 제공 될 때마다 앱에 알림을 제공해야합니다.

detector.detectInImage (image) .addOnSuccessListener (새로운 OnSuccessListener() {@Override // To do //}}). addOnFailureListener (new OnFailureListener () {@Override public void onFailure (@NonNull Exception exception) {// 예외로 작업 실패 //}}); }

이 작업이 실패하면 토스트가 표시되지만 작업이 성공하면 응답과 함께 processExtractedText를 호출합니다.

이 시점에서 내 텍스트 감지 코드는 다음과 같습니다.

// FirebaseVisionImage 생성 // private void runTextRecog () {FirebaseVisionImage image = FirebaseVisionImage.fromBitmap (myBitmap); // FirebaseVisionCloudTextDetector의 인스턴스 생성 // FirebaseVisionTextDetector detector = FirebaseVision.getInstance (). getVisionTextDetector (); // OnSuccessListener 등록 // detector.detectInImage (image) .addOnSuccessListener (새로운 OnSuccessListener() {@Override // onSuccess 콜백 구현 // public void onSuccess (FirebaseVisionText texts) {// 응답으로 processExtractedText를 호출 // processExtractedText (texts); }}). addOnFailureListener (new OnFailureListener () {@Override // onFailure calback // public void onFailure 구현 (@NonNull 예외 예외) {Toast.makeText (MainActivity.this, "Exception", Toast.LENGTH_LONG) .show ( );}}); }

앱이 onSuccess 알림을받을 때마다 결과를 파싱해야합니다.

FirebaseVisionText 객체는 요소, 선 및 블록을 포함 할 수 있으며, 각 블록은 일반적으로 단일 텍스트 단락과 같습니다. FirebaseVisionText가 0 개의 블록을 반환하면 "no_text"문자열이 표시되지만 하나 이상의 블록이 포함 된 경우 검색된 텍스트가 TextView의 일부로 표시됩니다.

private void processExtractedText (FirebaseVisionText firebaseVisionText) {myTextView.setText (null); if (firebaseVisionText.getBlocks (). size () == 0) {myTextView.setText (R.string.no_text); 반환; } (FirebaseVisionText.Block 블록의 경우 : firebaseVisionText.getBlocks ()) {myTextView.append (block.getText ()); }}}

완성 된 MainActivity 코드는 다음과 같습니다.

android.graphics.Bitmap 가져 오기; android.os.Bundle 가져 오기; import android.widget.ImageView; android.content.Intent 가져 오기; import android.widget.TextView; android.widget.Toast 가져 오기; import android.view.View; 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; Public 클래스 MainActivity 확장 BaseActivity 구현 View.OnClickListener {private Bitmap myBitmap; 개인 ImageView myImageView; 개인 TextView myTextView; @Override protected void onCreate (번들 저장 인스턴스 상태) {super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); myTextView = findViewById (R.id.textView); myImageView = findViewById (R.id.imageView); findViewById (R.id.checkText) .setOnClickListener (this); } @void public void onClick (View view) {switch (view.getId ()) {case R.id.checkText : if (myBitmap! = null) {runTextRecog (); } 휴식; }} @Protected void 무효화 onActivityResult (int requestCode, int resultCode, Intent data) {super.onActivityResult (requestCode, resultCode, data); if (resultCode == RESULT_OK) {switch (requestCode) {경우 WRITE_STORAGE : checkPermission (requestCode); 단절; 경우 SELECT_PHOTO : Uri dataUri = data.getData (); 문자열 경로 = MyHelper.getPath (this, dataUri); if (path == null) {myBitmap = MyHelper.resizePhoto (사진, 이것, dataUri, myImageView); } else {myBitmap = MyHelper.resizePhoto (사진, 경로, myImageView); } if (myBitmap! = null) {myTextView.setText (null); myImageView.setImageBitmap (myBitmap); } 휴식; }}} private void runTextRecog () {FirebaseVisionImage image = FirebaseVisionImage.fromBitmap (myBitmap); FirebaseVisionTextDetector 감지기 = FirebaseVision.getInstance (). getVisionTextDetector (); detector.detectInImage (image) .addOnSuccessListener (새로운 OnSuccessListener() {@public void onSuccess (FirebaseVisionText texts) 재정의 {processExtractedText (texts); }}). addOnFailureListener (new OnFailureListener () {@ public void onFailure (@NonNull 예외 예외 무시) {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); 반환; } (FirebaseVisionText.Block 블록의 경우 : firebaseVisionText.getBlocks ()) {myTextView.append (block.getText ()); }}}

프로젝트 테스트

이제 ML Kit의 텍스트 인식이 작동하는 것을 볼 차례입니다! 이 프로젝트를 Android 장치 또는 AVD에 설치하고 갤러리에서 이미지를 선택한 다음 "텍스트 확인"버튼을 탭하십시오. 앱은 이미지에서 모든 텍스트를 추출한 다음 TextView에 표시하여 응답해야합니다.

이미지의 크기와 이미지에 포함 된 텍스트의 양에 따라 추출 된 텍스트를 모두 보려면 스크롤해야 할 수도 있습니다.

완성 된 프로젝트를 GitHub에서 다운로드 할 수도 있습니다.

마무리

이제 ML Kit를 사용하여 이미지에서 텍스트를 감지하고 추출하는 방법을 알게되었습니다.

Text Recognition API는 ML Kit의 일부일뿐입니다. 이 SDK는 또한 바코드 스캔, 얼굴 감지, 이미지 라벨링 및 랜드 마크 인식을 제공하며 Smart Reply 및 고밀도 얼굴 윤곽 API를 포함한 일반적인 모바일 사용 사례에 더 많은 API를 추가 할 계획입니다.

어떤 ML Kit API를 가장 관심이 있습니까? 아래 의견에 알려주십시오!

우리와 같은 사람이라면 고품질 장치 월페이퍼에 감사드립니다. 스마트 폰, 노트북 또는 데스크탑이든 좋은 벽지는 모든 차이를 만들 수 있습니다. Google은 비즈니스에서 최고의 스톡 월페이퍼를 만듭니다. 우리는 모든 Pixel 휴대 전화에 사전로드되어 제공되는 Pixel 라인의“살아있는 우주”라이브 월페이퍼를 특히 좋아합니다....

2019 년 8 월 12 일 업데이트 (05:15 ET) : 2017 년 1 월 4 일 이전에 Google Pixel 또는 Google Pixel XL을 보유하고 있으며 해당 기기에서 마이크 문제가 발생한 경우 이제 소유권 주장을 제기하고 상당한 현금을 벌 수 있습니다....

인기있는 기사