gradle
posedetection
src
androidMain
commonMain
iosMain
sample
···
5
5
validateDistributionUrl=true
6
6
zipStoreBase=GRADLE_USER_HOME
7
7
zipStorePath=wrapper/dists
8
8
+
org.gradle.jvmargs=-Xmx4G
···
44
44
import androidx.camera.core.Preview
45
45
import androidx.camera.core.ImageAnalysis
46
46
import androidx.camera.core.ImageProxy
47
47
+
import androidx.compose.runtime.DisposableEffect
47
48
import androidx.compose.runtime.rememberCoroutineScope
48
49
import androidx.compose.ui.geometry.Rect
49
50
import com.google.mlkit.vision.pose.PoseDetector
···
75
76
frontCamera: Boolean,
76
77
recordingId: String?,
77
78
focusArea: Rect?,
79
79
+
controller: CameraViewController?,
78
80
onRecordToggled: (Boolean) -> Unit,
79
81
onVideoSaved: (String, String) -> Unit,
80
82
) {
···
212
214
skeletonRepository.updateSkeleton(skel)
213
215
}
214
216
bitmap = _bitmap.asImageBitmap().let { inbmp ->
217
217
+
controller?.setRequestDataProvider {
218
218
+
CameraViewData(
219
219
+
width = inbmp.width.toFloat(),
220
220
+
height = inbmp.height.toFloat(),
221
221
+
rotation = when (imageProxy.imageInfo.rotationDegrees) {
222
222
+
0 -> SensorRotation.ROTATION_0
223
223
+
90 -> SensorRotation.ROTATION_90
224
224
+
180 -> SensorRotation.ROTATION_180
225
225
+
270 -> SensorRotation.ROTATION_270
226
226
+
else -> SensorRotation.ROTATION_0
227
227
+
}
228
228
+
)
229
229
+
}
215
230
addFrameToActiveRecordings(inbmp, timestamp)
216
231
inbmp.drawResults(if(drawSkeleton) analysisResult.skeleton else null, drawObjects?.invoke(analysisResult.objects)?: emptyList())
217
232
}
···
227
242
)
228
243
previewView.scaleType = PreviewView.ScaleType.FIT_CENTER
229
244
}
230
230
-
231
245
Box(
232
246
modifier = modifier
233
247
) {
···
33
33
frontCamera: Boolean = true,
34
34
recordingId: String? = null,
35
35
focusArea: Rect? = null,
36
36
+
controller: CameraViewController? = null,
36
37
onRecordToggled: (Boolean) -> Unit = {},
37
38
onVideoSaved: (String, String) -> Unit
38
39
)
···
47
48
enum class DrawableShape {
48
49
OVAL,RECTANGLE
49
50
}
51
51
+
52
52
+
data class CameraViewData(
53
53
+
val width: Float,
54
54
+
val height: Float,
55
55
+
val rotation: SensorRotation,
56
56
+
)
57
57
+
58
58
+
enum class SensorRotation {
59
59
+
ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270
60
60
+
}
61
61
+
62
62
+
63
63
+
interface CameraViewController {
64
64
+
fun requestData(onResult: (CameraViewData) -> Unit)
65
65
+
fun setRequestDataProvider(provider: (() -> CameraViewData)?)
66
66
+
}
67
67
+
68
68
+
class CameraViewControllerImpl : CameraViewController {
69
69
+
private var dataProvider: (() -> CameraViewData)? = null
70
70
+
override fun requestData(onResult: (CameraViewData) -> Unit) {
71
71
+
dataProvider?.let { onResult(it()) }
72
72
+
}
73
73
+
override fun setRequestDataProvider(provider: (() -> CameraViewData)?) {
74
74
+
dataProvider = provider
75
75
+
}
76
76
+
}
···
201
201
cameraController.customObjectRepository = repository
202
202
}
203
203
204
204
+
fun addCameraViewController(controller: CameraViewController?) {
205
205
+
cameraController.cameraViewController = controller
206
206
+
}
207
207
+
204
208
fun addFrameListener(listener: FrameRepository) {
205
209
cameraController.frameListener = listener
206
210
}
···
246
250
var isUsingFrontCamera = true
247
251
var skeletonRepository: SkeletonRepository? = null
248
252
var customObjectRepository: CustomObjectRespository? = null
253
253
+
var cameraViewController: CameraViewController? = null
249
254
var frameListener: FrameRepository? = null
250
255
var onError: ((CameraException) -> Unit)? = null
251
256
var startTime: Long? = null
···
532
537
previewObjects?.also { objects ->
533
538
customObjectRepository?.updateCustomObject(objects)
534
539
}
535
535
-
536
540
preview.bounds.useContents {
537
541
Pair(
538
542
size.width.toInt(), size.height.toInt()
···
544
548
if (drawSkeleton) previewSkeleton else null,
545
549
drawObjects?.invoke(previewObjects) ?: emptyList()
546
550
).also { drawn ->
551
551
+
cameraViewController?.setRequestDataProvider {
552
552
+
CameraViewData(
553
553
+
width = bo.first.toFloat(),
554
554
+
height = bo.second.toFloat(),
555
555
+
rotation = when (currentVideoOrientation()) {
556
556
+
AVCaptureVideoOrientationPortrait -> SensorRotation.ROTATION_90
557
557
+
AVCaptureVideoOrientationLandscapeRight -> SensorRotation.ROTATION_180
558
558
+
AVCaptureVideoOrientationPortraitUpsideDown -> SensorRotation.ROTATION_270
559
559
+
AVCaptureVideoOrientationLandscapeLeft -> SensorRotation.ROTATION_0
560
560
+
else -> SensorRotation.ROTATION_0
561
561
+
}
562
562
+
)
563
563
+
}
547
564
frameListener?.updateFrame(
548
565
drawn
549
566
)
···
36
36
frontCamera: Boolean,
37
37
recordingId: String?,
38
38
focusArea: Rect?,
39
39
+
controller: CameraViewController?,
39
40
onRecordToggled: (Boolean) -> Unit,
40
41
onVideoSaved: (String, String) -> Unit,
41
42
) {
···
58
59
cameraEngine.value?.apply {
59
60
addSkeletonRepository(skeletonRepository)
60
61
addCustomObjectRepository(customObjectRepository)
62
62
+
addCameraViewController(controller)
61
63
addFrameListener(frameListener)
62
64
setOnVideoSavedCallback(recordingDone)
63
65
setDrawOptions(
···
35
35
import chaintech.videoplayer.model.VideoPlayerConfig
36
36
import chaintech.videoplayer.ui.video.VideoPlayerComposable
37
37
import chaintech.videoplayer.util.RetrieveMediaDuration
38
38
+
import co.touchlab.kermit.Logger
38
39
import com.nate.posedetection.theme.AppTheme
39
40
import com.performancecoachlab.posedetection.camera.CameraView
41
41
+
import com.performancecoachlab.posedetection.camera.CameraViewControllerImpl
40
42
import com.performancecoachlab.posedetection.camera.DetectMode
41
43
import com.performancecoachlab.posedetection.camera.DrawableObject
42
44
import com.performancecoachlab.posedetection.camera.DrawableShape
···
72
74
73
75
@Composable
74
76
internal fun App() = AppTheme {
75
75
-
var selectedTabIndex by remember { mutableStateOf(1) }
77
77
+
var selectedTabIndex by remember { mutableStateOf(0) }
76
78
val tabs = listOf("Camera Feed", "Recorded Video")
77
79
Column {
78
80
TabRow(selectedTabIndex = selectedTabIndex) {
···
307
309
"YOLOv3FP16"
308
310
)
309
311
)
312
312
+
val controller = remember { CameraViewControllerImpl() }
310
313
PermissionProvider().apply {
311
314
if (!hasCameraPermission()) RequestCameraPermission(onGranted = {
312
315
permissionGranted = true
···
344
347
CameraView(
345
348
skeletonRepository = skeletonRepository,
346
349
customObjectRepository = customObjectRespository,
347
347
-
detectMode = DetectMode.BOTH,
350
350
+
detectMode = DetectMode.NONE,
348
351
drawSkeleton = true,
349
352
drawObjects = { obj ->
350
350
-
351
353
obj.map {
352
354
DrawableObject(
353
355
obj = it,
···
362
364
focusArea = Rect(0f,0f,0.1f,1f),
363
365
frontCamera = false,
364
366
recordingId = recordingId,
367
367
+
controller = controller,
365
368
onVideoSaved = {id,url -> path = url },
366
369
)
367
370
}
368
371
Button(
369
372
onClick = {
370
370
-
recordingId = "${Clock.System.now().epochSeconds}"
373
373
+
//recordingId = "${Clock.System.now().epochSeconds}"
374
374
+
controller.requestData { data ->
375
375
+
Logger.d("CameraViewData: $data")
376
376
+
}
371
377
},
372
378
modifier = Modifier.imePadding().padding(16.dp).align(Alignment.TopStart)
373
379
) {
···
10
10
#Android
11
11
android.useAndroidX=true
12
12
android.nonTransitiveRClass=true
13
13
+
android.enableJetifier=true
···
14
14
mavenCentral()
15
15
}
16
16
}
17
17
+
plugins {
18
18
+
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
19
19
+
}
17
20
18
21
dependencyResolutionManagement {
19
22
repositories {