Firebase ML을 사용하여 이미지 속 텍스트를 인식할 수 있습니다. Firebase ML에는 도로 표지판 텍스트와 같은 이미지 속 텍스트 인식에 적합한 범용 API와 문서의 텍스트 인식에 최적화된 API가 모두 있습니다.
시작하기 전에
- 아직 추가하지 않았으면 Android 프로젝트에 Firebase를 추가합니다.
-
모듈(앱 수준) Gradle 파일(일반적으로
<project>/<app-module>/build.gradle.kts
또는<project>/<app-module>/build.gradle
)에서 Android용 Firebase ML Vision 라이브러리의 종속 항목을 추가합니다. 라이브러리 버전 관리 제어에는 Firebase Android BoM을 사용하는 것이 좋습니다.dependencies { // Import the BoM for the Firebase platform implementation(platform("com.google.firebase:firebase-bom:33.7.0")) // Add the dependency for the Firebase ML Vision library // When using the BoM, you don't specify versions in Firebase library dependencies implementation 'com.google.firebase:firebase-ml-vision' }
Firebase Android BoM을 사용하면 앱에서 항상 호환되는 Firebase Android 라이브러리 버전만 사용합니다.
(대안) BoM을 사용하지 않고 Firebase 라이브러리 종속 항목을 추가합니다.
Firebase BoM을 사용하지 않도록 선택한 경우에는 종속 항목 줄에 각 Firebase 라이브러리 버전을 지정해야 합니다.
앱에서 여러 Firebase 라이브러리를 사용하는 경우 모든 버전이 호환되도록 BoM을 사용하여 라이브러리 버전을 관리하는 것이 좋습니다.
dependencies { // Add the dependency for the Firebase ML Vision library // When NOT using the BoM, you must specify versions in Firebase library dependencies implementation 'com.google.firebase:firebase-ml-vision:24.1.0' }
-
프로젝트에 클라우드 기반 API를 아직 사용 설정하지 않았으면 지금 설정하세요.
- Firebase Console의 Firebase ML API 페이지를 엽니다.
-
프로젝트를 Blaze 요금제로 아직 업그레이드하지 않은 경우 업그레이드를 클릭하여 업그레이드하세요. 프로젝트가 Blaze 요금제가 아닌 경우에만 업그레이드하라는 메시지가 표시됩니다.
Blaze 수준 프로젝트만 클라우드 기반 API를 사용할 수 있습니다.
- 클라우드 기반 API가 아직 사용 설정되지 않은 경우 클라우드 기반 API 사용 설정을 클릭합니다.
이제 이미지 속 텍스트 인식을 시작할 수 있습니다.
입력 이미지 가이드라인
-
Firebase ML이 텍스트를 정확하게 인식하려면 입력 이미지에 충분한 픽셀 데이터로 표시된 텍스트가 있어야 합니다. 라틴어 텍스트의 경우 각 문자가 16x16픽셀 이상이어야 좋습니다. 한국어, 중국어, 일본어의 경우 각 문자가 24x24픽셀이어야 합니다. 정확도를 개선시키기 위한 문자 크기 최대치는 모든 언어에서 24x24픽셀입니다.
예를 들어 이미지의 전체 너비를 차지하는 명함을 스캔하려면 640x480픽셀 이미지가 적합합니다. 레터 사이즈 용지에 인쇄된 문서 스캔은 720x1280픽셀 이미지가 적합합니다.
-
이미지 초점이 잘 맞지 않으면 텍스트 인식 정확도가 저하될 수 있습니다. 인식 결과가 만족스럽지 않다면 사용자가 이미지를 다시 캡처하도록 요청합니다.
이미지 속 텍스트 인식
이미지 속 텍스트를 인식하려면 아래에 설명된 대로 텍스트 인식기를 실행합니다.
1. 텍스트 인식기 실행
이미지 속 텍스트를 인식하려면Bitmap
또는 media.Image
, ByteBuffer
, 바이트 배열 또는 기기의 파일에서 FirebaseVisionImage
객체를 만듭니다. 그런 다음 FirebaseVisionImage
객체를 FirebaseVisionTextRecognizer
의 processImage
메서드에 전달합니다.
이미지에서
FirebaseVisionImage
객체를 만듭니다.-
기기의 카메라에서 이미지를 캡처할 때와 같이
media.Image
객체에서FirebaseVisionImage
객체를 만들려면media.Image
객체 및 이미지 회전을FirebaseVisionImage.fromMediaImage()
에 전달합니다.CameraX 라이브러리를 사용하는 경우
OnImageCapturedListener
및ImageAnalysis.Analyzer
클래스가 회전 값을 계산하므로FirebaseVisionImage.fromMediaImage()
를 호출하기 전에 Firebase ML의ROTATION_
상수 중 하나로 회전을 변환하기만 하면 됩니다.Kotlin
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 Vision API // ... } } }
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 Vision API // ... } }
이미지 회전을 제공하는 카메라 라이브러리를 사용하지 않는 경우 기기의 카메라 센서 방향 및 기기 회전에서 이미지 회전을 계산할 수 있습니다.
Kotlin
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 }
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; }
그런 다음
media.Image
객체 및 회전 값을FirebaseVisionImage.fromMediaImage()
에 전달합니다.Kotlin
val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)
Java
FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
- 파일 URI에서
FirebaseVisionImage
객체를 만들려면 앱 컨텍스트 및 파일 URI를FirebaseVisionImage.fromFilePath()
에 전달합니다.ACTION_GET_CONTENT
인텐트를 사용하여 사용자에게 갤러리 앱에서 이미지를 선택하라는 메시지를 표시할 때 유용한 방법입니다.Kotlin
val image: FirebaseVisionImage try { image = FirebaseVisionImage.fromFilePath(context, uri) } catch (e: IOException) { e.printStackTrace() }
Java
FirebaseVisionImage image; try { image = FirebaseVisionImage.fromFilePath(context, uri); } catch (IOException e) { e.printStackTrace(); }
ByteBuffer
또는 바이트 배열에서FirebaseVisionImage
객체를 만들려면 먼저 위에서 설명한 대로media.Image
입력의 이미지 회전을 계산합니다.그런 다음 이미지의 높이, 너비, 색상 인코딩 형식, 회전이 포함된
FirebaseVisionImageMetadata
객체를 만듭니다.Kotlin
val metadata = FirebaseVisionImageMetadata.Builder() .setWidth(480) // 480x360 is typically sufficient for .setHeight(360) // image recognition .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21) .setRotation(rotation) .build()
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();
버퍼나 배열, 메타데이터 객체를 사용하여
FirebaseVisionImage
객체를 만듭니다.Kotlin
val image = FirebaseVisionImage.fromByteBuffer(buffer, metadata) // Or: val image = FirebaseVisionImage.fromByteArray(byteArray, metadata)
Java
FirebaseVisionImage image = FirebaseVisionImage.fromByteBuffer(buffer, metadata); // Or: FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(byteArray, metadata);
Bitmap
객체에서FirebaseVisionImage
객체를 만들려면 다음 안내를 따르세요.Kotlin
val image = FirebaseVisionImage.fromBitmap(bitmap)
Java
FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
Bitmap
객체로 표현된 이미지가 추가 회전이 필요 없는 수직 상태여야 합니다.
-
FirebaseVisionTextRecognizer
의 인스턴스를 가져옵니다.Kotlin
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()
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();
마지막으로 이미지를
processImage
메서드에 전달합니다.Kotlin
val result = detector.processImage(image) .addOnSuccessListener { firebaseVisionText -> // Task completed successfully // ... } .addOnFailureListener { e -> // Task failed with an exception // ... }
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 // ... } });
2. 인식된 텍스트 블록에서 텍스트 추출
텍스트 인식 작업이 성공하면FirebaseVisionText
객체가 성공 리스너에 전달됩니다. FirebaseVisionText
객체는 이미지에서 인식된 전체 텍스트 및 0개 이상의 TextBlock
객체를 포함합니다.
각 TextBlock
은 Line
객체를 0개 이상 포함하는 사각형 모양의 텍스트 블록을 나타냅니다. 각 Line
객체는 단어 및 단어와 유사한 항목(날짜, 숫자 등)을 나타내는 Element
객체를 0개 이상 포함합니다.
각 TextBlock
, Line
, Element
객체에 대해 해당 영역에서 인식된 텍스트와 영역의 경계 좌표를 가져올 수 있습니다.
예를 들면 다음과 같습니다.
Kotlin
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 } } }
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(); } } }
다음 단계
- Cloud API를 사용하는 앱을 프로덕션 환경에 배포하기 전에 몇 가지 추가 단계를 수행하여 승인되지 않은 API 액세스를 방지하고 그로 인한 영향을 완화합니다.
문서의 이미지 속 텍스트 인식
문서의 텍스트를 인식하려면 아래에 설명된 대로 문서 텍스트 인식기를 구성하고 실행합니다.
아래에 설명된 문서 텍스트 인식 API는 문서 이미지 작업에 더욱 편리한 전용 인터페이스를 제공합니다. 하지만 FirebaseVisionTextRecognizer
API에서 제공하는 인터페이스를 사용하려면 클라우드 텍스트 인식기에서 밀집 텍스트 모델을 사용하도록 구성하여 이 인터페이스로 문서를 스캔하면 됩니다.
문서 텍스트 인식 API를 사용하려면 다음을 수행합니다.
1. 텍스트 인식기 실행
이미지 속 텍스트를 인식하려면Bitmap
또는 media.Image
, ByteBuffer
, 바이트 배열 또는 기기의 파일에서 FirebaseVisionImage
객체를 만듭니다.
그런 다음 FirebaseVisionImage
객체를 FirebaseVisionDocumentTextRecognizer
의 processImage
메서드에 전달합니다.
이미지에서
FirebaseVisionImage
객체를 만듭니다.-
기기의 카메라에서 이미지를 캡처할 때와 같이
media.Image
객체에서FirebaseVisionImage
객체를 만들려면media.Image
객체 및 이미지 회전을FirebaseVisionImage.fromMediaImage()
에 전달합니다.CameraX 라이브러리를 사용하는 경우
OnImageCapturedListener
및ImageAnalysis.Analyzer
클래스가 회전 값을 계산하므로FirebaseVisionImage.fromMediaImage()
를 호출하기 전에 Firebase ML의ROTATION_
상수 중 하나로 회전을 변환하기만 하면 됩니다.Kotlin
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 Vision API // ... } } }
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 Vision API // ... } }
이미지 회전을 제공하는 카메라 라이브러리를 사용하지 않는 경우 기기의 카메라 센서 방향 및 기기 회전에서 이미지 회전을 계산할 수 있습니다.
Kotlin
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 }
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; }
그런 다음
media.Image
객체 및 회전 값을FirebaseVisionImage.fromMediaImage()
에 전달합니다.Kotlin
val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)
Java
FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
- 파일 URI에서
FirebaseVisionImage
객체를 만들려면 앱 컨텍스트 및 파일 URI를FirebaseVisionImage.fromFilePath()
에 전달합니다.ACTION_GET_CONTENT
인텐트를 사용하여 사용자에게 갤러리 앱에서 이미지를 선택하라는 메시지를 표시할 때 유용한 방법입니다.Kotlin
val image: FirebaseVisionImage try { image = FirebaseVisionImage.fromFilePath(context, uri) } catch (e: IOException) { e.printStackTrace() }
Java
FirebaseVisionImage image; try { image = FirebaseVisionImage.fromFilePath(context, uri); } catch (IOException e) { e.printStackTrace(); }
ByteBuffer
또는 바이트 배열에서FirebaseVisionImage
객체를 만들려면 먼저 위에서 설명한 대로media.Image
입력의 이미지 회전을 계산합니다.그런 다음 이미지의 높이, 너비, 색상 인코딩 형식, 회전이 포함된
FirebaseVisionImageMetadata
객체를 만듭니다.Kotlin
val metadata = FirebaseVisionImageMetadata.Builder() .setWidth(480) // 480x360 is typically sufficient for .setHeight(360) // image recognition .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21) .setRotation(rotation) .build()
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();
버퍼나 배열, 메타데이터 객체를 사용하여
FirebaseVisionImage
객체를 만듭니다.Kotlin
val image = FirebaseVisionImage.fromByteBuffer(buffer, metadata) // Or: val image = FirebaseVisionImage.fromByteArray(byteArray, metadata)
Java
FirebaseVisionImage image = FirebaseVisionImage.fromByteBuffer(buffer, metadata); // Or: FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(byteArray, metadata);
Bitmap
객체에서FirebaseVisionImage
객체를 만들려면 다음 안내를 따르세요.Kotlin
val image = FirebaseVisionImage.fromBitmap(bitmap)
Java
FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
Bitmap
객체로 표현된 이미지가 추가 회전이 필요 없는 수직 상태여야 합니다.
-
FirebaseVisionDocumentTextRecognizer
의 인스턴스를 가져옵니다.Kotlin
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)
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);
마지막으로 이미지를
processImage
메서드에 전달합니다.Kotlin
detector.processImage(myImage) .addOnSuccessListener { firebaseVisionDocumentText -> // Task completed successfully // ... } .addOnFailureListener { e -> // Task failed with an exception // ... }
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 // ... } });
2. 인식된 텍스트 블록에서 텍스트 추출
텍스트 인식 작업이 성공하면 FirebaseVisionDocumentText
객체가 반환됩니다. FirebaseVisionDocumentText
객체는 이미지에서 인식된 전체 텍스트 및 인식된 문서 구조를 반영하는 객체의 계층 구조를 포함합니다.
FirebaseVisionDocumentText.Block
FirebaseVisionDocumentText.Paragraph
FirebaseVisionDocumentText.Word
FirebaseVisionDocumentText.Symbol
각 Block
, Paragraph
, Word
, Symbol
객체에 대해 해당 영역에서 인식된 텍스트와 영역의 경계 좌표를 가져올 수 있습니다.
예를 들면 다음과 같습니다.
Kotlin
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 } } } }
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(); } } } }
다음 단계
- Cloud API를 사용하는 앱을 프로덕션 환경에 배포하기 전에 몇 가지 추가 단계를 수행하여 승인되지 않은 API 액세스를 방지하고 그로 인한 영향을 완화합니다.