วิธีดึงข้อความจากรูปภาพด้วย Machine Learning SDK ของ Google

ผู้เขียน: John Stephens
วันที่สร้าง: 27 มกราคม 2021
วันที่อัปเดต: 5 กรกฎาคม 2024
Anonim
Google Vision API in Python (Part 3): Detect and Extract Text (Image)
วิดีโอ: Google Vision API in Python (Part 3): Detect and Extract Text (Image)

เนื้อหา


นอกจากนี้คุณยังสามารถใช้ Text Recognition API เป็นพื้นฐานสำหรับแอปแปลภาษาหรือบริการการเข้าถึงที่ผู้ใช้สามารถเล็งกล้องไปที่ข้อความใด ๆ ที่พวกเขากำลังดิ้นรนและอ่านออกเสียงพวกเขา

ในบทช่วยสอนนี้เราจะวางรากฐานสำหรับคุณลักษณะใหม่ ๆ ที่หลากหลายโดยการสร้างแอปที่สามารถแยกข้อความจากภาพใด ๆ ในแกลเลอรีของผู้ใช้ แม้ว่าเราจะไม่ครอบคลุมในบทช่วยสอนนี้ แต่คุณสามารถจับข้อความจากสภาพแวดล้อมของผู้ใช้แบบเรียลไทม์โดยเชื่อมต่อแอปพลิเคชันนี้เข้ากับกล้องของอุปกรณ์

บนอุปกรณ์หรือในคลาวด์

ML Kit APIs บางตัวมีเฉพาะในอุปกรณ์เท่านั้น แต่มีบางอย่างบนอุปกรณ์และในระบบคลาวด์รวมถึง API การจดจำข้อความ

API ข้อความบนคลาวด์สามารถระบุภาษาและอักขระที่หลากหลายยิ่งขึ้นและรับประกันความถูกต้องได้ดีกว่าคู่ของอุปกรณ์ อย่างไรก็ตามมัน ทำ ต้องใช้การเชื่อมต่ออินเทอร์เน็ตที่ใช้งานได้และจะใช้ได้เฉพาะสำหรับโครงการในระดับ Blaze เท่านั้น

ในบทความนี้เราจะเรียกใช้ API การจดจำข้อความในเครื่องเพื่อให้คุณสามารถติดตามได้ไม่ว่าคุณจะอัปเกรดเป็น Blaze หรือคุณกำลังอยู่ในแผน Firebase Spark ฟรี


การสร้างแอปจดจำข้อความด้วย ML Kit

สร้างแอปพลิเคชันด้วยการตั้งค่าที่คุณเลือก แต่เมื่อได้รับแจ้งให้เลือกเทมเพลต“ กิจกรรมที่ว่างเปล่า”

ML Kit SDK เป็นส่วนหนึ่งของ Firebase ดังนั้นคุณจะต้องเชื่อมต่อโครงการของคุณกับ Firebase โดยใช้ใบรับรองการลงนาม SHA-1 วิธีรับ SHA-1 ของโครงการของคุณ:

  • เลือกแท็บ“ Gradle” ของ Android Studio
  • ในแผง "โครงการ Gradle" ดับเบิลคลิกเพื่อขยาย "รูทโครงการ" ของคุณจากนั้นเลือก "งาน> Android> รายงานการลงนาม"
  • พาเนลที่ด้านล่างของหน้าต่าง Android Studio ควรอัปเดตเพื่อแสดงข้อมูลบางอย่างเกี่ยวกับโครงการนี้ - รวมถึงใบรับรองการลงนาม SHA-1

