Skip to content

Commit aa05a34

Browse files
committed
refactoring(data): Refactoring inter-process data passing WIP
Add immutable Msg again (still 2-3x slower than main)
1 parent facf30f commit aa05a34

File tree

9 files changed

+47
-70
lines changed

9 files changed

+47
-70
lines changed

foosball/models.py

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -116,24 +116,11 @@ def to_string(self) -> str:
116116
return f'{self.title} {self.value}'
117117

118118

119-
class InfoLog:
120-
def __init__(self, infos=None):
121-
self.infos: [Info] = [] if infos is None else infos
119+
def filter_info(infos: [Info], infoVerbosity: Verbosity = Verbosity.TRACE) -> [Info]:
120+
return [i for i in infos if infoVerbosity is not None and infoVerbosity.value <= i.verbosity.value]
122121

123-
def __iter__(self):
124-
return (i for i in self.infos)
125-
126-
def append(self, info: Info):
127-
self.infos.append(info)
128-
129-
def extend(self, info_log):
130-
self.infos.extend(info_log.infos)
131-
132-
def filter(self, infoVerbosity: Verbosity = Verbosity.TRACE) -> [Info]:
133-
return [i for i in self.infos if infoVerbosity is not None and infoVerbosity.value <= i.verbosity.value]
134-
135-
def to_string(self):
136-
return " - ".join([i.to_string() for i in self.infos])
122+
def infos_to_string(infos: [Info]):
123+
return " - ".join([i.to_string() for i in infos])
137124

138125

139126
@dataclass

foosball/pipe/BaseProcess.py

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,41 +6,26 @@
66
from dataclasses import dataclass
77
from queue import Empty, Full
88

9-
from foosball.models import InfoLog
9+
from foosball.models import Info
1010
from foosball.pipe.Pipe import clear, SENTINEL
1111

1212

1313
# TODO: check why merging into one Msg is having a huge impact on FPS
1414
@dataclass
1515
class Msg:
1616
data: dict
17-
info: InfoLog
17+
info: [Info]
1818
timestamp: dt.datetime = dt.datetime.now()
1919

20-
def __init__(self, data=None, info=InfoLog(), timestamp=dt.datetime.now()):
20+
def __init__(self, data=None, info:[Info] = None, timestamp=dt.datetime.now(), msg: "Msg" = None):
2121
if data is None:
2222
data = dict()
23-
self.data = data
24-
self.info = info
23+
if info is None:
24+
info = list()
25+
self.data = {**(msg.data if msg is not None else {}), **data}
26+
self.info = (msg.info if msg is not None else []) + info
2527
self.timestamp = timestamp
2628

27-
def __getitem__(self, key):
28-
return self.data[key]
29-
30-
def __setitem__(self, key, value):
31-
self.data[key] = value
32-
33-
def add(self, name: str, data: any, info: InfoLog = None):
34-
self.data[name] = data
35-
info_log = InfoLog() if info is None else info
36-
if self.info is not None:
37-
self.info.extend(info_log)
38-
else:
39-
self.info = InfoLog()
40-
41-
def remove(self, name) -> any:
42-
return self.data.pop(name)
43-
4429

4530
class BaseProcess(multiprocessing.Process):
4631
def __init__(self, send_receive_timeout=0.5, *args, **kwargs):

foosball/tracking/ai.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from . import Tracking
1111
from .render import r_text, BLACK
1212
from ..detectors.color import GoalColorConfig, BallColorDetector, BallColorConfig, GoalColorDetector
13-
from ..models import FrameDimensions, Frame, InfoLog, Verbosity
13+
from ..models import FrameDimensions, Frame, Verbosity, Info, filter_info, infos_to_string
1414
from ..sink.opencv import DisplaySink, Key, BallColorCalibration, GoalColorCalibration
1515
from ..source import Source
1616

@@ -108,7 +108,7 @@ def step_frame():
108108
self.fps.update()
109109
result = msg.data.get('Renderer', None)
110110
frame = result.frame if result is not None else None
111-
info: InfoLog = msg.info
111+
info: [Info] = msg.info
112112
self.fps.stop()
113113
fps = int(self.fps.fps())
114114
if not self.headless:
@@ -122,7 +122,7 @@ def step_frame():
122122
break
123123
else:
124124
print(
125-
f"{info.filter(self.infoVerbosity).to_string() if self.infoVerbosity is not None else ''} - FPS: {fps} {BLANKS}",
125+
f"{infos_to_string(filter_info(info, self.infoVerbosity)) if self.infoVerbosity is not None else ''} - FPS: {fps} {BLANKS}",
126126
end="\r")
127127
except Empty:
128128
# logger.debug("No new frame")

foosball/tracking/analyzer/ScoreAnalyzer.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from . import AbstractAnalyzer
88
from ...hooks import AudioHook, Webhook
9-
from ...models import Team, Goals, Score, Track, Info, Verbosity, InfoLog
9+
from ...models import Team, Goals, Score, Track, Info, Verbosity, Info
1010
from ...pipe.BaseProcess import Msg
1111
from ...utils import contains
1212

