30
30
import time
31
31
32
32
from PyQt5 .QtCore import *
33
- from PyQt5 .QtGui import QIcon , QStandardItemModel , QStandardItem
33
+ from PyQt5 .QtGui import QIcon , QStandardItemModel , QStandardItem , QPixmap
34
34
from PyQt5 .QtWidgets import *
35
35
from PyQt5 import uic
36
36
import openshot # Python module for libopenshot (required video editing module installed separately)
40
40
from classes .logger import log
41
41
from classes .metrics import *
42
42
43
+ class BbWindow (QDialog ):
44
+ def __init__ (self , frame ):
45
+ super ().__init__ ()
46
+ self .setWindowModality (Qt .ApplicationModal )
47
+ self .title = "Bounding Box Selector"
48
+ self .top = 200
49
+ self .left = 500
50
+ self .width = 300
51
+ self .height = 200
52
+ self .windowIconName = os .path .join (info .PATH , 'xdg' , 'openshot-arrow.png' )
53
+ self .rubberBand = QRubberBand (QRubberBand .Rectangle , self )
54
+ self .InitWindow (frame )
55
+ self .origin = QPoint ()
56
+
57
+ def InitWindow (self ,frame ):
58
+ self .setWindowIcon (QIcon (self .windowIconName ))
59
+ self .setWindowTitle (self .title )
60
+ self .setGeometry (self .left , self .top , self .width , self .height )
61
+ vbox = QVBoxLayout ()
62
+ labelImage = QLabel (self )
63
+ pixmap = QPixmap (frame )
64
+ labelImage .setPixmap (pixmap )
65
+ vbox .addWidget (labelImage )
66
+ self .setLayout (vbox )
67
+ self .show ()
68
+
69
+ def closeEvent (self , event ):
70
+ event .accept ()
71
+
72
+ # Set top left rectangle coordinate
73
+ def mousePressEvent (self , event ):
74
+
75
+ if event .button () == Qt .LeftButton :
76
+ self .origin = QPoint (event .pos ())
77
+ self .rubberBand .setGeometry (QRect (self .origin , QSize ()))
78
+ self .rubberBand .show ()
79
+
80
+ # Change rectangle selection while the mouse moves
81
+ def mouseMoveEvent (self , event ):
82
+
83
+ if not self .origin .isNull ():
84
+ self .end = event .pos ()
85
+ self .rubberBand .setGeometry (QRect (self .origin , self .end ).normalized ())
86
+
87
+ # Return bounding box selection coordinates
88
+ def getBB (self ):
89
+ return self .origin .x (), self .origin .y (), self .end .x () - self .origin .x (), self .end .y () - self .origin .y ()
43
90
44
91
class ProcessEffect (QDialog ):
45
92
""" Choose Profile Dialog """
@@ -84,6 +131,10 @@ def __init__(self, clip_id, effect_name):
84
131
self .buttonBox .addButton (self .process_button , QDialogButtonBox .AcceptRole )
85
132
self .buttonBox .addButton (self .cancel_button , QDialogButtonBox .RejectRole )
86
133
134
+ # flag to close the clip processing thread
135
+ self .cancel_clip_processing = False
136
+ self .effect = None
137
+
87
138
def accept (self ):
88
139
""" Start processing effect """
89
140
# Disable UI
@@ -96,26 +147,88 @@ def accept(self):
96
147
timeline_instance = get_app ().window .timeline_sync .timeline
97
148
for clip_instance in timeline_instance .Clips ():
98
149
if clip_instance .Id () == self .clip_id :
99
- self .protobufPath = openshot .ClipProcessingJobs (self .effect_name , clip_instance ).stabilizeVideo (clip_instance )
100
- self .effect = openshot .EffectInfo ().CreateEffect (self .effect_name , "/media/brenno/Data/projects/openshot/stabilization.data" )
101
- # self.effect.SetJson('{"Stabilizer":{"protobuf_data_path": "/home/gustavostahl/LabVisao/VideoEditor/openshot-qt/stabilization.data"}}')
102
- # clip_instance.AddEffect(self.effect)
103
- # return self.effect
104
- print ("Apply effect: %s to clip: %s" % (self .effect_name , clip_instance .Id ()))
105
-
106
-
107
- # EXAMPLE progress updates
108
- # for value in range(1, 100, 4):
109
- # self.progressBar.setValue(value)
110
- # time.sleep(0.25)
111
-
112
- # # Process any queued events
113
- # QCoreApplication.processEvents()
150
+ self .clip_instance = clip_instance
151
+ break
152
+
153
+ # Create effect Id and protobuf data path
154
+ ID = get_app ().project .generate_id ()
155
+
156
+ protobufFolderPath = os .path .join (info .PATH , '..' , 'protobuf_data' )
157
+ # Check if protobuf data folder exists, otherwise it will create one
158
+ if not os .path .exists (protobufFolderPath ):
159
+ os .mkdir (protobufFolderPath )
160
+
161
+ # Create protobuf data path
162
+ protobufPath = os .path .join (protobufFolderPath , ID + '.data' )
163
+
164
+ # Load into JSON string info abou protobuf data path
165
+ jsonString = self .generateJson (protobufPath )
166
+
167
+ # Generate processed data
168
+ processing = openshot .ClipProcessingJobs (self .effect_name , jsonString )
169
+ processing .processClip (self .clip_instance )
170
+
171
+ # get processing status
172
+ while (not processing .IsDone () ):
173
+ # update progressbar
174
+ progressionStatus = processing .GetProgress ()
175
+ self .progressBar .setValue (progressionStatus )
176
+ time .sleep (0.01 )
177
+
178
+ # Process any queued events
179
+ QCoreApplication .processEvents ()
180
+
181
+ # if the cancel button was pressed, close the processing thread
182
+ if (self .cancel_clip_processing ):
183
+ processing .CancelProcessing ()
184
+
185
+ if (not self .cancel_clip_processing ):
186
+
187
+ # Load processed data into effect
188
+ self .effect = openshot .EffectInfo ().CreateEffect (self .effect_name )
189
+ self .effect .SetJson ( '{"protobuf_data_path": "%s"}' % protobufPath )
190
+ self .effect .Id (ID )
191
+
192
+ print ("Applied effect: %s to clip: %s" % (self .effect_name , self .clip_instance .Id ()))
114
193
115
194
# Accept dialog
116
195
super (ProcessEffect , self ).accept ()
117
196
118
197
def reject (self ):
119
198
# Cancel dialog
120
199
self .exporting = False
200
+ self .cancel_clip_processing = True
121
201
super (ProcessEffect , self ).reject ()
202
+
203
+ def generateJson (self , protobufPath ):
204
+ # Start JSON string with the protobuf data path, necessary for all pre-processing effects
205
+ jsonString = '{"protobuf_data_path": "%s"' % protobufPath
206
+
207
+ if self .effect_name == "Stabilizer" :
208
+ pass
209
+
210
+ # Special case where more info is needed for the JSON string
211
+ if self .effect_name == "Tracker" :
212
+
213
+ # Create temporary imagem to be shown in PyQt Window
214
+ temp_img_path = protobufPath .split (".data" )[0 ] + '.png'
215
+ self .clip_instance .GetFrame (0 ).Save (temp_img_path , 1 )
216
+
217
+ # Show bounding box selection window
218
+ bbWindow = BbWindow (temp_img_path )
219
+ bbWindow .exec_ ()
220
+
221
+ # Remove temporary image
222
+ os .remove (temp_img_path )
223
+
224
+ # Get bounding box selection coordinates
225
+ bb = bbWindow .getBB ()
226
+
227
+ # Set tracker info in JSON string
228
+ trackerType = "KCF"
229
+ jsonString += ',"tracker_type": "%s"' % trackerType
230
+ jsonString += ',"bbox": {"x": %d, "y": %d, "w": %d, "h": %d}' % (bb [0 ],bb [1 ],bb [2 ],bb [3 ])
231
+
232
+ # Finish JSON string
233
+ jsonString += '}'
234
+ return jsonString
0 commit comments