ในการเชื่อมต่อโครงการของคุณกับ Firebase:

  • ในเว็บเบราว์เซอร์ของคุณให้เปิดคอนโซล Firebase
  • เลือก“ เพิ่มโครงการ”
  • ตั้งชื่อโครงการของคุณ ฉันใช้“ การทดสอบ ML”
  • อ่านข้อกำหนดในการให้บริการและหากคุณยินดีที่จะดำเนินการต่อให้เลือก“ ฉันยอมรับ…” แล้วตามด้วย“ สร้างโครงการ”
  • เลือก“ เพิ่ม Firebase ไปยังแอพ Android ของคุณ”
  • ป้อนชื่อแพคเกจของโครงการซึ่งคุณจะพบที่ด้านบนของไฟล์ MainActivity และใน Manifest
  • ป้อนใบรับรองการลงนาม SHA-1 ของโครงการของคุณ
  • คลิก“ ลงทะเบียนแอพ”
  • เลือก "ดาวน์โหลด google-services.json" ไฟล์นี้มีข้อมูลเมตาของ Firebase ที่จำเป็นทั้งหมดสำหรับโครงการของคุณรวมถึงคีย์ API
  • ใน Android Studio ให้ลากและวางไฟล์ google-services.json ลงในไดเรกทอรี "แอป" ของโครงการ


  • เปิดไฟล์ build.gradle ระดับโครงการและเพิ่ม classpath ของบริการ 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, รวม:) การนำไปใช้งาน com.google.firebase: firebase-core: 16.0.1 com การปรับใช้ google.firebase: firebase-ml-vision: การใช้งาน 16.0.0 com.google.firebase: firebase-ml-model-interpreter: 16.0.0

ณ จุดนี้คุณจะต้องเรียกใช้โครงการของคุณเพื่อให้สามารถเชื่อมต่อกับเซิร์ฟเวอร์ Firebase:

  • ติดตั้งแอปของคุณบนสมาร์ทโฟนหรือแท็บเล็ต Android จริงหรืออุปกรณ์ Android เสมือน (AVD)
  • ใน Firebase Console เลือก“ เรียกใช้แอปเพื่อตรวจสอบการติดตั้ง”
  • หลังจากนั้นซักครู่คุณควรเห็น“ ขอแสดงความยินดี” เลือก“ ดำเนินการต่อไปยังคอนโซล”

ดาวน์โหลดโมเดลการเรียนรู้ของเครื่องที่ผ่านการฝึกอบรมมาแล้วของ Google

ตามค่าเริ่มต้น ML Kit จะดาวน์โหลดเฉพาะรุ่นและเมื่อต้องการดังนั้นแอปของเราจะดาวน์โหลดรุ่น OCR เมื่อผู้ใช้พยายามดึงข้อความเป็นครั้งแรก

สิ่งนี้อาจมีผลกระทบด้านลบต่อประสบการณ์ของผู้ใช้ - ลองจินตนาการถึงการเข้าถึงคุณลักษณะเฉพาะเมื่อพบว่าแอปต้องดาวน์โหลดทรัพยากรเพิ่มเติมก่อนจึงจะสามารถส่งมอบคุณสมบัตินี้ได้ ในกรณีที่เลวร้ายที่สุดแอปของคุณอาจไม่สามารถดาวน์โหลดทรัพยากรที่ต้องการได้เมื่อต้องการตัวอย่างเช่นหากอุปกรณ์ไม่มีการเชื่อมต่ออินเทอร์เน็ต

เพื่อให้แน่ใจว่าสิ่งนี้จะไม่เกิดขึ้นกับแอพของเราฉันจะดาวน์โหลดรุ่น OCR ที่จำเป็นในเวลาติดตั้งซึ่งต้องมีการเปลี่ยนแปลง Maniest

ในขณะที่เราเปิดการแสดงฉันจะเพิ่มสิทธิ์ WRITE_EXTERNAL_STORAGE ซึ่งเราจะใช้ในภายหลังในบทช่วยสอนนี้

// เพิ่มสิทธิ์ WRITE_EXTERNAL_STORAGE // // เพิ่มดังต่อไปนี้ //

สร้างเลย์เอาต์

มาช่วยกันจัดการเรื่องง่าย ๆ และสร้างเลย์เอาต์ที่ประกอบด้วย:

  • ImageView เริ่มแรกจะแสดงตัวยึดตำแหน่ง แต่จะอัปเดตเมื่อผู้ใช้เลือกรูปภาพจากแกลเลอรี
  • ปุ่มซึ่งทำให้เกิดการแยกข้อความ
  • TextView ที่เราจะแสดงข้อความที่แยกออกมา
  • ScrollView เนื่องจากไม่มีการรับประกันว่าข้อความที่แยกจะพอดีกับหน้าจออย่างเรียบร้อยฉันจะวาง TextView ไว้ใน ScrollView

