Resimlerdeki metni tanımak için ML Kit'i kullanabilirsiniz. ML Kit, hem sokak tabelası metni gibi resimlerdeki metni tanımaya uygun genel amaçlı bir API'ye hem de belge metnini tanımak için optimize edilmiş bir API'ye sahiptir. Genel amaçlı API'nin hem cihaz içi hem de bulut tabanlı modelleri vardır. Belge metni tanıma yalnızca bulut tabanlı bir model olarak mevcuttur. Bulut ve cihaz üstü modellerin karşılaştırması için genel bakışa bakın.
Sen başlamadan önce
- Henüz yapmadıysanız Android projenize Firebase'i ekleyin .
- ML Kit Android kitaplıklarının bağımlılıklarını modülünüze (uygulama düzeyi) Gradle dosyasına ekleyin (genellikle
app/build.gradle
):apply plugin: 'com.android.application' apply plugin: 'com.google.gms.google-services' dependencies { // ... implementation 'com.google.firebase:firebase-ml-vision:24.0.3' }
- İsteğe bağlıdır ancak önerilir : Cihazdaki API'yi kullanıyorsanız uygulamanızı, Play Store'dan yüklendikten sonra ML modelini cihaza otomatik olarak indirecek şekilde yapılandırın.
Bunu yapmak için uygulamanızın
AndroidManifest.xml
dosyasına aşağıdaki bildirimi ekleyin:<application ...> ... <meta-data android:name="com.google.firebase.ml.vision.DEPENDENCIES" android:value="ocr" /> <!-- To use multiple models: android:value="ocr,model2,model3" --> </application>
Kurulum sırasındaki model indirmelerini etkinleştirmezseniz, cihazdaki algılayıcıyı ilk kez çalıştırdığınızda model indirilecektir. İndirme işlemi tamamlanmadan yapacağınız istekler sonuç vermeyecektir. Bulut tabanlı modeli kullanmak istiyorsanız ve projeniz için Bulut tabanlı API'leri henüz etkinleştirmediyseniz hemen yapın:
- Firebase konsolunun ML Kit API'leri sayfasını açın.
Projenizi henüz bir Blaze fiyatlandırma planına yükseltmediyseniz bunu yapmak için Yükselt'e tıklayın. (Yalnızca projeniz Blaze planında değilse yükseltme yapmanız istenecektir.)
Yalnızca Blaze düzeyindeki projeler Bulut tabanlı API'leri kullanabilir.
- Bulut tabanlı API'ler henüz etkin değilse Bulut Tabanlı API'leri Etkinleştir'i tıklayın.
Yalnızca cihazdaki modeli kullanmak istiyorsanız bu adımı atlayabilirsiniz.
Artık resimlerdeki metni tanımaya hazırsınız.
Giriş görseli yönergeleri
ML Kit'in metni doğru şekilde tanıyabilmesi için giriş görüntülerinin yeterli piksel verileriyle temsil edilen metin içermesi gerekir. İdeal olarak Latince metinlerde her karakter en az 16x16 piksel olmalıdır. Çince, Japonca ve Korece metinler için (yalnızca bulut tabanlı API'ler tarafından desteklenir) her karakter 24x24 piksel olmalıdır. Tüm diller için, karakterlerin 24x24 pikselden büyük olmasının genellikle doğruluk açısından bir avantajı yoktur.
Örneğin, 640x480 boyutunda bir görüntü, görüntünün tüm genişliğini kaplayan bir kartviziti taramak için iyi sonuç verebilir. Letter boyutunda kağıda basılmış bir belgeyi taramak için 720x1280 piksel boyutunda bir görüntü gerekebilir.
Zayıf görüntü odağı metin tanıma doğruluğuna zarar verebilir. Kabul edilebilir sonuçlar alamıyorsanız kullanıcıdan görüntüyü yeniden yakalamasını istemeyi deneyin.
Gerçek zamanlı bir uygulamada metni tanıyorsanız, giriş görüntülerinin genel boyutlarını da dikkate almak isteyebilirsiniz. Daha küçük resimler daha hızlı işlenebilir; bu nedenle gecikmeyi azaltmak için, resimleri daha düşük çözünürlükte çekin (yukarıdaki doğruluk gerekliliklerini göz önünde bulundurarak) ve metnin resimde mümkün olduğunca fazla yer kaplamasını sağlayın. Ayrıca bkz . Gerçek zamanlı performansı artırmaya yönelik ipuçları .
Resimlerdeki metni tanıma
Cihaz içi veya bulut tabanlı bir model kullanarak görüntüdeki metni tanımak için metin tanıyıcıyı aşağıda açıklandığı şekilde çalıştırın.
1. Metin tanıyıcıyı çalıştırın
Bir görüntüdeki metni tanımak içinBitmap
, media.Image
, ByteBuffer
, bayt dizisinden veya aygıttaki bir dosyadan bir FirebaseVisionImage
nesnesi oluşturun. Ardından FirebaseVisionImage
nesnesini FirebaseVisionTextRecognizer
processImage
yöntemine iletin.Görüntünüzden bir
FirebaseVisionImage
nesnesi oluşturun.Bir
media.Image
nesnesinden birFirebaseVisionImage
nesnesi oluşturmak için (örneğin, bir cihazın kamerasından bir görüntü yakalarken),media.Image
nesnesini ve görüntünün dönüşünüFirebaseVisionImage.fromMediaImage()
öğesine iletin.CameraX kitaplığını kullanıyorsanız
OnImageCapturedListener
veImageAnalysis.Analyzer
sınıfları sizin için dönüş değerini hesaplar; dolayısıylaFirebaseVisionImage.fromMediaImage()
çağırmadan önce dönüşü ML Kit'inROTATION_
sabitlerinden birine dönüştürmeniz yeterlidir:Java
private class YourAnalyzer implements ImageAnalysis.Analyzer { private int degreesToFirebaseRotation(int degrees) { switch (degrees) { case 0: return FirebaseVisionImageMetadata.ROTATION_0; case 90: return FirebaseVisionImageMetadata.ROTATION_90; case 180: return FirebaseVisionImageMetadata.ROTATION_180; case 270: return FirebaseVisionImageMetadata.ROTATION_270; default: throw new IllegalArgumentException( "Rotation must be 0, 90, 180, or 270."); } } @Override public void analyze(ImageProxy imageProxy, int degrees) { if (imageProxy == null || imageProxy.getImage() == null) { return; } Image mediaImage = imageProxy.getImage(); int rotation = degreesToFirebaseRotation(degrees); FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation); // Pass image to an ML Kit Vision API // ... } }
Kotlin+KTX
private class YourImageAnalyzer : ImageAnalysis.Analyzer { private fun degreesToFirebaseRotation(degrees: Int): Int = when(degrees) { 0 -> FirebaseVisionImageMetadata.ROTATION_0 90 -> FirebaseVisionImageMetadata.ROTATION_90 180 -> FirebaseVisionImageMetadata.ROTATION_180 270 -> FirebaseVisionImageMetadata.ROTATION_270 else -> throw Exception("Rotation must be 0, 90, 180, or 270.") } override fun analyze(imageProxy: ImageProxy?, degrees: Int) { val mediaImage = imageProxy?.image val imageRotation = degreesToFirebaseRotation(degrees) if (mediaImage != null) { val image = FirebaseVisionImage.fromMediaImage(mediaImage, imageRotation) // Pass image to an ML Kit Vision API // ... } } }
Görüntünün dönüşünü sağlayan bir kamera kitaplığı kullanmıyorsanız, bunu cihazın dönüşünden ve cihazdaki kamera sensörünün yönünden hesaplayabilirsiniz:
Java
private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); static { ORIENTATIONS.append(Surface.ROTATION_0, 90); ORIENTATIONS.append(Surface.ROTATION_90, 0); ORIENTATIONS.append(Surface.ROTATION_180, 270); ORIENTATIONS.append(Surface.ROTATION_270, 180); } /** * Get the angle by which an image must be rotated given the device's current * orientation. */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private int getRotationCompensation(String cameraId, Activity activity, Context context) throws CameraAccessException { // Get the device's current rotation relative to its "native" orientation. // Then, from the ORIENTATIONS table, look up the angle the image must be // rotated to compensate for the device's rotation. int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation(); int rotationCompensation = ORIENTATIONS.get(deviceRotation); // On most devices, the sensor orientation is 90 degrees, but for some // devices it is 270 degrees. For devices with a sensor orientation of // 270, rotate the image an additional 180 ((270 + 270) % 360) degrees. CameraManager cameraManager = (CameraManager) context.getSystemService(CAMERA_SERVICE); int sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION); rotationCompensation = (rotationCompensation + sensorOrientation + 270) % 360; // Return the corresponding FirebaseVisionImageMetadata rotation value. int result; switch (rotationCompensation) { case 0: result = FirebaseVisionImageMetadata.ROTATION_0; break; case 90: result = FirebaseVisionImageMetadata.ROTATION_90; break; case 180: result = FirebaseVisionImageMetadata.ROTATION_180; break; case 270: result = FirebaseVisionImageMetadata.ROTATION_270; break; default: result = FirebaseVisionImageMetadata.ROTATION_0; Log.e(TAG, "Bad rotation value: " + rotationCompensation); } return result; }
Kotlin+KTX
private val ORIENTATIONS = SparseIntArray() init { ORIENTATIONS.append(Surface.ROTATION_0, 90) ORIENTATIONS.append(Surface.ROTATION_90, 0) ORIENTATIONS.append(Surface.ROTATION_180, 270) ORIENTATIONS.append(Surface.ROTATION_270, 180) } /** * Get the angle by which an image must be rotated given the device's current * orientation. */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Throws(CameraAccessException::class) private fun getRotationCompensation(cameraId: String, activity: Activity, context: Context): Int { // Get the device's current rotation relative to its "native" orientation. // Then, from the ORIENTATIONS table, look up the angle the image must be // rotated to compensate for the device's rotation. val deviceRotation = activity.windowManager.defaultDisplay.rotation var rotationCompensation = ORIENTATIONS.get(deviceRotation) // On most devices, the sensor orientation is 90 degrees, but for some // devices it is 270 degrees. For devices with a sensor orientation of // 270, rotate the image an additional 180 ((270 + 270) % 360) degrees. val cameraManager = context.getSystemService(CAMERA_SERVICE) as CameraManager val sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION)!! rotationCompensation = (rotationCompensation + sensorOrientation + 270) % 360 // Return the corresponding FirebaseVisionImageMetadata rotation value. val result: Int when (rotationCompensation) { 0 -> result = FirebaseVisionImageMetadata.ROTATION_0 90 -> result = FirebaseVisionImageMetadata.ROTATION_90 180 -> result = FirebaseVisionImageMetadata.ROTATION_180 270 -> result = FirebaseVisionImageMetadata.ROTATION_270 else -> { result = FirebaseVisionImageMetadata.ROTATION_0 Log.e(TAG, "Bad rotation value: $rotationCompensation") } } return result }
Ardından
media.Image
nesnesini ve döndürme değeriniFirebaseVisionImage.fromMediaImage()
öğesine iletin:Java
FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
Kotlin+KTX
val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)
- Bir dosya URI'sından
FirebaseVisionImage
nesnesi oluşturmak için uygulama içeriğini ve dosya URI'siniFirebaseVisionImage.fromFilePath()
öğesine iletin. Kullanıcıdan galeri uygulamasından bir resim seçmesini istemek içinACTION_GET_CONTENT
amacını kullandığınızda bu kullanışlıdır.Java
FirebaseVisionImage image; try { image = FirebaseVisionImage.fromFilePath(context, uri); } catch (IOException e) { e.printStackTrace(); }
Kotlin+KTX
val image: FirebaseVisionImage try { image = FirebaseVisionImage.fromFilePath(context, uri) } catch (e: IOException) { e.printStackTrace() }
-
ByteBuffer
veya bayt dizisinden birFirebaseVisionImage
nesnesi oluşturmak için, önceliklemedia.Image
girişi için yukarıda açıklandığı gibi görüntü döndürmeyi hesaplayın.Ardından görüntünün yüksekliğini, genişliğini, renk kodlama biçimini ve dönüşünü içeren bir
FirebaseVisionImageMetadata
nesnesi oluşturun:Java
FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder() .setWidth(480) // 480x360 is typically sufficient for .setHeight(360) // image recognition .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21) .setRotation(rotation) .build();
Kotlin+KTX
val metadata = FirebaseVisionImageMetadata.Builder() .setWidth(480) // 480x360 is typically sufficient for .setHeight(360) // image recognition .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21) .setRotation(rotation) .build()
FirebaseVisionImage
nesnesi oluşturmak için tamponu veya diziyi ve meta veri nesnesini kullanın:Java
FirebaseVisionImage image = FirebaseVisionImage.fromByteBuffer(buffer, metadata); // Or: FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(byteArray, metadata);
Kotlin+KTX
val image = FirebaseVisionImage.fromByteBuffer(buffer, metadata) // Or: val image = FirebaseVisionImage.fromByteArray(byteArray, metadata)
- Bir
Bitmap
nesnesindenFirebaseVisionImage
nesnesi oluşturmak için:Java
FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
Kotlin+KTX
val image = FirebaseVisionImage.fromBitmap(bitmap)
Bitmap
nesnesi tarafından temsil edilen görüntü, ek bir döndürme gerekmeden dik olmalıdır.
FirebaseVisionTextRecognizer
örneğini alın.Cihazdaki modeli kullanmak için:
Java
FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance() .getOnDeviceTextRecognizer();
Kotlin+KTX
val detector = FirebaseVision.getInstance() .onDeviceTextRecognizer
Bulut tabanlı modeli kullanmak için:
Java
FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance() .getCloudTextRecognizer(); // Or, to change the default settings: // FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance() // .getCloudTextRecognizer(options);
// Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages FirebaseVisionCloudTextRecognizerOptions options = new FirebaseVisionCloudTextRecognizerOptions.Builder() .setLanguageHints(Arrays.asList("en", "hi")) .build();
Kotlin+KTX
val detector = FirebaseVision.getInstance().cloudTextRecognizer // Or, to change the default settings: // val detector = FirebaseVision.getInstance().getCloudTextRecognizer(options)
// Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages val options = FirebaseVisionCloudTextRecognizerOptions.Builder() .setLanguageHints(listOf("en", "hi")) .build()
Son olarak görüntüyü
processImage
yöntemine aktarın:Java
Task<FirebaseVisionText> result = detector.processImage(image) .addOnSuccessListener(new OnSuccessListener<FirebaseVisionText>() { @Override public void onSuccess(FirebaseVisionText firebaseVisionText) { // Task completed successfully // ... } }) .addOnFailureListener( new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Task failed with an exception // ... } });
Kotlin+KTX
val result = detector.processImage(image) .addOnSuccessListener { firebaseVisionText -> // Task completed successfully // ... } .addOnFailureListener { e -> // Task failed with an exception // ... }
2. Tanınan metin bloklarından metni çıkarın
Metin tanıma işlemi başarılı olursa başarı dinleyicisine birFirebaseVisionText
nesnesi iletilecektir. FirebaseVisionText
nesnesi, görüntüde tanınan tam metni ve sıfır veya daha fazla TextBlock
nesnesini içerir. Her TextBlock
sıfır veya daha fazla Line
nesnesi içeren dikdörtgen bir metin bloğunu temsil eder. Her Line
nesnesi, sözcükleri ve sözcük benzeri varlıkları (tarihler, sayılar vb.) temsil eden sıfır veya daha fazla Element
nesnesi içerir.
Her TextBlock
, Line
ve Element
nesnesi için bölgede tanınan metni ve bölgenin sınırlayıcı koordinatlarını alabilirsiniz.
Örneğin:
Java
String resultText = result.getText(); for (FirebaseVisionText.TextBlock block: result.getTextBlocks()) { String blockText = block.getText(); Float blockConfidence = block.getConfidence(); List<RecognizedLanguage> blockLanguages = block.getRecognizedLanguages(); Point[] blockCornerPoints = block.getCornerPoints(); Rect blockFrame = block.getBoundingBox(); for (FirebaseVisionText.Line line: block.getLines()) { String lineText = line.getText(); Float lineConfidence = line.getConfidence(); List<RecognizedLanguage> lineLanguages = line.getRecognizedLanguages(); Point[] lineCornerPoints = line.getCornerPoints(); Rect lineFrame = line.getBoundingBox(); for (FirebaseVisionText.Element element: line.getElements()) { String elementText = element.getText(); Float elementConfidence = element.getConfidence(); List<RecognizedLanguage> elementLanguages = element.getRecognizedLanguages(); Point[] elementCornerPoints = element.getCornerPoints(); Rect elementFrame = element.getBoundingBox(); } } }
Kotlin+KTX
val resultText = result.text for (block in result.textBlocks) { val blockText = block.text val blockConfidence = block.confidence val blockLanguages = block.recognizedLanguages val blockCornerPoints = block.cornerPoints val blockFrame = block.boundingBox for (line in block.lines) { val lineText = line.text val lineConfidence = line.confidence val lineLanguages = line.recognizedLanguages val lineCornerPoints = line.cornerPoints val lineFrame = line.boundingBox for (element in line.elements) { val elementText = element.text val elementConfidence = element.confidence val elementLanguages = element.recognizedLanguages val elementCornerPoints = element.cornerPoints val elementFrame = element.boundingBox } } }
Gerçek zamanlı performansı artırmaya yönelik ipuçları
Gerçek zamanlı bir uygulamada metni tanımak için cihaz üstü modeli kullanmak istiyorsanız en iyi kare hızlarına ulaşmak için şu yönergeleri izleyin:
- Metin tanıyıcıya yapılan aramaları kısın. Metin tanıyıcı çalışırken yeni bir video karesi kullanılabilir hale gelirse kareyi bırakın.
- Grafikleri giriş görüntüsüne yerleştirmek için metin tanıyıcının çıktısını kullanıyorsanız, önce ML Kit'ten sonucu alın, ardından tek adımda görüntüyü oluşturun ve kaplayın. Bunu yaparak, her giriş karesi için ekran yüzeyini yalnızca bir kez görüntüleyebilirsiniz.
Camera2 API'sini kullanıyorsanız görüntüleri
ImageFormat.YUV_420_888
formatında yakalayın.Eski Kamera API'sini kullanıyorsanız görüntüleri
ImageFormat.NV21
formatında yakalayın.- Görüntüleri daha düşük çözünürlükte çekmeyi düşünün. Ancak bu API'nin resim boyutu gereksinimlerini de unutmayın.
Sonraki adımlar
- Cloud API kullanan bir uygulamayı üretime dağıtmadan önce, yetkisiz API erişimini önlemek ve etkisini azaltmak için bazı ek adımlar atmanız gerekir.
Belge görsellerindeki metni tanıma
Bir belgenin metnini tanımak için bulut tabanlı belge metin tanıyıcıyı aşağıda açıklandığı şekilde yapılandırın ve çalıştırın.
Aşağıda açıklanan belge metni tanıma API'si, belge görselleriyle çalışmak için daha kullanışlı olması amaçlanan bir arayüz sağlar. Ancak FirebaseVisionTextRecognizer
API tarafından sağlanan arayüzü tercih ederseniz, bulut metin tanıyıcıyı yoğun metin modelini kullanacak şekilde yapılandırarak belgeleri taramak için bunu kullanabilirsiniz.
Belge metni tanıma API'sini kullanmak için:
1. Metin tanıyıcıyı çalıştırın
Bir görüntüdeki metni tanımak içinBitmap
, media.Image
, ByteBuffer
, bayt dizisinden veya aygıttaki bir dosyadan bir FirebaseVisionImage
nesnesi oluşturun. Ardından FirebaseVisionImage
nesnesini FirebaseVisionDocumentTextRecognizer
processImage
yöntemine iletin.Görüntünüzden bir
FirebaseVisionImage
nesnesi oluşturun.Bir
media.Image
nesnesinden birFirebaseVisionImage
nesnesi oluşturmak için (örneğin, bir cihazın kamerasından bir görüntü yakalarken),media.Image
nesnesini ve görüntünün dönüşünüFirebaseVisionImage.fromMediaImage()
öğesine iletin.CameraX kitaplığını kullanıyorsanız
OnImageCapturedListener
veImageAnalysis.Analyzer
sınıfları sizin için dönüş değerini hesaplar; dolayısıylaFirebaseVisionImage.fromMediaImage()
çağırmadan önce dönüşü ML Kit'inROTATION_
sabitlerinden birine dönüştürmeniz yeterlidir:Java
private class YourAnalyzer implements ImageAnalysis.Analyzer { private int degreesToFirebaseRotation(int degrees) { switch (degrees) { case 0: return FirebaseVisionImageMetadata.ROTATION_0; case 90: return FirebaseVisionImageMetadata.ROTATION_90; case 180: return FirebaseVisionImageMetadata.ROTATION_180; case 270: return FirebaseVisionImageMetadata.ROTATION_270; default: throw new IllegalArgumentException( "Rotation must be 0, 90, 180, or 270."); } } @Override public void analyze(ImageProxy imageProxy, int degrees) { if (imageProxy == null || imageProxy.getImage() == null) { return; } Image mediaImage = imageProxy.getImage(); int rotation = degreesToFirebaseRotation(degrees); FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation); // Pass image to an ML Kit Vision API // ... } }
Kotlin+KTX
private class YourImageAnalyzer : ImageAnalysis.Analyzer { private fun degreesToFirebaseRotation(degrees: Int): Int = when(degrees) { 0 -> FirebaseVisionImageMetadata.ROTATION_0 90 -> FirebaseVisionImageMetadata.ROTATION_90 180 -> FirebaseVisionImageMetadata.ROTATION_180 270 -> FirebaseVisionImageMetadata.ROTATION_270 else -> throw Exception("Rotation must be 0, 90, 180, or 270.") } override fun analyze(imageProxy: ImageProxy?, degrees: Int) { val mediaImage = imageProxy?.image val imageRotation = degreesToFirebaseRotation(degrees) if (mediaImage != null) { val image = FirebaseVisionImage.fromMediaImage(mediaImage, imageRotation) // Pass image to an ML Kit Vision API // ... } } }
Görüntünün dönüşünü sağlayan bir kamera kitaplığı kullanmıyorsanız, bunu cihazın dönüşünden ve cihazdaki kamera sensörünün yönünden hesaplayabilirsiniz:
Java
private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); static { ORIENTATIONS.append(Surface.ROTATION_0, 90); ORIENTATIONS.append(Surface.ROTATION_90, 0); ORIENTATIONS.append(Surface.ROTATION_180, 270); ORIENTATIONS.append(Surface.ROTATION_270, 180); } /** * Get the angle by which an image must be rotated given the device's current * orientation. */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private int getRotationCompensation(String cameraId, Activity activity, Context context) throws CameraAccessException { // Get the device's current rotation relative to its "native" orientation. // Then, from the ORIENTATIONS table, look up the angle the image must be // rotated to compensate for the device's rotation. int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation(); int rotationCompensation = ORIENTATIONS.get(deviceRotation); // On most devices, the sensor orientation is 90 degrees, but for some // devices it is 270 degrees. For devices with a sensor orientation of // 270, rotate the image an additional 180 ((270 + 270) % 360) degrees. CameraManager cameraManager = (CameraManager) context.getSystemService(CAMERA_SERVICE); int sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION); rotationCompensation = (rotationCompensation + sensorOrientation + 270) % 360; // Return the corresponding FirebaseVisionImageMetadata rotation value. int result; switch (rotationCompensation) { case 0: result = FirebaseVisionImageMetadata.ROTATION_0; break; case 90: result = FirebaseVisionImageMetadata.ROTATION_90; break; case 180: result = FirebaseVisionImageMetadata.ROTATION_180; break; case 270: result = FirebaseVisionImageMetadata.ROTATION_270; break; default: result = FirebaseVisionImageMetadata.ROTATION_0; Log.e(TAG, "Bad rotation value: " + rotationCompensation); } return result; }
Kotlin+KTX
private val ORIENTATIONS = SparseIntArray() init { ORIENTATIONS.append(Surface.ROTATION_0, 90) ORIENTATIONS.append(Surface.ROTATION_90, 0) ORIENTATIONS.append(Surface.ROTATION_180, 270) ORIENTATIONS.append(Surface.ROTATION_270, 180) } /** * Get the angle by which an image must be rotated given the device's current * orientation. */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Throws(CameraAccessException::class) private fun getRotationCompensation(cameraId: String, activity: Activity, context: Context): Int { // Get the device's current rotation relative to its "native" orientation. // Then, from the ORIENTATIONS table, look up the angle the image must be // rotated to compensate for the device's rotation. val deviceRotation = activity.windowManager.defaultDisplay.rotation var rotationCompensation = ORIENTATIONS.get(deviceRotation) // On most devices, the sensor orientation is 90 degrees, but for some // devices it is 270 degrees. For devices with a sensor orientation of // 270, rotate the image an additional 180 ((270 + 270) % 360) degrees. val cameraManager = context.getSystemService(CAMERA_SERVICE) as CameraManager val sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION)!! rotationCompensation = (rotationCompensation + sensorOrientation + 270) % 360 // Return the corresponding FirebaseVisionImageMetadata rotation value. val result: Int when (rotationCompensation) { 0 -> result = FirebaseVisionImageMetadata.ROTATION_0 90 -> result = FirebaseVisionImageMetadata.ROTATION_90 180 -> result = FirebaseVisionImageMetadata.ROTATION_180 270 -> result = FirebaseVisionImageMetadata.ROTATION_270 else -> { result = FirebaseVisionImageMetadata.ROTATION_0 Log.e(TAG, "Bad rotation value: $rotationCompensation") } } return result }
Ardından
media.Image
nesnesini ve döndürme değeriniFirebaseVisionImage.fromMediaImage()
öğesine iletin:Java
FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
Kotlin+KTX
val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)
- Bir dosya URI'sından
FirebaseVisionImage
nesnesi oluşturmak için uygulama içeriğini ve dosya URI'siniFirebaseVisionImage.fromFilePath()
öğesine iletin. Kullanıcıdan galeri uygulamasından bir resim seçmesini istemek içinACTION_GET_CONTENT
amacını kullandığınızda bu kullanışlıdır.Java
FirebaseVisionImage image; try { image = FirebaseVisionImage.fromFilePath(context, uri); } catch (IOException e) { e.printStackTrace(); }
Kotlin+KTX
val image: FirebaseVisionImage try { image = FirebaseVisionImage.fromFilePath(context, uri) } catch (e: IOException) { e.printStackTrace() }
-
ByteBuffer
veya bayt dizisinden birFirebaseVisionImage
nesnesi oluşturmak için, önceliklemedia.Image
girişi için yukarıda açıklandığı gibi görüntü döndürmeyi hesaplayın.Ardından görüntünün yüksekliğini, genişliğini, renk kodlama biçimini ve dönüşünü içeren bir
FirebaseVisionImageMetadata
nesnesi oluşturun:Java
FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder() .setWidth(480) // 480x360 is typically sufficient for .setHeight(360) // image recognition .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21) .setRotation(rotation) .build();
Kotlin+KTX
val metadata = FirebaseVisionImageMetadata.Builder() .setWidth(480) // 480x360 is typically sufficient for .setHeight(360) // image recognition .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21) .setRotation(rotation) .build()
FirebaseVisionImage
nesnesi oluşturmak için tamponu veya diziyi ve meta veri nesnesini kullanın:Java
FirebaseVisionImage image = FirebaseVisionImage.fromByteBuffer(buffer, metadata); // Or: FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(byteArray, metadata);
Kotlin+KTX
val image = FirebaseVisionImage.fromByteBuffer(buffer, metadata) // Or: val image = FirebaseVisionImage.fromByteArray(byteArray, metadata)
- Bir
Bitmap
nesnesindenFirebaseVisionImage
nesnesi oluşturmak için:Java
FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
Kotlin+KTX
val image = FirebaseVisionImage.fromBitmap(bitmap)
Bitmap
nesnesi tarafından temsil edilen görüntü, ek bir döndürme gerekmeden dik olmalıdır.
FirebaseVisionDocumentTextRecognizer
örneğini alın:Java
FirebaseVisionDocumentTextRecognizer detector = FirebaseVision.getInstance() .getCloudDocumentTextRecognizer();
// Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages FirebaseVisionCloudDocumentRecognizerOptions options = new FirebaseVisionCloudDocumentRecognizerOptions.Builder() .setLanguageHints(Arrays.asList("en", "hi")) .build(); FirebaseVisionDocumentTextRecognizer detector = FirebaseVision.getInstance() .getCloudDocumentTextRecognizer(options);
Kotlin+KTX
val detector = FirebaseVision.getInstance() .cloudDocumentTextRecognizer
// Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages val options = FirebaseVisionCloudDocumentRecognizerOptions.Builder() .setLanguageHints(listOf("en", "hi")) .build() val detector = FirebaseVision.getInstance() .getCloudDocumentTextRecognizer(options)
Son olarak görüntüyü
processImage
yöntemine aktarın:Java
detector.processImage(myImage) .addOnSuccessListener(new OnSuccessListener<FirebaseVisionDocumentText>() { @Override public void onSuccess(FirebaseVisionDocumentText result) { // Task completed successfully // ... } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Task failed with an exception // ... } });
Kotlin+KTX
detector.processImage(myImage) .addOnSuccessListener { firebaseVisionDocumentText -> // Task completed successfully // ... } .addOnFailureListener { e -> // Task failed with an exception // ... }
2. Tanınan metin bloklarından metni çıkarın
Metin tanıma işlemi başarılı olursa FirebaseVisionDocumentText
nesnesini döndürür. FirebaseVisionDocumentText
nesnesi, görüntüde tanınan tam metni ve tanınan belgenin yapısını yansıtan nesnelerin hiyerarşisini içerir:
-
FirebaseVisionDocumentText.Block
-
FirebaseVisionDocumentText.Paragraph
-
FirebaseVisionDocumentText.Word
-
FirebaseVisionDocumentText.Symbol
Her Block
, Paragraph
, Word
ve Symbol
nesnesi için bölgede tanınan metni ve bölgenin sınırlayıcı koordinatlarını alabilirsiniz.
Örneğin:
Java
String resultText = result.getText(); for (FirebaseVisionDocumentText.Block block: result.getBlocks()) { String blockText = block.getText(); Float blockConfidence = block.getConfidence(); List<RecognizedLanguage> blockRecognizedLanguages = block.getRecognizedLanguages(); Rect blockFrame = block.getBoundingBox(); for (FirebaseVisionDocumentText.Paragraph paragraph: block.getParagraphs()) { String paragraphText = paragraph.getText(); Float paragraphConfidence = paragraph.getConfidence(); List<RecognizedLanguage> paragraphRecognizedLanguages = paragraph.getRecognizedLanguages(); Rect paragraphFrame = paragraph.getBoundingBox(); for (FirebaseVisionDocumentText.Word word: paragraph.getWords()) { String wordText = word.getText(); Float wordConfidence = word.getConfidence(); List<RecognizedLanguage> wordRecognizedLanguages = word.getRecognizedLanguages(); Rect wordFrame = word.getBoundingBox(); for (FirebaseVisionDocumentText.Symbol symbol: word.getSymbols()) { String symbolText = symbol.getText(); Float symbolConfidence = symbol.getConfidence(); List<RecognizedLanguage> symbolRecognizedLanguages = symbol.getRecognizedLanguages(); Rect symbolFrame = symbol.getBoundingBox(); } } } }
Kotlin+KTX
val resultText = result.text for (block in result.blocks) { val blockText = block.text val blockConfidence = block.confidence val blockRecognizedLanguages = block.recognizedLanguages val blockFrame = block.boundingBox for (paragraph in block.paragraphs) { val paragraphText = paragraph.text val paragraphConfidence = paragraph.confidence val paragraphRecognizedLanguages = paragraph.recognizedLanguages val paragraphFrame = paragraph.boundingBox for (word in paragraph.words) { val wordText = word.text val wordConfidence = word.confidence val wordRecognizedLanguages = word.recognizedLanguages val wordFrame = word.boundingBox for (symbol in word.symbols) { val symbolText = symbol.text val symbolConfidence = symbol.confidence val symbolRecognizedLanguages = symbol.recognizedLanguages val symbolFrame = symbol.boundingBox } } } }
Sonraki adımlar
- Cloud API kullanan bir uygulamayı üretime dağıtmadan önce, yetkisiz API erişimini önlemek ve etkisini azaltmak için bazı ek adımlar atmanız gerekir.