77import sys
88
99class ResultViewer (QtWidgets .QMainWindow ):
10- def __init__ (self , video , displacements , grid , fps = 30 , magnification = 1 , point_size = 10 , colormap = "cool" ):
10+ def __init__ (self , video , displacements , points , fps = 30 , magnification = 1 , point_size = 10 , colormap = "cool" ):
11+ """
12+ The results from the pyidi analysis can directly be passed to this class:
13+
14+ - ``video``: can be a ``VideoReader`` object (or numpy array of correct shape).
15+ - ``displacements``: directly the return from the ``get_displacements`` method.
16+ - ``points``: the points used for the analysis, which were passed to the ``set_points`` method.
17+
18+ Parameters
19+ ----------
20+ video : np.ndarray or VideoReader
21+ Array of shape (n_frames, height, width) containing the video frames.
22+ displacements : np.ndarray
23+ Array of shape (n_frames, n_points, 2) containing the displacement vectors.
24+ points : np.ndarray
25+ Array of shape (n_points, 2) containing the grid points.
26+ fps : int, optional
27+ Frames per second for the video playback, by default 30.
28+ magnification : int, optional
29+ Magnification factor for the displacements, by default 1.
30+ point_size : int, optional
31+ Size of the points in pixels, by default 10.
32+ colormap : str, optional
33+ Name of the colormap to use for the arrows, by default "cool".
34+ """
35+ # Create QApplication if it doesn't exist
36+ app = QtWidgets .QApplication .instance ()
37+ if app is None :
38+ app = QtWidgets .QApplication ([])
39+
1140 super ().__init__ ()
12- self .video = video
13- self .displacements = displacements
14- self .grid = grid
41+
42+ # Coordinate transformation to match viewer function behavior
43+ from ..video_reader import VideoReader
44+ if isinstance (video , VideoReader ):
45+ self .video = video .get_frames ()
46+ else :
47+ self .video = video
48+
49+ self .displacements = displacements [:, :, ::- 1 ] # Flip x,y coordinates
50+ self .grid = points [:, ::- 1 ] + 0.5 # Flip x,y coordinates
1551 self .fps = fps
1652 self .magnification = magnification
1753 self .points_size = point_size
@@ -25,6 +61,14 @@ def __init__(self, video, displacements, grid, fps=30, magnification=1, point_si
2561
2662 self .init_ui ()
2763 self .update_frame ()
64+
65+ # Start the GUI
66+ self .show ()
67+ # Only call sys.exit if not in IPython
68+ if not hasattr (sys , 'ps1' ): # Not interactive
69+ sys .exit (app .exec ())
70+ else :
71+ app .exec () # Don't raise SystemExit in IPython
2872
2973 def init_ui (self ):
3074 # Style
@@ -173,6 +217,7 @@ def init_ui(self):
173217 # === Finalize ===
174218 self .setCentralWidget (central_widget )
175219 self .setWindowTitle ("Displacement Viewer" )
220+ self .resize (800 , 600 )
176221
177222
178223 def toggle_playback (self ):
@@ -337,22 +382,10 @@ def viewer(frames, displacements, points, fps=30, magnification=1, point_size=10
337382 colormap : str, optional
338383 Name of the colormap to use for the arrows, by default "cool".
339384 """
340- points = points [:, ::- 1 ]
341- displacements = displacements [:, :, ::- 1 ]
342-
343- app = QtWidgets .QApplication .instance ()
344- if app is None :
345- app = QtWidgets .QApplication ([])
346-
347- win = ResultViewer (frames , displacements , points , fps = fps , magnification = magnification , point_size = point_size , colormap = colormap )
348- win .resize (800 , 600 )
349- win .show ()
350-
351- # Only call sys.exit if not in IPython
352- if not hasattr (sys , 'ps1' ): # Not interactive
353- sys .exit (app .exec ())
354- else :
355- app .exec () # Don't raise SystemExit in IPythonys
385+ # This function is now just a wrapper for backward compatibility
386+ # The ResultViewer class handles everything internally
387+ ResultViewer (frames , displacements , points , fps = fps , magnification = magnification ,
388+ point_size = point_size , colormap = colormap )
356389
357390
358391if __name__ == "__main__" :
@@ -362,5 +395,6 @@ def viewer(frames, displacements, points, fps=30, magnification=1, point_size=10
362395 displacements = 2 * (np .random .rand (n_points , n_frames , 2 ) - 0.5 )
363396 grid = np .stack (np .meshgrid (np .linspace (50 , 350 , int (np .sqrt (n_points ))),
364397 np .linspace (50 , 250 , int (np .sqrt (n_points )))), axis = - 1 ).reshape (- 1 , 2 )[:n_points ]
365- grid = grid [:, ::- 1 ]
366- viewer (frames , displacements , grid )
398+
399+ # Now you can directly call ResultViewer (no need to flip coordinates here since it's done internally)
400+ ResultViewer (frames , displacements , grid )
0 commit comments