Skip to content

Commit

Permalink
Update to PySide6, tweak ffmpeg call
Browse files Browse the repository at this point in the history
- Update to PySide6 to fix macOS support with Python 3.9
- Try to find ffmpeg in PATH, use FFMPEG_BINARY as fallback
  • Loading branch information
Thomas Fähse authored and Thomas Fähse committed Jan 12, 2022
1 parent 1315df4 commit 8f9591a
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 30 deletions.
8 changes: 4 additions & 4 deletions dashcamcleaner/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import sys
from glob import glob

from PySide2.QtCore import QSettings
from PySide2.QtWidgets import QApplication, QMainWindow, QFileDialog
from PySide2.QtWidgets import QSpinBox, QDoubleSpinBox, QLineEdit, QRadioButton, QMessageBox, QComboBox
from PySide6.QtCore import QSettings
from PySide6.QtWidgets import QApplication, QMainWindow, QFileDialog
from PySide6.QtWidgets import QSpinBox, QDoubleSpinBox, QLineEdit, QRadioButton, QMessageBox, QComboBox

from src.blurrer import VideoBlurrer
from src.ui_mainwindow import Ui_MainWindow
Expand Down Expand Up @@ -33,7 +33,7 @@ def __init__(self):

def load_weights_options(self):
self.ui.combo_box_weights.clear()
for net_path in glob(f"./weights/*.pt"):
for net_path in glob("./weights/*.pt"):
clean_name = os.path.splitext(os.path.basename(net_path))[0]
self.ui.combo_box_weights.addItem(clean_name)
self.setup_blurrer()
Expand Down
78 changes: 59 additions & 19 deletions dashcamcleaner/src/blurrer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
import imageio
import numpy as np
import torch
from PySide2.QtCore import QThread, Signal
from PySide6.QtCore import QThread, Signal
from src.box import Box
from shutil import which


class VideoBlurrer(QThread):
Expand Down Expand Up @@ -42,8 +43,9 @@ def apply_blur(self, frame: np.array, new_detections: list):
roi_multi = self.parameters["roi_multi"]

# gather and process all currently relevant detections
self.detections = [[x[0], x[1] + 1] for x in self.detections if
x[1] <= blur_memory] # throw out outdated detections, increase age by 1
self.detections = [
[x[0], x[1] + 1] for x in self.detections if x[1] <= blur_memory
] # throw out outdated detections, increase age by 1
for detection in new_detections:
scaled_detection = detection.scale(frame.shape, roi_multi)
self.detections.append([scaled_detection, 0])
Expand All @@ -60,18 +62,19 @@ def apply_blur(self, frame: np.array, new_detections: list):
if detection.kind == "plate":
# blur in-place on frame
frame[outer_box.coords_as_slices()] = cv2.blur(
frame[outer_box.coords_as_slices()], (blur_size, blur_size))
frame[outer_box.coords_as_slices()], (blur_size, blur_size)
)
frame[inner_box.coords_as_slices()] = cv2.blur(
frame[inner_box.coords_as_slices()],
(blur_size * 2 + 1, blur_size * 2 + 1))
frame[inner_box.coords_as_slices()], (blur_size * 2 + 1, blur_size * 2 + 1)
)
cv2.rectangle


elif detection.kind == "face":
center, axes = detection.ellipse_coordinates()
# blur rectangle around face
temp[outer_box.coords_as_slices()] = cv2.blur(
temp[outer_box.coords_as_slices()], (blur_size * 2 + 1, blur_size * 2 + 1))
temp[outer_box.coords_as_slices()], (blur_size * 2 + 1, blur_size * 2 + 1)
)
# add ellipse to mask
cv2.ellipse(mask, center, axes, 0, 0, 360, (255, 255, 255), -1)

Expand All @@ -95,7 +98,16 @@ def detect_identifiable_information(self, image: np.array):
boxes = []
for res in results.xyxy[0]:
detection_kind = "plate" if res[5].item() == 0 else "face"
boxes.append(Box(res[0].item(), res[1].item(), res[2].item(), res[3].item(), res[4].item(), detection_kind))
boxes.append(
Box(
res[0].item(),
res[1].item(),
res[2].item(),
res[3].item(),
res[4].item(),
detection_kind,
)
)
return boxes

def run(self):
Expand Down Expand Up @@ -134,7 +146,7 @@ def run(self):
self.setMaximum.emit(length)

if not cap.isOpened():
self.alert.emit('Error: Video file could not be found')
self.alert.emit("Error: Video file could not be found")
return

# loop through video
Expand All @@ -158,20 +170,41 @@ def run(self):
writer.close()

