Na podstawie obrazu z kamery zarejestrowanej przez ARCore w ramach potoku systemów uczących się możesz tworzyć inteligentne doświadczenia w rzeczywistości rozszerzonej. Przykład ARCore ML Kit pokazuje, jak używać pakietu ML Kit i Google Cloud Vision API do identyfikowania obiektów w świecie rzeczywistym. W przykładzie użyto modelu systemów uczących się do klasyfikowania obiektów w polu widzenia kamery i dodawania do nich etykiety w scenie wirtualnej.
Przykładowy zestaw ARCore ML Kit został napisany w Kotlin. Jest też dostępna jako przykładowa aplikacja ml_kotlin w repozytorium ARCore SDK na GitHubie.
Użyj obrazu procesora ARCore
ARCore domyślnie rejestruje co najmniej 2 zestawy strumieni obrazów:
- Strumień obrazów procesora używany do rozpoznawania cech i przetwarzania obrazu. Domyślnie obraz procesora ma rozdzielczość VGA (640 x 480). W razie potrzeby można skonfigurować ARCore tak, by używał dodatkowego strumienia obrazów o wyższej rozdzielczości.
- Strumień tekstur GPU zawierający teksturę w wysokiej rozdzielczości, zwykle w rozdzielczości 1080p. Zwykle służy do wyświetlania podglądu z kamery skierowanej do użytkownika.
Wartość ta jest przechowywana w teksturze OpenGL określonej przez
Session.setCameraTextureName()
. - Dodatkowe strumienie określone przez
SharedCamera.setAppSurfaces()
.
Uwagi na temat rozmiaru obrazu procesora
Jeśli używany jest strumień procesora o domyślnej wielkości VGA, nie ponosimy dodatkowych kosztów, ponieważ ARCore używa tego strumienia do zrozumienia treści przez cały świat. Żądanie transmisji o innej rozdzielczości może być kosztowne, ponieważ konieczne będzie zarejestrowanie dodatkowego strumienia. Pamiętaj, że wyższa rozdzielczość może szybko stać się kosztowna dla Twojego modelu: podwojenie szerokości i wysokości obrazu czterokrotnie spowoduje czterokrotne zwiększenie liczby pikseli na obrazie.
Przeskalowanie obrazu w dół może być korzystne, jeśli model nadal dobrze sprawdza się na obrazie w niższej rozdzielczości.
Skonfiguruj dodatkowy strumień obrazów z procesora o wysokiej rozdzielczości
Wydajność modelu ML może zależeć od rozdzielczości obrazu używanego jako dane wejściowe. Rozdzielczość tych strumieni można dostosować, zmieniając bieżący element CameraConfig
za pomocą Session.setCameraConfig()
, wybierając prawidłową konfigurację z Session.getSupportedCameraConfigs()
.
Java
CameraConfigFilter cameraConfigFilter = new CameraConfigFilter(session) // World-facing cameras only. .setFacingDirection(CameraConfig.FacingDirection.BACK); List<CameraConfig> supportedCameraConfigs = session.getSupportedCameraConfigs(cameraConfigFilter); // Select an acceptable configuration from supportedCameraConfigs. CameraConfig cameraConfig = selectCameraConfig(supportedCameraConfigs); session.setCameraConfig(cameraConfig);
Kotlin
val cameraConfigFilter = CameraConfigFilter(session) // World-facing cameras only. .setFacingDirection(CameraConfig.FacingDirection.BACK) val supportedCameraConfigs = session.getSupportedCameraConfigs(cameraConfigFilter) // Select an acceptable configuration from supportedCameraConfigs. val cameraConfig = selectCameraConfig(supportedCameraConfigs) session.setCameraConfig(cameraConfig)
Pobierz obraz procesora
Pobierz obraz procesora za pomocą narzędzia Frame.acquireCameraImage()
.
Takie zdjęcia należy wyrzucić, gdy tylko nie są już potrzebne.
Java
Image cameraImage = null; try { cameraImage = frame.acquireCameraImage(); // Process `cameraImage` using your ML inference model. } catch (NotYetAvailableException e) { // NotYetAvailableException is an exception that can be expected when the camera is not ready // yet. The image may become available on a next frame. } catch (RuntimeException e) { // A different exception occurred, e.g. DeadlineExceededException, ResourceExhaustedException. // Handle this error appropriately. handleAcquireCameraImageFailure(e); } finally { if (cameraImage != null) { cameraImage.close(); } }
Kotlin
// NotYetAvailableException is an exception that can be expected when the camera is not ready yet. // Map it to `null` instead, but continue to propagate other errors. fun Frame.tryAcquireCameraImage() = try { acquireCameraImage() } catch (e: NotYetAvailableException) { null } catch (e: RuntimeException) { // A different exception occurred, e.g. DeadlineExceededException, ResourceExhaustedException. // Handle this error appropriately. handleAcquireCameraImageFailure(e) } // The `use` block ensures the camera image is disposed of after use. frame.tryAcquireCameraImage()?.use { image -> // Process `image` using your ML inference model. }
Przetwarzanie obrazu procesora
Do przetwarzania obrazu procesora można używać różnych bibliotek systemów uczących się.
- ML Kit: ML Kit zapewnia na urządzeniu interfejs API Object Detection and Tracking.
Interfejs API ma wbudowany klasyfikator przybliżony. Może też używać niestandardowych modeli klasyfikacji do objęcia węższą domeną obiektów.
Użyj
InputImage.fromMediaImage
, aby przekonwertować obraz procesora naInputImage
. - Systemy uczące się Firebase: Firebase udostępnia interfejsy API systemów uczących się, które działają w chmurze lub na urządzeniu. Zapoznaj się z dokumentacją Firebase dotyczącą bezpiecznego oznaczania obrazów w Cloud Vision przy użyciu uwierzytelniania i funkcji Firebase na Androidzie.
Wyświetlanie wyników w scenie AR
Modele rozpoznawania obrazów często zwracają wykryte obiekty, wskazując punkt środkowy lub wielokąt ograniczający reprezentujący wykryty obiekt.
Korzystając z punktu środkowego lub środka ramki ograniczającej wyjściowej z modelu, możesz dołączyć do wykrytego obiektu kotwicę. Użyj Frame.hitTest()
, aby oszacować pozycję obiektu w scenie wirtualnej.
Konwertuj współrzędne IMAGE_PIXELS
na współrzędne VIEW
:
Java
// Suppose `mlResult` contains an (x, y) of a given point on the CPU image. float[] cpuCoordinates = new float[] {mlResult.getX(), mlResult.getY()}; float[] viewCoordinates = new float[2]; frame.transformCoordinates2d( Coordinates2d.IMAGE_PIXELS, cpuCoordinates, Coordinates2d.VIEW, viewCoordinates); // `viewCoordinates` now contains coordinates suitable for hit testing.
Kotlin
// Suppose `mlResult` contains an (x, y) of a given point on the CPU image. val cpuCoordinates = floatArrayOf(mlResult.x, mlResult.y) val viewCoordinates = FloatArray(2) frame.transformCoordinates2d( Coordinates2d.IMAGE_PIXELS, cpuCoordinates, Coordinates2d.VIEW, viewCoordinates ) // `viewCoordinates` now contains coordinates suitable for hit testing.
Użyj tych współrzędnych VIEW
, aby przeprowadzić test z trafieniami i utworzyć kotwicę na podstawie wyniku:
Java
List<HitResult> hits = frame.hitTest(viewCoordinates[0], viewCoordinates[1]); HitResult depthPointResult = null; for (HitResult hit : hits) { if (hit.getTrackable() instanceof DepthPoint) { depthPointResult = hit; break; } } if (depthPointResult != null) { Anchor anchor = depthPointResult.getTrackable().createAnchor(depthPointResult.getHitPose()); // This anchor will be attached to the scene with stable tracking. // It can be used as a position for a virtual object, with a rotation prependicular to the // estimated surface normal. }
Kotlin
val hits = frame.hitTest(viewCoordinates[0], viewCoordinates[1]) val depthPointResult = hits.filter { it.trackable is DepthPoint }.firstOrNull() if (depthPointResult != null) { val anchor = depthPointResult.trackable.createAnchor(depthPointResult.hitPose) // This anchor will be attached to the scene with stable tracking. // It can be used as a position for a virtual object, with a rotation prependicular to the // estimated surface normal. }
Możliwe spowolnienie działania witryny
Postępuj zgodnie z tymi zaleceniami, aby oszczędzać moc obliczeniową i zużywać mniej energii:
- Nie uruchamiaj modelu ML w każdej przychodzącej ramce. Rozważ uruchomienie wykrywania obiektów z małą liczbą klatek na sekundę.
- Rozważ zastosowanie modelu wnioskowania dotyczącego systemów uczących się online, aby zmniejszyć złożoność obliczeniową.
Dalsze kroki
- Poznaj sprawdzone metody dla inżynierii systemów uczących się.
- Dowiedz się więcej o metodach odpowiedzialnej AI.
- Zapoznaj się z podstawowymi informacjami o systemach uczących się w ramach kursu TensorFlow.