นี่คือไฟล์ activity_main.xml ที่เสร็จสิ้นแล้ว:

รูปแบบนี้อ้างอิงถึง "ic_placeholder" drawable ดังนั้นให้สร้างตอนนี้:

  • เลือก“ ไฟล์> ใหม่> สินทรัพย์รูปภาพ” จากแถบเครื่องมือ Android Studio
  • เปิดเมนูแบบเลื่อนลง“ ประเภทไอคอน” แล้วเลือก“ ไอคอนแถบการกระทำและแท็บ”
  • ตรวจสอบให้แน่ใจว่าได้เลือกปุ่มตัวเลือก“ ภาพตัดปะ”
  • คลิกปุ่ม“ ภาพตัดปะ”
  • เลือกภาพที่คุณต้องการใช้เป็นตัวยึดตำแหน่งของคุณ ฉันใช้“ เพิ่มในรูปภาพ”
  • คลิก“ ตกลง”
  • เปิดเมนูแบบเลื่อนลง "ชุดรูปแบบ" และเลือก "HOLO_LIGHT"
  • ในฟิลด์“ ชื่อ,” ให้ป้อน“ ic_placeholder”
  • คลิก "ถัดไป" อ่านข้อมูลและหากคุณยินดีที่จะดำเนินการต่อให้คลิก "เสร็จสิ้น"

ไอคอนแถบการทำงาน: การเรียกใช้แอพคลังภาพ

ต่อไปฉันจะสร้างรายการแถบการกระทำที่จะเปิดแกลเลอรีของผู้ใช้พร้อมให้พวกเขาเลือกภาพ

คุณกำหนดไอคอนแถบการกระทำภายในไฟล์ทรัพยากรของเมนูซึ่งอยู่ในไดเรกทอรี“ res / menu” หากโครงการของคุณไม่มีไดเรกทอรีนี้คุณจะต้องสร้างมันขึ้นมา:

  • ควบคุมคลิกที่ไดเรกทอรี“ res” ของโปรเจ็กต์ของคุณและเลือก“ ใหม่> Android Resource Directory”
  • เปิดเมนูแบบเลื่อนลง“ ประเภททรัพยากร” และเลือก“ เมนู”
  • "ชื่อไดเรกทอรี" ควรอัปเดตเป็น "เมนู" โดยอัตโนมัติ แต่หากไม่เป็นเช่นนั้นคุณจะต้องเปลี่ยนชื่อด้วยตนเอง
  • คลิก“ ตกลง”

คุณพร้อมที่จะสร้างไฟล์ทรัพยากรเมนูแล้ว

  • ควบคุมคลิกไดเรกทอรี "เมนู" ของโครงการและเลือก "ใหม่> ไฟล์ทรัพยากรเมนู"
  • ตั้งชื่อไฟล์นี้“ my_menu”
  • คลิก“ ตกลง”
  • เปิดไฟล์“ my_menu.xml” และเพิ่มรายการต่อไปนี้:

// สร้าง องค์ประกอบสำหรับทุกการกระทำ //

ไฟล์เมนูอ้างอิงถึงสตริง“ action_gallery” ดังนั้นให้เปิดไฟล์ res / values ​​/ strings.xml ของโปรเจ็กต์ของคุณและสร้างทรัพยากรนี้ ในขณะที่ฉันอยู่ที่นี่ฉันจะกำหนดสตริงอื่น ๆ ที่เราจะใช้ในโครงการนี้ด้วย

เฉลียง แอพนี้จำเป็นต้องเข้าถึงไฟล์ในอุปกรณ์ของคุณ ไม่พบข้อความ

จากนั้นใช้ Image Asset Studio เพื่อสร้างไอคอน“ ic_gallery” ของแถบแอ็คชัน:

  • เลือก“ ไฟล์> ใหม่> สินทรัพย์รูปภาพ”
  • ตั้งค่าแบบเลื่อนลง“ ประเภทไอคอน” เป็น“ แถบการกระทำและไอคอนแท็บ”
  • คลิกปุ่ม "ภาพตัดปะ"
  • เลือก drawable; ฉันกำลังใช้ "รูปภาพ"
  • คลิก“ ตกลง”
  • เพื่อให้แน่ใจว่าไอคอนนี้จะมองเห็นได้ชัดเจนในแถบการกระทำให้เปิดเมนูแบบเลื่อนลง“ ธีม” และเลือก“ HOLO_DARK”
  • ตั้งชื่อไอคอนนี้“ ic_gallery”
  • “ คลิก“ ถัดไป” ตามด้วย“ เสร็จสิ้น”