# copy over audio stream from original video to edited video
ffmpeg_exe = os.getenv("FFMPEG_BINARY")
if not ffmpeg_exe:
self.alert.emit(
"FFMPEG could not be found! Please make sure the ffmpeg.exe is available under the envirnment variable 'FFMPEG_BINARY'.")
return
if is_installed("ffmpeg"):
ffmpeg_exe = "ffmpeg"
else:
ffmpeg_exe = os.getenv("FFMPEG_BINARY")
if not ffmpeg_exe:
self.alert.emit(
"FFMPEG could not be found! Please make sure the ffmpeg.exe is available under the envirnment variable 'FFMPEG_BINARY'."
)
return
subprocess.run(
[ffmpeg_exe, "-y", "-i", temp_output, "-i", input_path, "-c", "copy", "-map", "0:0", "-map", "1:1",
"-shortest", output_path])
[
ffmpeg_exe,
"-y",
"-i",
temp_output,
"-i",
input_path,
"-c",
"copy",
"-map",
"0:0",
"-map",
"1:1",
"-shortest",
output_path,
]
)

# delete temporary output that had no audio track
try:
os.remove(temp_output)
except:
self.alert.emit("Could not delete temporary, muted video. Maybe another process (like a cloud service or antivirus) is using it already.")
self.alert.emit(
"Could not delete temporary, muted video. Maybe another process (like a cloud service or antivirus) is using it already."
)

# store success and elapsed time
self.result["success"] = True
Expand All @@ -184,11 +217,18 @@ def setup_detector(weights_path: str):
:param weights_path: path to .pt file with this repo's weights
:return: initialized yolov5 detector
"""
model = torch.hub.load('ultralytics/yolov5', 'custom', weights_path)
model = torch.hub.load("ultralytics/yolov5", "custom", weights_path)
if torch.cuda.is_available():
print(f"Using {torch.cuda.get_device_name(torch.cuda.current_device())}.")
model.cuda()
torch.backends.cudnn.benchmark = True
else:
print("Using CPU.")
return model


def is_installed(name):
"""
Check whether an executable is available
"""
return which(name) is not None
23 changes: 18 additions & 5 deletions dashcamcleaner/src/ui_mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,22 @@
################################################################################
## Form generated from reading UI file 'mainwindow.ui'
##
## Created by: Qt User Interface Compiler version 5.15.2
## Created by: Qt User Interface Compiler version 6.2.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################

from PySide2.QtCore import *
from PySide2.QtWidgets import *

from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QComboBox, QDoubleSpinBox, QFrame,
QHBoxLayout, QLabel, QLineEdit, QMainWindow,
QProgressBar, QPushButton, QSizePolicy, QSpacerItem,
QSpinBox, QVBoxLayout, QWidget)

class Ui_MainWindow(object):
def setupUi(self, MainWindow):
Expand All @@ -35,6 +43,7 @@ def setupUi(self, MainWindow):

self.horizontalLayout.addWidget(self.button_source)


self.verticalLayout.addLayout(self.horizontalLayout)

self.horizontalLayout_2 = QHBoxLayout()
Expand All @@ -51,6 +60,7 @@ def setupUi(self, MainWindow):

self.horizontalLayout_2.addWidget(self.button_target)


self.verticalLayout.addLayout(self.horizontalLayout_2)

self.line = QFrame(self.centralwidget)
Expand Down Expand Up @@ -110,6 +120,7 @@ def setupUi(self, MainWindow):

self.horizontalLayout_3.addWidget(self.double_spin_roimulti)


self.verticalLayout.addLayout(self.horizontalLayout_3)

self.line_2 = QFrame(self.centralwidget)
Expand Down Expand Up @@ -160,6 +171,7 @@ def setupUi(self, MainWindow):

self.horizontalLayout_4.addItem(self.horizontalSpacer)


self.verticalLayout.addLayout(self.horizontalLayout_4)

self.line_3 = QFrame(self.centralwidget)
Expand Down Expand Up @@ -189,14 +201,14 @@ def setupUi(self, MainWindow):

self.horizontalLayout_5.addWidget(self.button_abort)


self.verticalLayout.addLayout(self.horizontalLayout_5)

MainWindow.setCentralWidget(self.centralwidget)

self.retranslateUi(MainWindow)

QMetaObject.connectSlotsByName(MainWindow)

# setupUi

def retranslateUi(self, MainWindow):
Expand All @@ -218,3 +230,4 @@ def retranslateUi(self, MainWindow):
self.button_start.setText(QCoreApplication.translate("MainWindow", u"Start", None))
self.button_abort.setText(QCoreApplication.translate("MainWindow", u"Abort", None))
# retranslateUi

2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ imageio>=2.9.0
imageio-ffmpeg=>=0.4.5
torchvision>=0.8.1
tqdm>=4.41.0
pyside2>=5.15.2
pyside6>=6.2.2.1
requests>=2.25.1
pandas>=1.2.3
seaborn>=0.11.1
Expand Down
2 changes: 1 addition & 1 deletion requirements_gpu.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ torchvision>=0.8.1
imageio>=2.9.0
imageio-ffmpeg=>=0.4.5
tqdm>=4.41.0
pyside2>=5.15.2
pyside2>=6.2.2.1
requests>=2.25.1
pandas>=1.2.3
seaborn>=0.11.1
Expand Down

0 comments on commit 8f9591a

Please sign in to comment.