@@ -52,10 +52,9 @@ def goal_shot(self, goals: Goals, track: Track) -> Optional[Team]:
5252
self.logger.error(f"Error {e}")
5353
return None
5454

55-
def analyze(self, msg: Msg, timestamp: dt.datetime) -> [ScoreAnalyzerResult, InfoLog]:
55+
def analyze(self, msg: Msg, timestamp: dt.datetime) -> [ScoreAnalyzerResult, [Info]]:
5656
goals = msg.data["Tracker"].goals
5757
track = msg.data["Tracker"].ball_track
58-
info = InfoLog()
5958
team_scored = None
6059
try:
6160
self.check_reset_score()
@@ -81,8 +80,10 @@ def analyze(self, msg: Msg, timestamp: dt.datetime) -> [ScoreAnalyzerResult, Inf
8180
self.logger.error("Error in analyzer ", e)
8281
traceback.print_exc()
8382
self.last_track = track
84-
info.append(Info(verbosity=Verbosity.INFO, title="Score", value=self.score.to_string()))
85-
return [ScoreAnalyzerResult(score=self.score, team_scored=team_scored), info]
83+
return [
84+
ScoreAnalyzerResult(score=self.score, team_scored=team_scored),
85+
[Info(verbosity=Verbosity.INFO, title="Score", value=self.score.to_string())]
86+
]
8687

8788
def check_reset_score(self):
8889
if self.score_reset.is_set():

foosball/tracking/analyzer/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from abc import ABC, abstractmethod
33
from datetime import datetime
44

5-
from foosball.models import InfoLog
5+
from foosball.models import Info
66
from foosball.pipe.BaseProcess import Msg
77

88

@@ -13,7 +13,7 @@ def __init__(self, name: str = "UnknownAnalyzer", **kwargs):
1313
self.logger = logging.getLogger(name)
1414

1515
@abstractmethod
16-
def analyze(self, msg: Msg, timestamp: datetime) -> [dict, InfoLog]:
16+
def analyze(self, msg: Msg, timestamp: datetime) -> [dict, [Info]]:
1717
pass
1818

1919
@abstractmethod

foosball/tracking/analyzer/analyze.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import traceback
22

33
from .ScoreAnalyzer import ScoreAnalyzer
4-
from ... import hooks
5-
from ...models import Team
64
from ...pipe.BaseProcess import BaseProcess, Msg
75

86

@@ -23,11 +21,14 @@ def reset_score(self):
2321
a.reset()
2422

2523
def process(self, msg: Msg) -> Msg:
24+
results = {}
25+
infos = []
2626
for a in self.analyzers:
2727
try:
2828
[result, info] = a.analyze(msg, msg.timestamp)
29-
msg.add(a.name, result, info=info)
29+
results[a.name] = result
30+
infos.extend(info)
3031
except Exception as e:
3132
self.logger.error("Error in Analyzer - analyzers ", e)
3233
traceback.print_exc()
33-
return msg
34+
return Msg(msg=msg, info=infos, data=results)

foosball/tracking/preprocess.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import timeit
12
import traceback
23
from enum import Enum
34
from multiprocessing import Queue
@@ -11,7 +12,7 @@
1112
from ..arUcos.models import Aruco
1213
from ..detectors.color import GoalDetector, GoalColorConfig
1314
from ..models import Frame, PreprocessorResult, Point, Rect, Blob, Goals, FrameDimensions, ScaleDirection, \
14-
InfoLog, Info, Verbosity
15+
Info, Verbosity
1516
from ..pipe.BaseProcess import BaseProcess, Msg
1617
from ..pipe.Pipe import clear
1718
from ..utils import ensure_cpu, generate_processor_switches, relative_change, scale
@@ -94,7 +95,7 @@ def process(self, msg: Msg) -> Msg:
9495
frame = self.proc(frame)
9596
frame = scale(frame, self.dims, ScaleDirection.DOWN)
9697
preprocessed = frame
97-
info: InfoLog = InfoLog()
98+
info: [Info] = []
9899
try:
99100
if self.goals_calibration:
100101
try:
@@ -147,8 +148,9 @@ def process(self, msg: Msg) -> Msg:
147148
except Exception as e:
148149
self.logger.error(f"Error in preprocess {e}")
149150
traceback.print_exc()
150-
msg.add("Preprocessor", PreprocessorResult(original=self.iproc(frame), preprocessed=self.iproc(preprocessed), homography_matrix=self.homography_matrix, goals=self.goals), info=info)
151-
return msg
151+
return Msg(msg=msg, info=info, data={
152+
"Preprocessor": PreprocessorResult(original=self.iproc(frame), preprocessed=self.iproc(preprocessed), homography_matrix=self.homography_matrix, goals=self.goals)
153+
})
152154

153155
@staticmethod
154156
def corners2pt(corners) -> [int, int]:

foosball/tracking/render.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import numpy as np
66

77
from const import INFO_VERBOSITY
8-
from ..models import Goal, Score, FrameDimensions, Blob, InfoLog, Verbosity, RendererResult
8+
from ..models import Goal, Score, FrameDimensions, Blob, Verbosity, RendererResult, Info, infos_to_string, filter_info
99
from ..pipe.BaseProcess import Msg, BaseProcess
1010
from ..utils import generate_processor_switches
1111
logger = logging.getLogger(__name__)
@@ -32,7 +32,7 @@ def text_color(key, value):
3232
return GREEN
3333

3434

35-
def r_info(frame, shape: tuple[int, int, int], info: InfoLog, text_scale=1.0, thickness=1) -> None:
35+
def r_info(frame, shape: tuple[int, int, int], info: [Info], text_scale=1.0, thickness=1) -> None:
3636
[height, width, channels] = shape
3737
# loop over the info tuples and draw them on our frame
3838
x = 0
@@ -113,7 +113,7 @@ def __init__(self, dims: FrameDimensions, headless=False, useGPU: bool = False,
113113
def process(self, msg: Msg) -> Msg:
114114
score_analyzer = msg.data["ScoreAnalyzer"]
115115
tracker = msg.data["Tracker"]
116-
info: InfoLog = msg.info
116+
info: [Info] = msg.info
117117
try:
118118
if not self.headless:
119119
shape = tracker.frame.shape
@@ -131,8 +131,10 @@ def process(self, msg: Msg) -> Msg:
131131
r_track(f, track, self.dims.scale)
132132
r_score(f, score, text_scale=1, thickness=4)
133133
if self.infoVerbosity is not None:
134-
r_info(f, shape, info.filter(self.infoVerbosity), text_scale=0.5, thickness=1)
135-
msg.add("Renderer", RendererResult(frame=self.iproc(f)), info=InfoLog())
134+
r_info(f, shape, filter_info(info, self.infoVerbosity), text_scale=0.5, thickness=1)
135+
return Msg(msg=msg, info=None, data={
136+
"Renderer": RendererResult(frame=self.iproc(f))
137+
})
136138
except Exception as e:
137139
logger.error(f"Error in renderer {e}")
138140
traceback.print_exc()

foosball/tracking/tracker.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from const import CalibrationMode
77
from .preprocess import WarpMode, project_blob
88
from ..detectors.color import BallColorDetector, BallColorConfig
9-
from ..models import TrackerResult, Track, Info, Blob, Goals, InfoLog, Verbosity
9+
from ..models import TrackerResult, Track, Info, Blob, Goals, Verbosity
1010
from ..pipe.BaseProcess import BaseProcess, Msg
1111
from ..pipe.Pipe import clear
1212
from ..utils import generate_processor_switches
@@ -46,12 +46,12 @@ def update_ball_track(self, detected_ball: Blob) -> Track:
4646
self.ball_track.appendleft(None)
4747
return self.ball_track
4848

49-
def get_info(self, ball_track: Track) -> InfoLog:
50-
info = InfoLog(infos=[
49+
def get_info(self, ball_track: Track) -> [Info]:
50+
info = [
5151
Info(verbosity=Verbosity.DEBUG, title="Track length", value=f"{str(sum([1 for p in ball_track or [] if p is not None])).rjust(2, ' ')}"),
5252
Info(verbosity=Verbosity.TRACE, title="Calibration", value=f"{self.calibrationMode if self.calibrationMode is not None else 'off'}"),
5353
Info(verbosity=Verbosity.TRACE, title="Tracker", value=f"{'off' if self.off else 'on'}")
54-
])
54+
]
5555
if self.calibration:
5656
[lower, upper] = self.ball_detector.config.bounds
5757
info.append(Info(verbosity=Verbosity.TRACE, title="lower", value=f'({",".join(map(str,lower))})'))
@@ -74,7 +74,7 @@ def process(self, msg: Msg) -> Msg:
7474
ball = None
7575
goals = data.goals
7676
ball_track = None
77-
tracker_info = InfoLog()
77+
tracker_info = []
7878
try:
7979
if not self.off:
8080
if self.calibration:
@@ -104,7 +104,6 @@ def process(self, msg: Msg) -> Msg:
104104
traceback.print_exc()
105105
# TODO: splitting into Preprocess and Tracker data maybe renders this obsolete
106106
if not self.verbose:
107-
msg.add("Tracker", TrackerResult(frame=data.original, goals=goals, ball_track=ball_track, ball=ball), info=tracker_info)
107+
return Msg(msg=msg, info=tracker_info, data={"Tracker": TrackerResult(frame=data.original, goals=goals, ball_track=ball_track, ball=ball)})
108108
else:
109-
msg.add("Tracker", TrackerResult(frame=data.preprocessed, goals=goals, ball_track=ball_track, ball=ball), info=tracker_info)
110-
return msg
109+
return Msg(msg=msg, info=tracker_info, data={"Tracker": TrackerResult(frame=data.preprocessed, goals=goals, ball_track=ball_track, ball=ball)})

0 commit comments

Comments
 (0)