Mit Firebase ML können Sie bekannte Orientierungspunkte in einem Bild erkennen.
Bevor Sie beginnen
- Falls noch nicht geschehen, fügen Sie Firebase zu Ihrem Android-Projekt hinzu .
- Fügen Sie in Ihrer Modul-Gradle-Datei (auf App-Ebene) (normalerweise
<project>/<app-module>/build.gradle.kts
oder<project>/<app-module>/build.gradle
) die Abhängigkeit für den Firebase ML hinzu Vision-Bibliothek für Android. Wir empfehlen die Verwendung der Firebase Android BoM zur Steuerung der Bibliotheksversionierung.dependencies { // Import the BoM for the Firebase platform implementation(platform("com.google.firebase:firebase-bom:32.8.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' }
Durch die Verwendung der Firebase Android BoM verwendet Ihre App immer kompatible Versionen der Firebase Android-Bibliotheken.
Suchen Sie nach einem Kotlin-spezifischen Bibliotheksmodul? Ab Oktober 2023 (Firebase BoM 32.5.0) können sich sowohl Kotlin- als auch Java-Entwickler auf das Hauptbibliotheksmodul verlassen (Einzelheiten finden Sie in den FAQ zu dieser Initiative ).(Alternative) Fügen Sie Firebase-Bibliotheksabhängigkeiten hinzu , ohne die Stückliste zu verwenden
Wenn Sie die Firebase-Stückliste nicht verwenden möchten, müssen Sie jede Firebase-Bibliotheksversion in ihrer Abhängigkeitszeile angeben.
Beachten Sie: Wenn Sie mehrere Firebase-Bibliotheken in Ihrer App verwenden, empfehlen wir dringend, die BoM zum Verwalten der Bibliotheksversionen zu verwenden, um sicherzustellen, dass alle Versionen kompatibel sind.
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' }
Wenn Sie cloudbasierte APIs für Ihr Projekt noch nicht aktiviert haben, tun Sie dies jetzt:
- Öffnen Sie die Seite „Firebase ML APIs“ der Firebase-Konsole.
Wenn Sie Ihr Projekt noch nicht auf den Blaze-Preisplan aktualisiert haben, klicken Sie dazu auf „Upgrade“ . (Sie werden nur dann zum Upgrade aufgefordert, wenn Ihr Projekt nicht im Blaze-Plan enthalten ist.)
Nur Projekte auf Blaze-Ebene können cloudbasierte APIs verwenden.
- Wenn Cloud-basierte APIs noch nicht aktiviert sind, klicken Sie auf Cloud-basierte APIs aktivieren .
Konfigurieren Sie den Orientierungspunktdetektor
Standardmäßig verwendet der Cloud-Detektor die STABLE
Version des Modells und gibt bis zu 10 Ergebnisse zurück. Wenn Sie eine dieser Einstellungen ändern möchten, geben Sie sie mit einem FirebaseVisionCloudDetectorOptions
-Objekt an.
Um beispielsweise beide Standardeinstellungen zu ändern, erstellen Sie ein FirebaseVisionCloudDetectorOptions
Objekt wie im folgenden Beispiel:
Kotlin+KTX
val options = FirebaseVisionCloudDetectorOptions.Builder() .setModelType(FirebaseVisionCloudDetectorOptions.LATEST_MODEL) .setMaxResults(15) .build()
Java
FirebaseVisionCloudDetectorOptions options = new FirebaseVisionCloudDetectorOptions.Builder() .setModelType(FirebaseVisionCloudDetectorOptions.LATEST_MODEL) .setMaxResults(15) .build();
Um die Standardeinstellungen zu verwenden, können Sie im nächsten Schritt FirebaseVisionCloudDetectorOptions.DEFAULT
verwenden.
Führen Sie den Orientierungspunktdetektor aus
Um Orientierungspunkte in einem Bild zu erkennen, erstellen Sie einFirebaseVisionImage
Objekt entweder aus einem Bitmap
, media.Image
, ByteBuffer
, einem Byte-Array oder einer Datei auf dem Gerät. Übergeben Sie dann das FirebaseVisionImage
Objekt an die Methode detectInImage
von FirebaseVisionCloudLandmarkDetector
.Erstellen Sie aus Ihrem Bild ein
FirebaseVisionImage
Objekt.Um ein
FirebaseVisionImage
Objekt aus einemmedia.Image
Objekt zu erstellen, beispielsweise beim Aufnehmen eines Bildes von der Kamera eines Geräts, übergeben Sie dasmedia.Image
Objekt und die Drehung des Bildes anFirebaseVisionImage.fromMediaImage()
.Wenn Sie die CameraX- Bibliothek verwenden, berechnen die Klassen
OnImageCapturedListener
undImageAnalysis.Analyzer
den Rotationswert für Sie. Sie müssen also nur die Rotation in eine derROTATION_
Konstanten von Firebase ML konvertieren, bevor SieFirebaseVisionImage.fromMediaImage()
aufrufen: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 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 // ... } }
Wenn Sie keine Kamerabibliothek verwenden, die Ihnen die Drehung des Bildes liefert, können Sie diese aus der Drehung des Geräts und der Ausrichtung des Kamerasensors im Gerät berechnen:
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 }
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; }
Übergeben Sie dann das
media.Image
Objekt und den Rotationswert anFirebaseVisionImage.fromMediaImage()
:Kotlin+KTX
val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)
Java
FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
- Um ein
FirebaseVisionImage
Objekt aus einem Datei-URI zu erstellen, übergeben Sie den App-Kontext und den Datei-URI anFirebaseVisionImage.fromFilePath()
. Dies ist nützlich, wenn Sie eineACTION_GET_CONTENT
Absicht verwenden, um den Benutzer aufzufordern, ein Bild aus seiner Galerie-App auszuwählen.Kotlin+KTX
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(); }
- Um ein
FirebaseVisionImage
Objekt aus einemByteBuffer
oder einem Byte-Array zu erstellen, berechnen Sie zunächst die Bildrotation wie oben fürmedia.Image
Eingabe beschrieben.Erstellen Sie dann ein
FirebaseVisionImageMetadata
-Objekt, das die Höhe, Breite, das Farbkodierungsformat und die Drehung des Bildes enthält: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()
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();
Verwenden Sie den Puffer oder das Array und das Metadatenobjekt, um ein
FirebaseVisionImage
Objekt zu erstellen:Kotlin+KTX
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);
- So erstellen Sie ein
FirebaseVisionImage
Objekt aus einemBitmap
Objekt:Das durch dasKotlin+KTX
val image = FirebaseVisionImage.fromBitmap(bitmap)
Java
FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
Bitmap
Objekt dargestellte Bild muss aufrecht stehen, ohne dass eine zusätzliche Drehung erforderlich ist.
Holen Sie sich eine Instanz von
FirebaseVisionCloudLandmarkDetector
:Kotlin+KTX
val detector = FirebaseVision.getInstance() .visionCloudLandmarkDetector // Or, to change the default settings: // val detector = FirebaseVision.getInstance() // .getVisionCloudLandmarkDetector(options)
Java
FirebaseVisionCloudLandmarkDetector detector = FirebaseVision.getInstance() .getVisionCloudLandmarkDetector(); // Or, to change the default settings: // FirebaseVisionCloudLandmarkDetector detector = FirebaseVision.getInstance() // .getVisionCloudLandmarkDetector(options);
Übergeben Sie abschließend das Bild an die Methode
detectInImage
:Kotlin+KTX
val result = detector.detectInImage(image) .addOnSuccessListener { firebaseVisionCloudLandmarks -> // Task completed successfully // ... } .addOnFailureListener { e -> // Task failed with an exception // ... }
Java
Task<List<FirebaseVisionCloudLandmark>> result = detector.detectInImage(image) .addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionCloudLandmark>>() { @Override public void onSuccess(List<FirebaseVisionCloudLandmark> firebaseVisionCloudLandmarks) { // Task completed successfully // ... } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Task failed with an exception // ... } });
Informieren Sie sich über die anerkannten Sehenswürdigkeiten
Wenn die Landmark-Erkennung erfolgreich ist, wird eine Liste vonFirebaseVisionCloudLandmark
Objekten an den Erfolgs-Listener übergeben. Jedes FirebaseVisionCloudLandmark
Objekt stellt einen Orientierungspunkt dar, der im Bild erkannt wurde. Für jeden Orientierungspunkt können Sie seine Begrenzungskoordinaten im Eingabebild, den Namen des Orientierungspunkts, seinen Breiten- und Längengrad, seine Knowledge Graph-Entitäts-ID (falls verfügbar) und den Konfidenzwert der Übereinstimmung abrufen. Zum Beispiel: Kotlin+KTX
for (landmark in firebaseVisionCloudLandmarks) { val bounds = landmark.boundingBox val landmarkName = landmark.landmark val entityId = landmark.entityId val confidence = landmark.confidence // Multiple locations are possible, e.g., the location of the depicted // landmark and the location the picture was taken. for (loc in landmark.locations) { val latitude = loc.latitude val longitude = loc.longitude } }
Java
for (FirebaseVisionCloudLandmark landmark: firebaseVisionCloudLandmarks) { Rect bounds = landmark.getBoundingBox(); String landmarkName = landmark.getLandmark(); String entityId = landmark.getEntityId(); float confidence = landmark.getConfidence(); // Multiple locations are possible, e.g., the location of the depicted // landmark and the location the picture was taken. for (FirebaseVisionLatLng loc: landmark.getLocations()) { double latitude = loc.getLatitude(); double longitude = loc.getLongitude(); } }
Nächste Schritte
- Bevor Sie eine App, die eine Cloud-API verwendet, für die Produktion bereitstellen, sollten Sie einige zusätzliche Schritte unternehmen, um die Auswirkungen eines unbefugten API-Zugriffs zu verhindern und abzuschwächen .