Smoother skeleton
This commit is contained in:
@@ -5,7 +5,6 @@ import androidx.camera.core.ExperimentalGetImage
|
||||
import androidx.camera.core.ImageAnalysis
|
||||
import androidx.camera.core.ImageProxy
|
||||
import com.google.mlkit.vision.common.InputImage
|
||||
import com.google.mlkit.vision.pose.Pose
|
||||
import com.google.mlkit.vision.pose.PoseDetection
|
||||
import com.google.mlkit.vision.pose.PoseDetector
|
||||
import com.google.mlkit.vision.pose.accurate.AccuratePoseDetectorOptions
|
||||
@@ -39,10 +38,13 @@ class PoseAnalyzer(
|
||||
* map it from analysis-image pixels to view pixels, plus the joint
|
||||
* angles derived from that same pose (see [PoseAngleCalculator]) so
|
||||
* downstream consumers (overlay text, future frame-by-frame logging)
|
||||
* don't need to recompute them from [pose] themselves.
|
||||
* don't need to recompute them from [landmarks] themselves. [landmarks]
|
||||
* is already smoothed across frames (see [PoseLandmarkSmoother]) rather
|
||||
* than raw ML Kit output, so anything drawn straight from it doesn't
|
||||
* need to smooth it again.
|
||||
*/
|
||||
data class PoseFrameResult(
|
||||
val pose: Pose,
|
||||
val landmarks: Map<Int, SmoothedLandmark>,
|
||||
val imageWidth: Int,
|
||||
val imageHeight: Int,
|
||||
val rotationDegrees: Int,
|
||||
@@ -56,6 +58,12 @@ class PoseAnalyzer(
|
||||
.build()
|
||||
)
|
||||
|
||||
// One smoother per analyzer instance -- a fresh PoseAnalyzer (see
|
||||
// CameraXController.bindToLifecycle) means a fresh detection stream, so
|
||||
// its smoothing state should start clean rather than lerping in from
|
||||
// whatever pose the previous stream last saw.
|
||||
private val landmarkSmoother = PoseLandmarkSmoother()
|
||||
|
||||
// STRATEGY_KEEP_ONLY_LATEST on the ImageAnalysis use case (see
|
||||
// CameraXController) already ensures we're never handed a backlog, but
|
||||
// this guards against overlapping calls if the detector ever falls
|
||||
@@ -85,16 +93,17 @@ class PoseAnalyzer(
|
||||
|
||||
detector.process(inputImage)
|
||||
.addOnSuccessListener { pose ->
|
||||
val landmarks = landmarkSmoother.smooth(pose)
|
||||
onResult(
|
||||
PoseFrameResult(
|
||||
pose = pose,
|
||||
landmarks = landmarks,
|
||||
imageWidth = width,
|
||||
imageHeight = height,
|
||||
rotationDegrees = rotationDegrees,
|
||||
isFrontCamera = frontCamera,
|
||||
// Cheap (four atan2 pairs at most), safe to compute
|
||||
// on every frame right alongside the detection result.
|
||||
angles = PoseAngleCalculator.compute(pose)
|
||||
angles = PoseAngleCalculator.compute(landmarks)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user