การจัดการคำขอการอนุญาตและเหตุการณ์คลิก

ฉันจะทำงานทั้งหมดที่ไม่เกี่ยวข้องโดยตรงกับ Text Recognition API ในคลาส BaseActivity ที่แยกต่างหากรวมถึงการสร้างเมนูการจัดการเหตุการณ์คลิกของแถบแอ็คชันและร้องขอการเข้าถึงที่เก็บข้อมูลของอุปกรณ์

  • เลือก“ ไฟล์> ใหม่> คลาส Java” จากแถบเครื่องมือของ Android Studio
  • ตั้งชื่อคลาสนี้ว่า "BaseActivity"
  • คลิก“ ตกลง”
  • เปิด BaseActivity และเพิ่มรายการต่อไปนี้:

นำเข้า android.app.Activity; นำเข้า android.support.v4.app.ActivityCompat; นำเข้า android.support.v7.app.ActionBar; นำเข้า android.support.v7.app.AlertDialog; นำเข้า android.support.v7.app.AppCompatActivity; นำเข้า android.os.Bundle; นำเข้า android.content.DialogInterface; นำเข้า android.content.Tent; android.Manifest นำเข้า; นำเข้า android.provider.MediaStore; นำเข้า android.view.Menu; นำเข้า android.view.MenuItem; นำเข้า android.content.pm แพคเกจผู้จัดการ; android.net.Uri นำเข้า นำเข้า android.provider การตั้งค่า; นำเข้า android.support.annotation.NonNull; นำเข้า android.support.annotation.Nullable; นำเข้า java.io.File; BaseActivity ระดับสาธารณะขยาย AppCompatActivity {สาธารณะคงที่สุดท้าย int WRITE_STORAGE = 100; สาธารณะคงที่สุดท้าย int SELECT_PHOTO = 102; String สาธารณะสุดท้ายสุดท้าย ACTION_BAR_TITLE = "action_bar_title"; รูปถ่ายไฟล์สาธารณะ @Override ที่ได้รับการป้องกันเป็นโมฆะ onCreate (@Nullable Bundle บันทึกInstanceState) {super.onCreate (saveInstanceState); ActionBar actionBar = getSupportActionBar (); if (actionBar! = null) {actionBar.setDisplayHomeAsUpEnabled (จริง); actionBar.setTitle (getIntent () getStringExtra (ACTION_BAR_TITLE).); }} @Override บูลีนสาธารณะ onCreateOptionsMenu (เมนูเมนู) {getMenuInflater (). ขยายตัว (R.menu.my_menu เมนู); กลับจริง } @Override บูลีนสาธารณะ onOptionsItemSelected (รายการเมนู) {switch (item.getItemId ()) {// หากเลือก“ gallery_action” ไว้แล้ว ... // กรณี R.id.gallery_action: //...check เรามี สิทธิ์ WRITE_STORAGE // checkPermission (WRITE_STORAGE); ทำลาย; } คืนค่า super.onOptionsItemSelected (รายการ); } @Override โมฆะสาธารณะ onRequestPermissionsResult (int requestCode, @NonNull สิทธิ์การใช้งานสตริง, @NonNull การให้สิทธิ์ int ไม่ จำกัด จำนวน) {super.onRequestPermissionsResult (requestCode, สิทธิ์, GrantResults); switch (requestCode) {case WRITE_STORAGE: // หากได้รับการร้องขอสิทธิ์แล้ว ... // ถ้า (grantResults.length> 0 && GrantResults == PackageManager.PERMISSION_GRANTED) {//...call selectPicture // selectPicture (selectCicture) ); // ถ้าคำขอการอนุญาตถูกปฏิเสธดังนั้น ... //} else {//...display สตริง“ permission_request” string // requestPermission (สิ่งนี้ requestCode, R.string.permission_request); } พัก; }} // แสดงไดอะล็อกการร้องขอการอนุญาต // โมฆะ staticPermission แบบสาธารณะ (กิจกรรมกิจกรรมสุดท้าย, requestCode int ขั้นสุดท้าย, msg ภายใน) {AlertDialog.Builder Alert = AlertDialog.Builder ใหม่ (กิจกรรม); alert.set (ผงชูรส); alert.setPositiveButton (android.R.string.ok, DialogInterfaceOnClickListener ใหม่ () {@Override โมฆะสาธารณะ onClick (DialogInterface dialogInterface, int i) {dialogInterface.dismiss (); เจตนา PermissonIntent .setData (Uri.parse ("แพ็คเกจ:" + activity.getPackageName ())); activity.startActivityForResult (permissonIntent, RequestCode);}}; alert.setNegativeButton (android.R.string.cancel, DialogInterfaceOnClickListener ใหม่ () {@Override โมฆะสาธารณะ onClick (DialogInterface dialogInterface โต้ตอบ int ฉัน) {dialogInterface.dismiss ();}}; alert.setCancelable (false); alert.show (); } // ตรวจสอบว่าผู้ใช้ได้รับสิทธิ์ WRITE_STORAGE // โมฆะสาธารณะ checkPermission (int requestCode) {switch (requestCode) {กรณี WRITE_STORAGE: int hasWriteExternalStoragePermission = ActivityCompat.checkSelfPermission (สิ่งนี้การประกาศ // ถ้าเราเข้าถึงที่เก็บข้อมูลภายนอก ... // ถ้า (hasWriteExternalStoragePermission == PackageManager.PERMISSION_GRANTED) {// ...call selectPicture ซึ่งจะเปิดใช้งานกิจกรรมที่ผู้ใช้สามารถเลือกรูปภาพ // selectPicture (); // หากไม่ได้รับการอนุญาตดังนั้น ... //} else {//...request การอนุญาต // ActivityCompat.requestPermissions (นี่คือสตริงใหม่ {Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode); } พัก; }} โมฆะส่วนตัว selectPicture () {photo = MyHelper.createTempFile (photo); เจตนาเจตนา = เจตนาใหม่ (Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); // เริ่มกิจกรรมที่ผู้ใช้สามารถเลือกรูปภาพ // startActivityForResult (เจตนา, SELECT_PHOTO); }}

ณ จุดนี้โครงการของคุณควรบ่นว่าไม่สามารถแก้ไข MyHelper.createTempFile ได้ มาทำสิ่งนี้กันเถอะ!

การปรับขนาดรูปภาพด้วย createTempFile

สร้างคลาส“ MyHelper” ใหม่ ในคลาสนี้เราจะปรับขนาดรูปภาพที่ผู้ใช้เลือกซึ่งพร้อมที่จะประมวลผลโดย API การรู้จำข้อความ

นำเข้า android.graphics.Bitmap; นำเข้า android.graphics.BitmapFactory; นำเข้า android.content.Context; นำเข้า android.database.Cursor; นำเข้า android.os.Environment; นำเข้า android.widget.ImageView; นำเข้า android.provider.MediaStore; android.net.Uri นำเข้า นำเข้าแบบคงที่ android.graphics.BitmapFactory.decodeFile; นำเข้าแบบคงที่ android.graphics.BitmapFactory.decodeStream; นำเข้า java.io.File; นำเข้า java.io.FileNotFoundException; นำเข้า java.io.FileOutputStream; นำเข้า java.io.IOException; MyHelper ระดับสาธารณะ {สาธารณะคงที่ String getPath (บริบทบริบท, Uri uri) {เส้นทางสตริง = ""; การฉายสตริง = {MediaStore.Images.Media.DATA}; เคอร์เซอร์เคอร์เซอร์ = context.getContentResolver (). แบบสอบถาม (uri, การฉาย, null, null, null); int column_index; if (cursor! = null) {column_index = cursor.getColumnIndexOrThrow (MediaStore.Images.Media.DATA); cursor.moveToFirst (); path = cursor.getString (column_index); cursor.close (); } เส้นทางกลับ; } ไฟล์คงที่สาธารณะ createTempFile (ไฟล์ไฟล์) {ไฟล์ไดเรกทอรี = ไฟล์ใหม่ (Environment.getExternalStorageDirectory (). getPath () + "/com.jessicathornsby.myapplication"); if (! directory.exists () ||! directory.isDirectory ()) {directory.mkdirs (); } if (file == null) {file = new File (ไดเรกทอรี, "orig.jpg"); } ไฟล์ที่ส่งคืน; } สาธารณะคงบิตแมป resizePhoto (ไฟล์ imageFile บริบทบริบท, Uri uri, มุมมอง ImageView) {BitmapFactory.Options newOptions = ใหม่ BitmapFactory.Options (); ลอง {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 }} บิตแมปคงที่สาธารณะ resizePhoto (ไฟล์ imageFile, เส้นทางสตริง, มุมมอง ImageView) {ตัวเลือก BitmapFactory.Options = ใหม่ BitmapFactory.Options (); decodeFile (เส้นทางตัวเลือก); int photoHeight = options.outHeight; int photoWidth = options.outWidth; options.inSampleSize = Math.min (photoWidth / view.getWidth (), photoHeight / view.getHeight ()); return compressPhoto (imageFile, BitmapFactory.decodeFile (พา ธ , ตัวเลือก)); } ส่วนตัวคงบิตแมป compressPhoto (ไฟล์ photoFile, บิตแมปบิตแมป) {ลอง {FileOutputStream fOutput = ใหม่ FileOutputStream (photoFile); bitmap.compress (Bitmap.CompressFormat.JPEG, 70, fOutput); fOutput.close (); } catch (ข้อยกเว้น IOException) {exception.printStackTrace (); } ส่งคืนบิตแมป }}

ตั้งค่ารูปภาพเป็น ImageView

ต่อไปเราต้องใช้ onActivityResult () ในคลาส MainActivity ของเราและตั้งค่ารูปภาพที่ผู้ใช้เลือกเป็น ImageView ของเรา

นำเข้า android.graphics.Bitmap; นำเข้า android.os.Bundle; นำเข้า android.widget.ImageView; นำเข้า android.content.Tent; นำเข้า android.widget.TextView; android.net.Uri นำเข้า MainActivity ระดับสาธารณะขยาย BaseActivity {ส่วนตัว Bitmap myBitmap; ImageView ส่วนตัว myImageView; TextView ส่วนตัว myTextView; @Override ที่ได้รับการป้องกันเป็นโมฆะ onCreate (บันเดิลที่บันทึกไว้InstanceState) {super.onCreate (hiddenInstanceState) setContentView (R.layout.activity_main); myTextView = findViewById (R.id.textView); myImageView = findViewById (R.id.imageView); } @Override ป้องกันโมฆะ onActivityResult (int requestCode, int resultCode, ข้อมูล Intent) {super.onActivityResult (requestCode, resultCode ข้อมูล); if (resultCode == RESULT_OK) {switch (requestCode) {กรณี WRITE_STORAGE: checkPermission (requestCode); ทำลาย; กรณี SELECT_PHOTO: Uri dataUri = data.getData (); เส้นทางสตริง = MyHelper.getPath (นี่ 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; นำเข้า android.widget.ImageView; นำเข้า android.content.Tent; นำเข้า android.widget.TextView; นำเข้า android.view.View; android.net.Uri นำเข้า MainActivity ระดับสาธารณะขยายการดำเนินการ BaseActivity ViewOnClickListener {ส่วนตัว Bitmap myBitmap; ImageView ส่วนตัว myImageView; TextView ส่วนตัว myTextView; @Override ที่ได้รับการป้องกันเป็นโมฆะ onCreate (บันเดิลที่บันทึกไว้InstanceState) {super.onCreate (hiddenInstanceState) setContentView (R.layout.activity_main); myTextView = findViewById (R.id.textView); myImageView = findViewById (R.id.imageView); findViewById (R.id.checkText) .setOnClickListener (นี้); } @Override โมฆะสาธารณะ onClick (ดูมุมมอง) {switch (view.getId ()) {case R.id.checkText: if (myBitmap! = null) {// เราจะใช้งาน runTextRecog ในขั้นตอนต่อไป // runTextRecog (); } พัก; }}

ML Kit สามารถประมวลผลภาพเมื่ออยู่ในรูปแบบ FirebaseVisionImage เท่านั้นดังนั้นเราจึงจำเป็นต้องแปลงรูปภาพของเราให้เป็นวัตถุ FirebaseVisionImage คุณสามารถสร้าง FirebaseVisionImage ได้จาก Bitmap, media.Image, ByteBuffer หรืออาร์เรย์ไบต์ เนื่องจากเรากำลังทำงานกับ Bitmaps เราจึงต้องเรียกใช้วิธีการอรรถประโยชน์ fromBitmap () ของคลาส FirebaseVisionImage และส่งผ่านบิตแมปของเรา

โมฆะส่วนตัว runTextRecog เป็นโมฆะ () {FirebaseVisionImage ภาพ = FirebaseVisionImage.fromBitmap (myBitmap);

ML Kit มีคลาสเครื่องมือตรวจจับที่แตกต่างกันสำหรับการดำเนินการจดจำภาพแต่ละประเภท สำหรับข้อความเราต้องใช้คลาส FirebaseVisionTextDetector ซึ่งดำเนินการจดจำตัวอักษรด้วยแสง (OCR) บนภาพ

เราสร้างตัวอย่างของ FirebaseVisionTextDetector โดยใช้ getVisionTextDetector:

เครื่องตรวจจับ FirebaseVisionTextDetector = FirebaseVision.getInstance (). getVisionTextDetector ();

ถัดไปเราต้องตรวจสอบ FirebaseVisionImage เพื่อหาข้อความโดยเรียกวิธี detectInImage () และส่งต่อไปยังวัตถุ FirebaseVisionImage นอกจากนี้เรายังต้องใช้การเรียกกลับแบบ onSuccess และ onFailure รวมถึงผู้ฟังที่เกี่ยวข้องเพื่อให้แอปของเราได้รับแจ้งเมื่อมีผลลัพธ์

detector.detectInImage (รูปภาพ) .addOnSuccessListener (OnSuccessListener ใหม่() {@Override // To // //}}) addOnFailureListener (OnFailureListener ใหม่ () {@Override โมฆะสาธารณะ onFailure (ยกเว้นข้อยกเว้น @NonNull) {// งานล้มเหลวโดยมีข้อยกเว้น //}}; }

หากการดำเนินการนี้ล้มเหลวฉันจะแสดงขนมปังปิ้ง แต่หากการดำเนินการประสบความสำเร็จฉันจะเรียกกระบวนการหักออกด้วยการตอบกลับ

ณ จุดนี้รหัสตรวจจับข้อความของฉันมีลักษณะดังนี้:

// สร้าง FirebaseVisionImage // โมฆะส่วนตัวของ runTextRecog () {FirebaseVisionImage image = FirebaseVisionImage.fromBitmap (myBitmap); // สร้างตัวอย่างของ FirebaseVisionCloudTextDetector // เครื่องตรวจจับ FirebaseVisionTextDetector = FirebaseVision.getInstance (). getVisionTextDetector (); // ลงทะเบียน OnSuccessListener // detector.detectInImage (รูปภาพ) .addOnSuccessListener (ใหม่ OnSuccessListener() {@Override // ใช้การเรียกกลับแบบ onSuccess // โมฆะสาธารณะแบบ onSuccess (ข้อความ FirebaseVisionText) {// การเรียก processExtractedText พร้อมการตอบสนอง // processExtractedText (ข้อความ); }}). addOnFailureListener (ใหม่ OnFailureListener () {@Override // ใช้งาน onFailure calback // โมฆะสาธารณะ onFailure (ยกเว้นข้อยกเว้น @NonNull) {Toast.makeText (MainActivity.this, "ข้อยกเว้น", Toast.LENGTH_LONG) );}}); }

เมื่อใดก็ตามที่แอปของเราได้รับการแจ้งเตือนการเข้าถึงเราจำเป็นต้องแยกวิเคราะห์ผลลัพธ์

วัตถุ FirebaseVisionText สามารถมีองค์ประกอบเส้นและบล็อกที่แต่ละบล็อกมักจะเท่ากับข้อความย่อหน้าเดียว ถ้า FirebaseVisionText ส่งคืน 0 บล็อกเราจะแสดงสตริง“ no_text” แต่ถ้ามีหนึ่งบล็อกขึ้นไปเราจะแสดงข้อความที่ดึงมาเป็นส่วนหนึ่งของ TextView ของเรา

โมฆะส่วนตัว 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; นำเข้า android.widget.ImageView; นำเข้า android.content.Tent; นำเข้า android.widget.TextView; นำเข้า android.widget.Toast; นำเข้า android.view.View; android.net.Uri นำเข้า นำเข้า android.support.annotation.NonNull; นำเข้า com.google.firebase.ml.vision.common.FirebaseVisionImage; นำเข้า com.google.firebase.ml.vision.text.FirebaseVisionText; นำเข้า com.google.firebase.ml.vision.text.FirebaseVisionTextDetector; นำเข้า com.google.firebase.ml.vision.FirebaseVision; นำเข้า com.google.android.gms.tasksOnSuccessListener; นำเข้า com.google.android.gms.tasksOnFailureListener; MainActivity ระดับสาธารณะขยายการดำเนินการ BaseActivity ViewOnClickListener {ส่วนตัว Bitmap myBitmap; ImageView ส่วนตัว myImageView; TextView ส่วนตัว myTextView; @Override ที่ได้รับการป้องกันเป็นโมฆะ onCreate (บันเดิลที่บันทึกไว้InstanceState) {super.onCreate (hiddenInstanceState) setContentView (R.layout.activity_main); myTextView = findViewById (R.id.textView); myImageView = findViewById (R.id.imageView); findViewById (R.id.checkText) .setOnClickListener (นี้); } @Override โมฆะสาธารณะ onClick (มุมมองดู) {switch (view.getId ()) {case R.id.checkText: if (myBitmap! = null) {runTextRecog (); } พัก; }} @Override โมฆะป้องกัน onActivityResult (int requestCode, int resultCode, ข้อมูล Intent) {super.onActivityResult (requestCode, resultCode ข้อมูล); if (resultCode == RESULT_OK) {switch (requestCode) {กรณี WRITE_STORAGE: checkPermission (requestCode); ทำลาย; กรณี SELECT_PHOTO: Uri dataUri = data.getData (); เส้นทางสตริง = MyHelper.getPath (นี่ 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 (รูปภาพ) .addOnSuccessListener (OnSuccessListener ใหม่() {@Override โมฆะสาธารณะ onSuccess (FirebaseVisionText ตำรา) {processExtractedText (ตำรา); }}). addOnFailureListener (ใหม่ OnFailureListener () {@Override โมฆะสาธารณะ onFailure (@NonNull ข้อยกเว้นข้อยกเว้น) {Toast.makeText (MainActivity.this, "ข้อยกเว้น", Toast.LENGTH_LONG) .show ();}}); } โมฆะส่วนตัว 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 นี้ยังมีการสแกนบาร์โค้ด, การตรวจจับใบหน้า, การติดฉลากรูปภาพและการจดจำสถานที่สำคัญโดยมีแผนที่จะเพิ่ม APIs เพิ่มเติมสำหรับกรณีการใช้โทรศัพท์มือถือทั่วไปรวมถึง Smart Reply และ API ใบหน้าที่มีความหนาแน่นสูง

ML Kit API ใดที่คุณสนใจมากที่สุดลองดู แจ้งให้เราทราบในความคิดเห็นด้านล่าง!

นักเขียนนิยายวิทยาศาสตร์เป็นนักคิดล่วงหน้าที่ยอดเยี่ยมในยุคสมัยของเรานิยายวิทยาศาสตร์เรื่องยากเป็นหมวดหมู่เฉพาะในประเภทที่สำคัญที่สุดในการจินตนาการถึงอนาคตที่เรามีร่วมกันโดยที่กฎของฟิสิกส์ได้รับการปฏิ...

ไม่ใช่ทุกคนที่มีพรสวรรค์ด้านศิลปะ แต่ถึงแม้ว่างานศิลปะชิ้นเอกของคุณจะเป็นงานวาดรูปคนคุณยังสามารถเป็นมืออาชีพที่สร้างสรรค์ได้ จากการออกแบบกราฟิกไปจนถึงการผลิตวิดีโอมีวิธีนับไม่ถ้วนที่จะแสดงความเป็นตัวข...

การได้รับความนิยม