103103class HolisticPool :
104104 _lock = threading .Lock ()
105105 _instances : Dict [str , List ] = {}
106+ # A small blank frame used to clear tracking state between videos.
107+ # Faster than reset() (which tears down and restarts the entire MediaPipe graph)
108+ # while producing identical results to static_image_mode=True on the next frame.
109+ _BLANK_FRAME = np .ones ((256 , 256 , 3 ), dtype = np .uint8 ) * 255
106110
107111 @staticmethod
108112 def _config_key (config : dict ) -> str :
@@ -117,18 +121,25 @@ def acquire(cls, n: int, config: dict) -> list:
117121 while pool and len (acquired ) < n :
118122 acquired .append (pool .pop ())
119123
124+ # Clear tracking state for reused instances by processing a blank frame.
125+ # This flushes the PreviousLoopbackCalculator state so the next real frame
126+ # runs full detection instead of using stale tracking from a previous video.
127+ reused = acquired [:len (acquired ) - need ]
128+ if reused and not config .get ('static_image_mode' , False ):
129+ with ThreadPoolExecutor (max_workers = len (reused )) as ex :
130+ list (ex .map (lambda h : h .process (cls ._BLANK_FRAME ), reused ))
131+
120132 need = n - len (acquired )
121133 if need > 0 :
122- new = [mp_holistic .Holistic (** config ) for _ in range (need )]
134+ with ThreadPoolExecutor (max_workers = need ) as ex :
135+ new = list (ex .map (lambda _ : mp_holistic .Holistic (** config ), range (need )))
123136 acquired .extend (new )
124137
125138 return acquired
126139
127140 @classmethod
128141 def release (cls , instances : list , config : dict ):
129142 key = cls ._config_key (config )
130- for h in instances :
131- h .reset ()
132143 with cls ._lock :
133144 cls ._instances .setdefault (key , []).extend (instances )
134145
0 commit comments