ARCore:如何检测光照不足以排查平面检测失败原因?
Great question—this is a super common pain point when building ARCore apps, since plain timer-based prompts are pretty useless for distinguishing between different failure causes. Here's how you can reliably tie low light conditions to plane detection failures:
1. 利用ARCore内置的光照估计API获取环境亮度
ARCore provides direct access to lighting data that you can use to gauge ambient brightness. In every frame update, extract LightEstimate from the Frame object:
- First check
LightEstimate.isValid()to ensure the data is reliable; - Use
LightEstimate.getPixelIntensity()to get the average pixel brightness of the scene (range: 0-255). Lower values mean darker environments; - For HDR-enabled sessions, you can also use
getEnvironmentalHdrMainLightIntensity()for more precise intensity data (units: cd/m²), butpixelIntensityis usually sufficient for low-light detection.
2. Set a reasonable low-light threshold (test required)
There’s no one-size-fits-all threshold—you’ll need to test with your target devices and use cases:
- Generally, when
pixelIntensitydrops below 30-50, ARCore’s feature point detection degrades sharply, which directly impacts plane detection; - Test your app in varying light conditions, note the
pixelIntensityvalue when plane detection starts failing, and use that as your threshold.
3. Cross-verify with plane detection status and feature point count
Low light alone doesn’t prove it’s causing plane failure. You need to combine three conditions to make a reliable judgment:
- Plane detection status: Track results from
Session.getAllTrackables(Plane.class). Check if no planes are detected for multiple consecutive frames (e.g., 5-10 frames), or if previously detected planes are lost; - Feature point count: Get the total number of feature points via
Frame.getFeaturePointCount(). If the count is below a threshold (e.g., 50), it means ARCore can’t identify enough visual features—this is a direct result of low light.
Only when light level < threshold + feature points < minimum + plane detection fails consecutively can you confidently attribute the issue to low light.
4. Code Example (Kotlin)
Here’s a snippet implementing this logic in the onUpdateFrame callback:
private var badFrameCounter = 0 private val LOW_LIGHT_THRESHOLD = 40f private val MIN_FEATURE_POINTS = 50 private val CONSECUTIVE_BAD_FRAMES = 8 // Trigger alert after 8 consecutive bad frames override fun onUpdateFrame(frame: Frame) { val lightEstimate = frame.lightEstimate if (lightEstimate.isValid) { val pixelIntensity = lightEstimate.pixelIntensity val featurePointCount = frame.featurePointCount val detectedPlanes = session.getAllTrackables(Plane::class.java) val hasValidPlanes = detectedPlanes.any { it.trackingState == TrackingState.TRACKING } // Check if all low-light failure conditions are met val isLowLightIssue = pixelIntensity < LOW_LIGHT_THRESHOLD && featurePointCount < MIN_FEATURE_POINTS && !hasValidPlanes if (isLowLightIssue) { badFrameCounter++ if (badFrameCounter >= CONSECUTIVE_BAD_FRAMES) { // Show warning to user showLowLightWarning() badFrameCounter = 0 // Reset to avoid repeated alerts } } else { badFrameCounter = 0 } } } private fun showLowLightWarning() { // Implement your alert logic (Toast, dialog, etc.) Toast.makeText(context, "Low light detected! Please move to a brighter area to detect planes.", Toast.LENGTH_LONG).show() }
Additional Notes
- Avoid single-frame false positives: Use consecutive frame checks to prevent alerts from temporary obstructions (e.g., a hand covering the lens);
- Device adaptation: Camera sensor sensitivity varies across devices. Consider letting users adjust the threshold in settings, or preset different thresholds for specific device models;
- Distinguish scene issues: If feature points are sufficient but plane detection fails, the problem is likely the scene itself (e.g., plain black walls, smooth glass)—don’t trigger a low-light alert in this case.
内容的提问来源于stack exchange,提问作者toto_tata

