คุณสามารถใช้ฟีดกล้องที่ ARCore บันทึกในไปป์ไลน์แมชชีนเลิร์นนิงเพื่อสร้างประสบการณ์ Augmented Reality ที่ชาญฉลาด ตัวอย่าง ARCore ML Kit สาธิตวิธีใช้ ML Kit และ Google Cloud Vision API เพื่อระบุวัตถุในโลกจริง ตัวอย่างใช้โมเดลแมชชีนเลิร์นนิงเพื่อจำแนกวัตถุในมุมมองกล้องและติดป้ายกำกับวัตถุในฉากเสมือนจริง
ตัวอย่าง ARCore ML Kit ที่เขียนด้วยภาษา Kotlin และมีจำหน่ายเป็นตัวอย่าง ml_kotlin ด้วย แอปใน ARCore SDK ที่เก็บ GitHub
ใช้อิมเมจ CPU ของ ARCore
โดยค่าเริ่มต้น ARCore จะบันทึกสตรีมรูปภาพอย่างน้อย 2 ชุดดังนี้
- สตรีมรูปภาพ CPU ที่ใช้สำหรับการจดจำฟีเจอร์และการประมวลผลรูปภาพ โดยค่าเริ่มต้น อิมเมจ CPU มีความละเอียด VGA (640x480) หากจำเป็น คุณสามารถกำหนดค่าให้ ARCore ใช้สตรีมรูปภาพที่มีความละเอียดสูงขึ้น
- สตรีมพื้นผิว GPU ซึ่งมีพื้นผิวความละเอียดสูง โดยปกติจะมีความละเอียดที่ 1080p ซึ่งมักจะใช้เป็นการแสดงตัวอย่างจากกล้องที่แสดงต่อผู้ใช้
ซึ่งจัดเก็บไว้ในพื้นผิว OpenGL ที่ระบุโดย
Session.setCameraTextureName()
- สตรีมเพิ่มเติมใดๆ ที่ระบุโดย
SharedCamera.setAppSurfaces()
ข้อควรพิจารณาเกี่ยวกับขนาดอิมเมจ CPU
ไม่มีค่าใช้จ่ายเพิ่มเติมหากใช้สตรีม CPU ขนาด VGA เริ่มต้น เนื่องจาก ARCore ใช้สตรีมนี้เพื่อทำความเข้าใจผู้คนทั่วโลก การขอสตรีมที่มีความละเอียดอื่นอาจมีค่าใช้จ่ายสูง เนื่องจากต้องมีการบันทึกสตรีมเพิ่มเติม โปรดทราบว่าความละเอียดที่สูงขึ้นอาจทำให้โมเดลของคุณมีราคาแพงอย่างรวดเร็วโดยการเพิ่มความกว้างและความสูงเป็น 2 เท่าเพื่อเพิ่มจำนวนพิกเซลในรูปภาพ
การลดขนาดรูปภาพอาจมีประโยชน์ หากโมเดลของคุณยังทำงานได้ดีในรูปภาพที่มีความละเอียดต่ำ
กำหนดค่าสตรีมรูปภาพ CPU ความละเอียดสูงเพิ่มเติม
ประสิทธิภาพของโมเดล ML อาจขึ้นอยู่กับความละเอียดของรูปภาพที่ใช้เป็นอินพุต คุณปรับความละเอียดของสตรีมเหล่านี้ได้โดยเปลี่ยน CameraConfig
ปัจจุบันโดยใช้ Session.setCameraConfig()
แล้วเลือกการกำหนดค่าที่ถูกต้องจาก 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)
ดึงข้อมูลอิมเมจ CPU
เรียกข้อมูลอิมเมจ CPU โดยใช้ Frame.acquireCameraImage()
รูปภาพเหล่านี้ควรกำจัดทิ้งทันทีที่ไม่จำเป็นต้องใช้แล้ว
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. }
ประมวลผลอิมเมจ CPU
คุณจะใช้ไลบรารีแมชชีนเลิร์นนิงต่างๆ เพื่อประมวลผลอิมเมจของ CPU ได้
- ML Kit: ML Kit มี API การตรวจจับวัตถุและการติดตามในอุปกรณ์
โดยมาพร้อมกับตัวแยกประเภทคร่าวๆ ที่สร้างขึ้นใน API และยังใช้โมเดลการจัดประเภทที่กำหนดเองเพื่อให้ครอบคลุมโดเมนของออบเจ็กต์ที่แคบลงได้
ใช้
InputImage.fromMediaImage
เพื่อแปลงอิมเมจ CPU เป็นInputImage
- แมชชีนเลิร์นนิงของ Firebase: Firebase มี Machine Learning API ที่ทำงานในระบบคลาวด์หรือในอุปกรณ์ ดูเอกสารประกอบของ Firebase เกี่ยวกับป้ายกำกับรูปภาพอย่างปลอดภัยด้วย Cloud Vision โดยใช้การตรวจสอบสิทธิ์และฟังก์ชันของ Firebase บน Android
แสดงผลลัพธ์ในฉาก AR
โมเดลการจดจำรูปภาพมักจะแสดงผลวัตถุที่ตรวจพบโดยการระบุจุดศูนย์กลางหรือรูปหลายเหลี่ยมล้อมรอบซึ่งแทนวัตถุที่ตรวจพบ
การใช้จุดศูนย์กลางหรือจุดศูนย์กลางของกรอบล้อมรอบที่เอาต์พุตจากโมเดลจะทําให้สามารถติดจุดยึดกับวัตถุที่ตรวจพบได้ ใช้ Frame.hitTest()
เพื่อประมาณตำแหน่งของวัตถุในฉากเสมือนจริง
แปลงพิกัด IMAGE_PIXELS
เป็นพิกัด 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.
ใช้พิกัด VIEW
เหล่านี้เพื่อทดสอบ Hit และสร้าง Anchor จากผลลัพธ์
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. }
ข้อพิจารณาด้านประสิทธิภาพ
ทำตามคำแนะนำต่อไปนี้เพื่อประหยัดพลังงานในการประมวลผลและใช้พลังงานน้อยลง
- อย่าเรียกใช้โมเดล ML ในเฟรมขาเข้าทุกเฟรม ลองเรียกใช้การตรวจจับออบเจ็กต์ที่อัตราเฟรมต่ำแทน
- ลองใช้โมเดลการอนุมาน ML ออนไลน์เพื่อลดความซับซ้อนในการประมวลผล
ขั้นตอนถัดไป
- ดูข้อมูลเกี่ยวกับแนวทางปฏิบัติแนะนำสำหรับวิศวกรรม ML
- ดูข้อมูลเกี่ยวกับการใช้ AI อย่างมีความรับผิดชอบ
- โปรดทำตามพื้นฐานของแมชชีนเลิร์นนิงด้วยหลักสูตร TensorFlow