Anda dapat menggunakan Firebase ML untuk mengenali bangunan terkenal dalam sebuah gambar.
Sebelum kamu memulai
- Jika Anda belum melakukannya, tambahkan Firebase ke proyek Android Anda .
- Dalam file Gradle modul (level aplikasi) Anda (biasanya
<project>/<app-module>/build.gradle
), tambahkan dependensi untuk library Android Firebase ML Vision. Kami merekomendasikan penggunaan Firebase Android BoM untuk mengontrol pembuatan versi library.dependencies { // Import the BoM for the Firebase platform implementation platform('com.google.firebase:firebase-bom:31.2.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' }
Dengan menggunakan Firebase Android BoM , aplikasi Anda akan selalu menggunakan versi pustaka Android Firebase yang kompatibel.
(Alternatif) Tambahkan dependensi library Firebase tanpa menggunakan BoM
Jika Anda memilih untuk tidak menggunakan Firebase BoM, Anda harus menentukan setiap versi pustaka Firebase di baris dependensinya.
Perhatikan bahwa jika Anda menggunakan beberapa pustaka Firebase di aplikasi Anda, kami sangat menyarankan penggunaan BoM untuk mengelola versi pustaka, yang memastikan bahwa semua versi kompatibel.
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' }
Jika Anda belum mengaktifkan API berbasis Cloud untuk proyek Anda, lakukan sekarang:
- Buka halaman API Firebase ML dari konsol Firebase.
Jika Anda belum mengupgrade proyek Anda ke paket harga Blaze, klik Upgrade untuk melakukannya. (Anda akan diminta untuk memutakhirkan hanya jika proyek Anda tidak termasuk dalam paket Blaze.)
Hanya project level Blaze yang dapat menggunakan API berbasis Cloud.
- Jika API berbasis Cloud belum diaktifkan, klik Aktifkan API berbasis Cloud .
Konfigurasikan detektor bangunan terkenal
Secara default, pendeteksi Cloud menggunakan versi model STABLE
dan menampilkan hingga 10 hasil. Jika Anda ingin mengubah salah satu setelan ini, tentukan dengan objek FirebaseVisionCloudDetectorOptions
.
Misalnya, untuk mengubah kedua setelan default, buat objek FirebaseVisionCloudDetectorOptions
seperti contoh berikut:
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();
Untuk menggunakan setelan default, Anda dapat menggunakan FirebaseVisionCloudDetectorOptions.DEFAULT
di langkah berikutnya.
Jalankan detektor tengara
Untuk mengenali bangunan terkenal dalam gambar, buat objekFirebaseVisionImage
dari Bitmap
, media.Image
, ByteBuffer
, larik byte, atau file di perangkat. Kemudian, teruskan objek FirebaseVisionImage
ke metode detectInImage
dari FirebaseVisionCloudLandmarkDetector
.Buat objek
FirebaseVisionImage
dari gambar Anda.Untuk membuat objek
FirebaseVisionImage
dari objekmedia.Image
, seperti saat mengambil gambar dari kamera perangkat, teruskan objekmedia.Image
dan rotasi gambar keFirebaseVisionImage.fromMediaImage()
.Jika Anda menggunakan pustaka CameraX , kelas
OnImageCapturedListener
danImageAnalysis.Analyzer
menghitung nilai rotasi untuk Anda, jadi Anda hanya perlu mengonversi rotasi ke salah satu konstantaROTATION_
Firebase ML sebelum memanggilFirebaseVisionImage.fromMediaImage()
: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 // ... } }
Jika Anda tidak menggunakan pustaka kamera yang memberikan rotasi gambar, Anda dapat menghitungnya dari rotasi perangkat dan orientasi sensor kamera di perangkat:
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; }
Kemudian, teruskan objek
media.Image
dan nilai rotasi keFirebaseVisionImage.fromMediaImage()
:Kotlin+KTX
val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)
Java
FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
- Untuk membuat objek
FirebaseVisionImage
dari URI file, teruskan konteks aplikasi dan URI file keFirebaseVisionImage.fromFilePath()
. Ini berguna saat Anda menggunakan maksudACTION_GET_CONTENT
untuk meminta pengguna memilih gambar dari aplikasi galeri mereka.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(); }
- Untuk membuat objek
FirebaseVisionImage
dariByteBuffer
atau larik byte, pertama-tama hitung rotasi gambar seperti yang dijelaskan di atas untuk inputmedia.Image
.Kemudian, buat objek
FirebaseVisionImageMetadata
yang berisi tinggi, lebar, format enkode warna, dan rotasi gambar: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();
Gunakan buffer atau larik, dan objek metadata, untuk membuat objek
FirebaseVisionImage
: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);
- Untuk membuat objek
FirebaseVisionImage
dari objekBitmap
:Gambar yang diwakili oleh objekKotlin+KTX
val image = FirebaseVisionImage.fromBitmap(bitmap)
Java
FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
Bitmap
harus tegak, tanpa perlu rotasi tambahan.
Dapatkan instance
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);
Terakhir, teruskan gambar ke metode
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 // ... } });
Dapatkan informasi tentang landmark yang dikenali
Jika operasi pengenalan bangunan terkenal berhasil, daftar objekFirebaseVisionCloudLandmark
akan diteruskan ke pemroses yang berhasil. Setiap objek FirebaseVisionCloudLandmark
merepresentasikan bangunan terkenal yang dikenali dalam gambar. Untuk setiap bangunan terkenal, Anda bisa mendapatkan koordinat pembatasnya di gambar input, nama bangunan terkenal, lintang dan bujurnya, ID entitas Grafik Pengetahuannya (jika tersedia), dan skor keyakinan kecocokan. Sebagai contoh: 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(); } }
Langkah selanjutnya
- Sebelum Anda men-deploy ke produksi aplikasi yang menggunakan Cloud API, Anda harus melakukan beberapa langkah tambahan untuk mencegah dan mengurangi dampak akses API yang tidak sah .