Skip to content

Commit

Permalink
🐛 fixed visualization size issues
Browse files Browse the repository at this point in the history
  • Loading branch information
adeeteya committed May 1, 2023
1 parent a4540d3 commit 20ef899
Show file tree
Hide file tree
Showing 9 changed files with 246 additions and 75 deletions.
Binary file added assets/images/fabio_fognini.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/rafael_nadal.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/roger_federer.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions lib/finals.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ final ServeResult fabioFognini = ServeResult.fromCompleteInferenceList(
"Fabio Fognini",
178,
false,
"assets/images/fabio_fognini.jpeg",
[
[
[260, 304, 0.23688101768493652],
Expand Down Expand Up @@ -1176,6 +1177,7 @@ final ServeResult rogerFederer = ServeResult.fromCompleteInferenceList(
"Roger Federer",
185,
false,
"assets/images/roger_federer.jpeg",
[
[
[264, 304, 0.6883679628372192],
Expand Down Expand Up @@ -2342,6 +2344,7 @@ final ServeResult rafaelNadal = ServeResult.fromCompleteInferenceList(
"Rafael Nadal",
185,
true,
"assets/images/rafael_nadal.jpeg",
[
[
[238, 281, 0.497579962015152],
Expand Down
68 changes: 63 additions & 5 deletions lib/models/serve_result.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@ class InferencePoint {

class ServeResult {
final String playerName;
final String? playerPhotoUrl;
final String? playerPhotoAssetPath;
final int height; //in cm
final bool isLeftHanded;

double minWidth = 2000;
double minHeight = 2000;
double maxHeight = 0;

final List<double> leftShoulderAngles = [];
final List<double> leftKneeAngles = [];
final List<double> leftElbowAngles = [];
Expand All @@ -52,7 +56,7 @@ class ServeResult {
final List<InferencePoint> rightAnklePoints = [];

ServeResult(this.playerName, this.height, this.isLeftHanded,
{this.playerPhotoUrl});
{this.playerPhotoAssetPath});

ServeResult copyWith({String? playerName, int? height, bool? isLeftHanded}) {
return ServeResult(playerName ?? this.playerName, height ?? this.height,
Expand Down Expand Up @@ -180,6 +184,55 @@ class ServeResult {
rightShoulderPoint.point));
rightShoulderAngles.add(getAngle(
rightElbowPoint.point, rightShoulderPoint.point, rightHipPoint.point));

List<double> pointHeights = [
nosePoint.point.dy,
leftEyePoint.point.dy,
rightEyePoint.point.dy,
leftEarPoint.point.dy,
rightEarPoint.point.dy,
leftShoulderPoint.point.dy,
rightShoulderPoint.point.dy,
leftElbowPoint.point.dy,
rightElbowPoint.point.dy,
leftWristPoint.point.dy,
rightWristPoint.point.dy,
leftHipPoint.point.dy,
rightHipPoint.point.dy,
leftKneePoint.point.dy,
rightKneePoint.point.dy,
leftAnklePoint.point.dy,
rightAnklePoint.point.dy,
];
List<double> pointWidths = [
nosePoint.point.dx,
leftEyePoint.point.dx,
rightEyePoint.point.dx,
leftEarPoint.point.dx,
rightEarPoint.point.dx,
leftShoulderPoint.point.dx,
rightShoulderPoint.point.dx,
leftElbowPoint.point.dx,
rightElbowPoint.point.dx,
leftWristPoint.point.dx,
rightWristPoint.point.dx,
leftHipPoint.point.dx,
rightHipPoint.point.dx,
leftKneePoint.point.dx,
rightKneePoint.point.dx,
leftAnklePoint.point.dx,
rightAnklePoint.point.dx,
];

if (pointWidths.min < minWidth) {
minWidth = pointWidths.min;
}
if (pointHeights.min < minHeight) {
minHeight = pointHeights.min;
}
if (pointHeights.max > maxHeight) {
maxHeight = pointHeights.max;
}
}

String heightInFeetAndInches() {
Expand All @@ -188,9 +241,14 @@ class ServeResult {
return "${heightInFeet.floor()}ft ${heightInRemainingInches.round()}in";
}

factory ServeResult.fromCompleteInferenceList(String playerName, int height,
bool isLeftHanded, List completeExtractedInferenceList) {
ServeResult newServeResult = ServeResult(playerName, height, isLeftHanded);
factory ServeResult.fromCompleteInferenceList(
String playerName,
int height,
bool isLeftHanded,
String imageAssetPath,
List completeExtractedInferenceList) {
ServeResult newServeResult = ServeResult(playerName, height, isLeftHanded,
playerPhotoAssetPath: imageAssetPath);
for (var inferenceList in completeExtractedInferenceList) {
newServeResult.addInferenceFromFrame(inferenceList);
}
Expand Down
57 changes: 57 additions & 0 deletions lib/screens/change_reference_player.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'package:flutter/material.dart';
import 'package:tennis_serve_analysis/finals.dart';
import 'package:tennis_serve_analysis/widgets/reference_player_card.dart';

class ChangeReferencePlayerScreen extends StatefulWidget {
final int selectedPlayerIndex;
const ChangeReferencePlayerScreen(
{Key? key, required this.selectedPlayerIndex})
: super(key: key);

@override
State<ChangeReferencePlayerScreen> createState() =>
_ChangeReferencePlayerScreenState();
}

class _ChangeReferencePlayerScreenState
extends State<ChangeReferencePlayerScreen> {
late int selectedIndex;

@override
void initState() {
selectedIndex = widget.selectedPlayerIndex;
super.initState();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Change Reference Player"),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.pop(context, selectedIndex);
},
child: const Icon(Icons.done),
),
body: ListView.builder(
itemCount: availableReferencePlayers.length,
itemBuilder: (context, index) => Padding(
padding: const EdgeInsets.only(bottom: 10),
child: GestureDetector(
onTap: () {
setState(() {
selectedIndex = index;
});
},
child: ReferencePlayerCard(
referencePlayerResult: availableReferencePlayers[index],
isSelected: index == selectedIndex,
),
),
),
),
);
}
}
98 changes: 42 additions & 56 deletions lib/screens/results_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:image/image.dart' as image_lib;
import 'package:tennis_serve_analysis/controllers/user_controller.dart';
import 'package:tennis_serve_analysis/finals.dart';
import 'package:tennis_serve_analysis/models/serve_result.dart';
import 'package:tennis_serve_analysis/screens/change_reference_player.dart';
import 'package:tennis_serve_analysis/utility/classifier.dart';
import 'package:tennis_serve_analysis/utility/isolate_utils.dart';
import 'package:tennis_serve_analysis/widgets/analyzing_loading.dart';
import 'package:tennis_serve_analysis/widgets/reference_player_card.dart';
import 'package:tennis_serve_analysis/widgets/stat_tile.dart';
import 'package:tennis_serve_analysis/widgets/serve_visualizer.dart';

Expand Down Expand Up @@ -153,59 +156,25 @@ class _ResultsScreenState extends ConsumerState<ResultsScreen> {
ref.watch(selectedPlayerProvider(selectedPlayerIndex));
return Scaffold(
appBar: AppBar(
title: const Text("Serve Analysis Result"),
title: const Text("Analysis Result"),
actions: [
if (!isLoading)
IconButton(
onPressed: () async {
await showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text("Change Reference Player"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
RadioListTile(
title: const Text("Fabio Fognini"),
value: 0,
groupValue: selectedPlayerIndex,
onChanged: (val) {
selectedPlayerIndex = val ?? 2;
setState(() {});
Navigator.pop(context);
},
),
RadioListTile(
title: const Text("Roger Federer"),
value: 1,
groupValue: selectedPlayerIndex,
onChanged: (val) {
selectedPlayerIndex = val ?? 0;
setState(() {});
Navigator.pop(context);
},
),
RadioListTile(
title: const Text("Rafael Nadel"),
value: 2,
groupValue: selectedPlayerIndex,
onChanged: (val) {
selectedPlayerIndex = val ?? 1;
setState(() {});
Navigator.pop(context);
},
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text("Ok"),
),
],
),
);
selectedPlayerIndex = availableReferencePlayers.indexWhere(
(element) =>
element.playerName ==
selectedPlayerServeResult.playerName);
selectedPlayerIndex =
(selectedPlayerIndex == -1) ? null : selectedPlayerIndex;
selectedPlayerIndex = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChangeReferencePlayerScreen(
selectedPlayerIndex: selectedPlayerIndex ?? 0)));
setState(() {});
},
tooltip: "Change Reference Player",
icon: const Icon(Icons.change_circle),
)
],
Expand All @@ -217,21 +186,24 @@ class _ResultsScreenState extends ConsumerState<ResultsScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ReferencePlayerCard(
referencePlayerResult: selectedPlayerServeResult,
),
Card(
child: Column(
children: [
const SizedBox(height: 10),
const SizedBox(height: 5),
Row(
children: [
const SizedBox(width: 20),
const SizedBox(
height: 20,
width: 20,
height: 15,
width: 15,
child: ColoredBox(color: Colors.red),
),
const SizedBox(width: 10),
Text(
"User Serve",
"User's Serve",
style: Theme.of(context).textTheme.titleSmall,
),
],
Expand All @@ -241,13 +213,13 @@ class _ResultsScreenState extends ConsumerState<ResultsScreen> {
children: [
const SizedBox(width: 20),
const SizedBox(
height: 20,
width: 20,
height: 15,
width: 15,
child: ColoredBox(color: Colors.green),
),
const SizedBox(width: 10),
Text(
"${selectedPlayerServeResult.playerName} Serve",
"${selectedPlayerServeResult.playerName}'s Serve",
style: Theme.of(context).textTheme.titleSmall,
),
],
Expand All @@ -256,19 +228,33 @@ class _ResultsScreenState extends ConsumerState<ResultsScreen> {
children: [
UserServeVisualizer(
points: serveResult.completeInferenceList,
minSize: Size(
serveResult.minWidth, serveResult.minHeight),
maxSize: Size(
500,
serveResult.maxHeight,
),
),
UserServeVisualizer(
key: ValueKey(
selectedPlayerServeResult.playerName),
points: selectedPlayerServeResult
.completeInferenceList,
isReference: true,
minSize: Size(selectedPlayerServeResult.minWidth,
selectedPlayerServeResult.minHeight),
maxSize: Size(
500,
selectedPlayerServeResult.maxHeight,
),
),
],
),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(10, 15, 20, 5),
padding: const EdgeInsets.fromLTRB(10, 5, 20, 5),
child: Text(
"Average Angles",
style: Theme.of(context).textTheme.titleLarge,
Expand Down
Loading

0 comments on commit 20ef899

Please sign in to comment.