pose_painter.dart 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import 'package:body_detection/models/pose.dart';
  2. import 'package:body_detection/models/pose_landmark.dart';
  3. import 'package:body_detection/models/pose_landmark_type.dart';
  4. import 'package:flutter/widgets.dart';
  5. class PosePainter extends CustomPainter {
  6. final Pose? pose;
  7. final Size imageSize;
  8. PosePainter({required this.pose, required this.imageSize, Key? key});
  9. final pointPaint = Paint()..color = const Color.fromRGBO(255, 255, 255, 0.8);
  10. final leftPointPaint = Paint()..color = const Color.fromRGBO(223, 157, 80, 1);
  11. final rightPointPaint = Paint()..color = const Color.fromRGBO(100, 208, 218, 1);
  12. final linePaint = Paint()
  13. ..color = const Color.fromARGB(228, 0, 0, 0)
  14. ..strokeWidth = 3;
  15. @override
  16. void paint(Canvas canvas, Size size) {
  17. if (pose == null) return;
  18. final double hRatio = imageSize.width == 0 ? 1 : size.width / imageSize.width;
  19. final double vRatio = imageSize.height == 0 ? 1 : size.height / imageSize.height;
  20. offsetForPart(PoseLandmark part) => Offset(part.position.x * hRatio, part.position.y * vRatio);
  21. // Landmark connections
  22. final landmarksByType = {for (final it in pose!.landmarks) it.type: it};
  23. for (final connection in connections) {
  24. if (landmarksByType[connection[0]] != null && landmarksByType[connection[1]] != null) {
  25. final point1 = offsetForPart(landmarksByType[connection[0]]!);
  26. final point2 = offsetForPart(landmarksByType[connection[1]]!);
  27. canvas.drawLine(point1, point2, linePaint);
  28. }
  29. }
  30. // for (final part in pose!.landmarks) {
  31. // // Landmark points
  32. // canvas.drawCircle(offsetForPart(part), 5, pointPaint);
  33. // if (part.type.isLeftSide) {
  34. // canvas.drawCircle(offsetForPart(part), 3, leftPointPaint);
  35. // } else if (part.type.isRightSide) {
  36. // canvas.drawCircle(offsetForPart(part), 3, rightPointPaint);
  37. // }
  38. // // Landmark labels
  39. // TextSpan span = TextSpan(
  40. // text: part.type.toString().substring(16),
  41. // style: const TextStyle(
  42. // color: Color.fromRGBO(0, 128, 255, 1),
  43. // fontSize: 10,
  44. // shadows: [
  45. // Shadow(
  46. // color: Color.fromRGBO(255, 255, 255, 1),
  47. // offset: Offset(1, 1),
  48. // blurRadius: 1,
  49. // ),
  50. // ],
  51. // ),
  52. // );
  53. // TextPainter tp = TextPainter(text: span, textAlign: TextAlign.left);
  54. // tp.textDirection = TextDirection.ltr;
  55. // tp.layout();
  56. // tp.paint(canvas, offsetForPart(part));
  57. // }
  58. }
  59. @override
  60. bool shouldRepaint(PosePainter oldDelegate) {
  61. return oldDelegate.pose != pose || oldDelegate.imageSize != imageSize;
  62. }
  63. static const List<List<PoseLandmarkType>> connections = [
  64. // [PoseLandmarkType.leftEar, PoseLandmarkType.leftEyeOuter],
  65. // [PoseLandmarkType.leftEyeOuter, PoseLandmarkType.leftEye],
  66. // [PoseLandmarkType.leftEye, PoseLandmarkType.leftEyeInner],
  67. // [PoseLandmarkType.leftEyeInner, PoseLandmarkType.nose],
  68. // [PoseLandmarkType.nose, PoseLandmarkType.rightEyeInner],
  69. // [PoseLandmarkType.rightEyeInner, PoseLandmarkType.rightEye],
  70. // [PoseLandmarkType.rightEye, PoseLandmarkType.rightEyeOuter],
  71. // [PoseLandmarkType.rightEyeOuter, PoseLandmarkType.rightEar],
  72. // [PoseLandmarkType.mouthLeft, PoseLandmarkType.mouthRight],
  73. [PoseLandmarkType.leftShoulder, PoseLandmarkType.rightShoulder],
  74. [PoseLandmarkType.leftShoulder, PoseLandmarkType.leftHip],
  75. [PoseLandmarkType.rightShoulder, PoseLandmarkType.rightHip],
  76. [PoseLandmarkType.rightShoulder, PoseLandmarkType.rightElbow],
  77. [PoseLandmarkType.rightWrist, PoseLandmarkType.rightElbow],
  78. // [PoseLandmarkType.rightWrist, PoseLandmarkType.rightThumb],
  79. // [PoseLandmarkType.rightWrist, PoseLandmarkType.rightIndexFinger],
  80. // [PoseLandmarkType.rightWrist, PoseLandmarkType.rightPinkyFinger],
  81. [PoseLandmarkType.leftHip, PoseLandmarkType.rightHip],
  82. [PoseLandmarkType.leftHip, PoseLandmarkType.leftKnee],
  83. [PoseLandmarkType.rightHip, PoseLandmarkType.rightKnee],
  84. [PoseLandmarkType.rightKnee, PoseLandmarkType.rightAnkle],
  85. [PoseLandmarkType.leftKnee, PoseLandmarkType.leftAnkle],
  86. [PoseLandmarkType.leftElbow, PoseLandmarkType.leftShoulder],
  87. [PoseLandmarkType.leftWrist, PoseLandmarkType.leftElbow],
  88. // [PoseLandmarkType.leftWrist, PoseLandmarkType.leftThumb],
  89. // [PoseLandmarkType.leftWrist, PoseLandmarkType.leftIndexFinger],
  90. // [PoseLandmarkType.leftWrist, PoseLandmarkType.leftPinkyFinger],
  91. // [PoseLandmarkType.leftAnkle, PoseLandmarkType.leftHeel],
  92. // [PoseLandmarkType.leftAnkle, PoseLandmarkType.leftToe],
  93. // [PoseLandmarkType.rightAnkle, PoseLandmarkType.rightHeel],
  94. // [PoseLandmarkType.rightAnkle, PoseLandmarkType.rightToe],
  95. // [PoseLandmarkType.rightHeel, PoseLandmarkType.rightToe],
  96. // [PoseLandmarkType.leftHeel, PoseLandmarkType.leftToe],
  97. // [PoseLandmarkType.rightIndexFinger, PoseLandmarkType.rightPinkyFinger],
  98. // [PoseLandmarkType.leftIndexFinger, PoseLandmarkType.leftPinkyFinger],
  99. ];
  100. }