Skip to content

Commit

Permalink
#4, timotheeg#8: Add 'main.runner' and begin work on 'stats-metadata-…
Browse files Browse the repository at this point in the history
…extraction' mode.
  • Loading branch information
r002 committed Mar 14, 2021
1 parent d42f61b commit a3649d9
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 9 deletions.
7 changes: 4 additions & 3 deletions main/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,16 @@ class Config:


def setup() -> Config:
print("Setting up config!")
print(">> Setting up config!")

try:
print("Trying reading from 'config.json'...\n")
print(">> Trying reading from 'config.json'...\n")
# config must be present and valid, will throw if not
with open("config.json") as f:
configDict: dict = json.load(f)
config_from_file: Config = Config(**configDict)
print(">> SUCCESSFULLY read config_from_file:", config_from_file)
print(">> SUCCESSFULLY read config_from_file!\n")
# print(config_from_file)
return config_from_file

# # TODO: Make a Proper config class to handle the config file properly
Expand Down
15 changes: 9 additions & 6 deletions runner.py → main/runner.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
from gen import sayHello, Test

aaa: int = Test.sayTest()
import videoProcessor.statsExtractor as se


def invoke_exit() -> None:
print("Bye! Have a great day! 😀" + str(aaa))
print("Bye! Have a great day! 😀")
exit()


options = {0: invoke_exit, 1: sayHello}
# fmt: off
options = {
0: invoke_exit,
4: se.extractStats
}
# fmt: on

# Present an options menu to solicit the user's input
while True:
Expand All @@ -21,7 +24,7 @@ def invoke_exit() -> None:
1) Generate 'stats-injected' video
2) Generate '*.verify.mp4' video
3) Generate 'verify-snap' frame
4) Generate all stats meta data as '*.txt' file
4) Extract stats metadata from video (-> *.txt)
0) Exit
Expand Down
6 changes: 6 additions & 0 deletions player.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@ def getPaceMaxScore(self):
def getData(self, frame_idx):
return self.lines, self.score, self.level

def getStatsData(self) -> str:
return (
f"{self.score}, {self.lines}, {self.level}, {self.pace_score}, "
+ f"{self.tetris_line_count}"
)

def getTRTLabel(self):
if self.lines is None:
label = ""
Expand Down
116 changes: 116 additions & 0 deletions videoProcessor/statsExtractor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
from io import TextIOWrapper
import numpy
import cv2

import time
from PIL import Image
from player import Player
import main.config as config


def initializePlayers(c: config.Config) -> list:
player1 = Player(
c.p1_lines_xywh,
c.p1_score_xywh,
c.p1_level_xywh,
c.p1_score_stats_xy,
c.p1_pace_stats_xy,
c.p1_trt_stats_xy,
)
player2 = Player(
c.p2_lines_xywh,
c.p2_score_xywh,
c.p2_level_xywh,
c.p2_score_stats_xy,
c.p2_pace_stats_xy,
c.p2_trt_stats_xy,
)
return [player1, player2]


def log(message: str, fileOutput: TextIOWrapper, file: bool, console: bool):
if console:
print(message)
if file:
fileOutput.write(f"{message}\n")


# https://stackoverflow.com/questions/5531249/how-to-convert-time-format-into-milliseconds-and-back-in-python
def conv_ms_to_timestamp(ms: int) -> str:
hours, milliseconds = divmod(ms, 3600000)
minutes, milliseconds = divmod(ms, 60000)
seconds = float(milliseconds) / 1000
return "%i:%02i:%06.3f" % (hours, minutes, seconds)


def extractStats() -> None:
print("Time to extract some stats!")
c: config.Config = config.setup()
# print(">> FINAL Config:", c)

cap = cv2.VideoCapture(r"./videos/fullkoryanscotto1080p.mp4")
total_frames: int = cap.get(cv2.CAP_PROP_FRAME_COUNT)

[player1, player2] = initializePlayers(c)

frame_idx: int = -1
start_time = time.time()

with open("./videos/statsOutput.txt", "w") as outFile:
while True:
cv2_retval, cv2_image = cap.read()

if not cv2_retval:
break

frame_idx += 1

cv2_image = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2RGB)
frame = Image.fromarray(cv2_image)

p1_changed = player1.setFrame(frame)
p2_changed = player2.setFrame(frame)

changed = p1_changed or p2_changed

if changed:
p1_stat = player1.getStatsData()
p2_stat = player2.getStatsData()

cur_ts: str = conv_ms_to_timestamp(cap.get(cv2.CAP_PROP_POS_MSEC))
if p1_changed:
p1_stat = str(p1_stat) + f" <- {cur_ts}"
if p2_changed:
p2_stat = str(p2_stat) + f" <- {cur_ts}"

log("Change detected:", outFile, file=False, console=True)
log(f"{p1_stat}\n{p2_stat}", outFile, file=True, console=True)
# print(f"Current timestamp in video: {cur_ts}")

frame = cv2.cvtColor(numpy.array(frame), cv2.COLOR_RGB2BGR)
status: str = "Processed frame %d of %d (at %5.1f fps)" % (
frame_idx + 1,
total_frames,
(frame_idx + 1) / (time.time() - start_time),
)
print(status, end="\r")
if changed:
# status: str = "Processed frame %d of %d (at %5.1f fps)" % (
# frame_idx + 1,
# total_frames,
# (frame_idx + 1) / (time.time() - start_time),
# )
log(status + "\n", outFile, file=False, console=True)

log(
"\nDone - processed %d frames in %d seconds"
% (total_frames, int(time.time() - start_time)),
outFile,
file=True,
console=True,
)


if __name__ == "__main__":
print("\n### Config StatsExtractor in standlone mode!! ####\n")
extractStats()

0 comments on commit a3649d9

Please sign in to comment.