Skip to content

Commit 6f5855a

Browse files
committed
added comunication with CV processing effects
1 parent 83f6e41 commit 6f5855a

File tree

2 files changed

+134
-21
lines changed

2 files changed

+134
-21
lines changed

src/windows/process_effect.py

+129-16
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import time
3131

3232
from PyQt5.QtCore import *
33-
from PyQt5.QtGui import QIcon, QStandardItemModel, QStandardItem
33+
from PyQt5.QtGui import QIcon, QStandardItemModel, QStandardItem, QPixmap
3434
from PyQt5.QtWidgets import *
3535
from PyQt5 import uic
3636
import openshot # Python module for libopenshot (required video editing module installed separately)
@@ -40,6 +40,53 @@
4040
from classes.logger import log
4141
from classes.metrics import *
4242

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()
4390

4491
class ProcessEffect(QDialog):
4592
""" Choose Profile Dialog """
@@ -84,6 +131,10 @@ def __init__(self, clip_id, effect_name):
84131
self.buttonBox.addButton(self.process_button, QDialogButtonBox.AcceptRole)
85132
self.buttonBox.addButton(self.cancel_button, QDialogButtonBox.RejectRole)
86133

134+
# flag to close the clip processing thread
135+
self.cancel_clip_processing = False
136+
self.effect = None
137+
87138
def accept(self):
88139
""" Start processing effect """
89140
# Disable UI
@@ -96,26 +147,88 @@ def accept(self):
96147
timeline_instance = get_app().window.timeline_sync.timeline
97148
for clip_instance in timeline_instance.Clips():
98149
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()))
114193

115194
# Accept dialog
116195
super(ProcessEffect, self).accept()
117196

118197
def reject(self):
119198
# Cancel dialog
120199
self.exporting = False
200+
self.cancel_clip_processing = True
121201
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

src/windows/views/timeline_webview.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -2962,7 +2962,7 @@ def addEffect(self, effect_names, position):
29622962
if name in ["Bars", "Stabilizer", "Tracker"]:
29632963

29642964
from windows.process_effect import ProcessEffect
2965-
win = ProcessEffect(clip.id, "Stabilizer")
2965+
win = ProcessEffect(clip.id, name)
29662966
# Run the dialog event loop - blocking interaction on this window during this time
29672967
result = win.exec_()
29682968

@@ -2972,15 +2972,15 @@ def addEffect(self, effect_names, position):
29722972
log.info('Cancel processing')
29732973
return
29742974

2975-
effect = win.effect
2976-
2977-
29782975
# Create Effect
2976+
effect = win.effect # effect.Id already set
2977+
if effect is None:
2978+
break
29792979
else:
29802980
effect = openshot.EffectInfo().CreateEffect(name)
2981+
effect.Id(get_app().project.generate_id())
29812982

29822983
# Get Effect JSON
2983-
effect.Id(get_app().project.generate_id())
29842984
effect_json = json.loads(effect.Json())
29852985

29862986
# Append effect JSON to clip

0 commit comments

Comments
 (0)