Author SHA1 Message Date
Gabriel Low bbaa7bb04f Merge branch 'Gabriel' into merge-testing 2026-09-11 11:18:35 +08:00
Gabriel Low 1c6ced2dce this good 2026-09-11 11:12:30 +08:00
Gabriel Low 610bfd7991 Merged Khalil 2026-09-11 10:13:25 +08:00
7 changed files with 9 additions and 30 deletions
@@ -41,8 +41,6 @@ import androidx.lifecycle.LifecycleOwner
import com.example.jnicpp.R
import java.text.SimpleDateFormat
import java.util.Locale
import com.google.mlkit.vision.pose.PoseLandmark // for testing
import java.util.concurrent.Executor
/**
@@ -325,10 +323,6 @@ class CameraXController(
PoseSkeletonRenderer.draw(canvas, poseFrame.landmarks, transform, overlayBonePaint, overlayJointPaint)
PoseSkeletonRenderer.drawAngleLabels(canvas, poseFrame.landmarks, poseFrame.angles, transform, overlayAnglePaint)
val leftWrist = poseFrame.landmarks[PoseLandmark.LEFT_WRIST]
val singleLandmark = if (leftWrist != null) mapOf(PoseLandmark.LEFT_WRIST to leftWrist) else emptyMap()
feedbackUI?.drawCircles(canvas, singleLandmark, transform, forRecord = true)
val state = recordingOverlayStateProvider?.invoke()
val scale = feedbackUI?.computeCamScale(canvas) ?: (minOf(targetWidth, targetHeight) / 1080f)
@@ -11,7 +11,7 @@ import androidx.camera.core.ImageProxy
import com.google.mlkit.vision.common.InputImage
import com.google.mlkit.vision.pose.PoseDetection
import com.google.mlkit.vision.pose.PoseDetector
import com.google.mlkit.vision.pose.defaults.PoseDetectorOptions
import com.google.mlkit.vision.pose.accurate.AccuratePoseDetectorOptions
/**
* @brief Bridges CameraX's [ImageAnalysis] frame stream into ML Kit's
@@ -84,8 +84,8 @@ class PoseAnalyzer(
// if later angle-based form analysis needs the extra precision and a
// real device's frame rate can keep up with it.
private val detector: PoseDetector = PoseDetection.getClient(
PoseDetectorOptions.Builder()
.setDetectorMode(PoseDetectorOptions.STREAM_MODE)
AccuratePoseDetectorOptions.Builder()
.setDetectorMode(AccuratePoseDetectorOptions.STREAM_MODE)
.build()
)
@@ -61,8 +61,7 @@ class PoseLandmarkSmoother(
SmoothedLandmark(
x = prev.x + (smoothingFactor * (landmark.position.x - prev.x)),
y = prev.y + (smoothingFactor * (landmark.position.y - prev.y)),
inFrameLikelihood = prev.inFrameLikelihood +
(smoothingFactor * (landmark.inFrameLikelihood - prev.inFrameLikelihood)),
inFrameLikelihood = landmark.inFrameLikelihood,
)
}
previous[landmark.landmarkType] = next
@@ -12,7 +12,6 @@ import android.util.AttributeSet
import android.view.View
import androidx.core.content.ContextCompat
import com.example.jnicpp.R
import com.google.mlkit.vision.pose.PoseLandmark // for testing
/**
* @brief Draws the 33 ML Kit pose landmarks and connecting skeleton lines
@@ -126,19 +125,6 @@ class PoseOverlayView @JvmOverloads constructor(
val currentLandmarks = landmarks ?: return
PoseSkeletonRenderer.draw(canvas, currentLandmarks, transform, bonePaint, jointPaint)
angles?.let { PoseSkeletonRenderer.drawAngleLabels(canvas, currentLandmarks, it, transform, anglePaint) }
// currentLandmarks to change to landmarks that require highlighting
// test code to contain only left wrist in currentLandmarks to not clutter the screen
val leftWrist = currentLandmarks[PoseLandmark.LEFT_WRIST]
// Build a singleitem map if it exists
val singleLandmark = if (leftWrist != null) {
mapOf(PoseLandmark.LEFT_WRIST to leftWrist)
} else {
emptyMap()
}
// end test code
feedbackUI?.drawCircles(canvas, singleLandmark, transform)
}
/**
@@ -23,7 +23,7 @@ import com.google.mlkit.vision.pose.PoseLandmark
object PoseSkeletonRenderer {
/** @brief Minimum `inFrameLikelihood` a landmark needs to be considered reliable enough to draw or use. */
const val MIN_LIKELIHOOD = 0.5f
const val MIN_LIKELIHOOD = 0.35f
/** @brief Radius, in target/view pixels, of each drawn joint dot. */
const val DOT_RADIUS = 8f
/** @brief Stroke width, in target/view pixels, of each drawn bone line. */
@@ -167,7 +167,7 @@
tools:text="Torso: 12° · Knee L: 168° R: 170°
Elbow L: 85° R: 90°"
app:layout_constraintBottom_toTopOf="@id/switch_pose"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginBottom="12dp"
android:layout_marginBottom="8dp"
android:layout_marginStart="24dp" />
<!-- Delivery Phase Badge -->
@@ -192,7 +192,7 @@
tools:visibility="visible" />
</LinearLayout>
<!-- Bottom Left: Body Angles Readout (above Pose Switch) -->
<!-- Bottom Left: Body Angles Readout (above Audio Toggle) -->
<TextView
android:id="@+id/text_pose_metrics"
android:layout_width="wrap_content"
@@ -206,9 +206,9 @@
android:visibility="gone"
tools:visibility="visible"
tools:text="Torso: 12° · Knee L: 168° R: 170°&#10;Elbow L: 85° R: 90°"
app:layout_constraintBottom_toTopOf="@id/switch_pose"
app:layout_constraintBottom_toTopOf="@id/switch_audio"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginBottom="12dp"
android:layout_marginBottom="8dp"
android:layout_marginStart="16dp" />
<!-- BOTTOM CONTROLS: Pose Overlay Switch & Record Button -->