I am trying to have a shape on the video while still having that video as a label instead of having it as a background.
import os
import sys
import numpy as np
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
# https://stackoverflow.com/questions/67488022/how-do-i-run-a-video-in-a-pyqt-container
class ThreadOpenCV(QThread):
changePixmap = pyqtSignal(QImage)
def __init__(self, source):
super().__init__()
self.source = source
self.running = True
def run(self):
print('start')
cap = cv2.VideoCapture(self.source)
self.running = True
while self.running:
ret, frame = cap.read()
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = frame.shape
bytes_per_line = ch * w # PEP8: `lower_case_names` for variables
image = QImage(frame.data, w, h, bytes_per_line, QImage.Format_RGB888)
image = image.scaled(640, 480, Qt.KeepAspectRatio)
self.changePixmap.emit(image)
cap.release()
print('stop')
def stop(self):
self.running = False
class Widget(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
PATH_TO_VIDEO = os.path.join(os.getcwd(), 'videoname.mp4')
self.thread = ThreadOpenCV(PATH_TO_VIDEO)
self.thread.changePixmap.connect(self.setImage)
self.image =""
# layout and adding buttons and images
layout = QVBoxLayout()
self.label_video = QLabel()
layout.addWidget(self.label_video)
self.btn1 = QPushButton("PLAY")
self.btn1.clicked.connect(self.playVideo)
layout.addWidget(self.btn1)
self.btn_stop = QPushButton("STOP")
self.btn_stop.clicked.connect(self.stopVideo)
layout.addWidget(self.btn_stop)
self.widget = QWidget()
self.widget.setLayout(layout)
self.setCentralWidget(self.widget)
def playVideo(self):
self.thread.start()
def stopVideo(self):
self.thread.running = False
def setImage(self, image):
self.image = QPixmap.fromImage(image)
self.update()
self.label_video.setPixmap(self.image)
# https://stackoverflow.com/questions/42769354/draw-on-top-of-image
def paintEvent(self, event):
painter = QPainter(self)
pixmap = QPixmap(self.image)
painter.drawPixmap(self.rect(), pixmap)
pen = QPen(Qt.red, 3)
painter.setPen(pen)
painter.drawEllipse(int(self.frameGeometry().width()//2),int(self.frameGeometry().height()//2) ,50,50)
if __name__ == '__main__':
app = QtWidgets.QApplication([])
mw = Widget()
mw.show()
app.exec()
I was able to get the video to play with a shape on it however it seemed to set the video as a background which isn't what I wanted and the video is also playing but without the drawing Infront. (if self.label_video.setPixmap(self.image) is commented out you can see that the background image does have a drawing on it)
I was curious if this could be done by drawing something and then bringing the drawing to the front if this could be done then how so? (I looked into the raise() method but couldn't figure out how to use it)
I was able to fix it by changing the run function to this
def run(self):
# print('start')
# try:
# self.count
# except:
cap = cv2.VideoCapture(self.source)
fps = float(cap.get(cv2.CAP_PROP_FPS))
self.running = True
while self.running:
time.sleep(1/fps)
ret, frame = cap.read()
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = frame.shape
bytes_per_line = ch * w # PEP8: `lower_case_names` for variables
image = QImage(frame.data, w, h, bytes_per_line, QImage.Format_RGB888)
image = image.scaled(640, 480, Qt.KeepAspectRatio)
painter = QPainter(image)
pixmap = QPixmap(image)
painter.drawPixmap(640,480, pixmap)
pen = QPen(QColor(0, 0, 0), 1)
painter.setPen(pen)
painter.drawEllipse(285,45 ,30,50)
self.count +=1
del painter
del pen
self.changePixmap.emit(image)