Skip to content

Instantly share code, notes, and snippets.

@iamjosephmj
Last active December 30, 2024 05:35
Show Gist options
  • Save iamjosephmj/cd58862c466189644f59945881db8361 to your computer and use it in GitHub Desktop.
Save iamjosephmj/cd58862c466189644f59945881db8361 to your computer and use it in GitHub Desktop.
Face Landmarker centering logic
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/camera_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.camera.view.PreviewView
android:id="@+id/view_finder"
android:layout_width="match_parent"
android:layout_height="match_parent" // removed app:scaleType="fillStart"
/>
....
</androidx.coordinatorlayout.widget.CoordinatorLayout>
override fun draw(canvas: Canvas) {
super.draw(canvas)
// Clear previous drawings if results exist but have no face landmarks
if (results?.faceLandmarks().isNullOrEmpty()) {
clear()
return
}
results?.let { faceLandmarkerResult ->
// Calculate scaled image dimensions
val scaledImageWidth = imageWidth * scaleFactor
val scaledImageHeight = imageHeight * scaleFactor
// Calculate offsets to center the image on the canvas
val offsetX = (width - scaledImageWidth) / 2f
val offsetY = (height - scaledImageHeight) / 2f
// Iterate through each detected face
faceLandmarkerResult.faceLandmarks().forEach { faceLandmarks ->
// Draw all landmarks for the current face
drawFaceLandmarks(canvas, faceLandmarks, offsetX, offsetY)
// Draw all connectors for the current face
drawFaceConnectors(canvas, faceLandmarks, offsetX, offsetY)
}
}
}
/**
* Draws all landmarks for a single face on the canvas.
*/
private fun drawFaceLandmarks(
canvas: Canvas,
faceLandmarks: List<NormalizedLandmark>,
offsetX: Float,
offsetY: Float
) {
faceLandmarks.forEach { landmark ->
val x = landmark.x() * imageWidth * scaleFactor + offsetX
val y = landmark.y() * imageHeight * scaleFactor + offsetY
canvas.drawPoint(x, y, pointPaint)
}
}
/**
* Draws all connectors between landmarks for a single face on the canvas.
*/
private fun drawFaceConnectors(
canvas: Canvas,
faceLandmarks: List<NormalizedLandmark>,
offsetX: Float,
offsetY: Float
) {
FaceLandmarker.FACE_LANDMARKS_CONNECTORS.filterNotNull().forEach { connector ->
val startLandmark = faceLandmarks.getOrNull(connector.start())
val endLandmark = faceLandmarks.getOrNull(connector.end())
if (startLandmark != null && endLandmark != null) {
val startX = startLandmark.x() * imageWidth * scaleFactor + offsetX
val startY = startLandmark.y() * imageHeight * scaleFactor + offsetY
val endX = endLandmark.x() * imageWidth * scaleFactor + offsetX
val endY = endLandmark.y() * imageHeight * scaleFactor + offsetY
canvas.drawLine(startX, startY, endX, endY, linePaint)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment