Webcam streamer with PyQt and Python threading, PySerial and GPIO [duplicate] - python

Try to link PyQt and Opencv video feed, can't understand how to apply while loop for continuously streaming video. It just take a still picture.Please can anyone help to solve the problem.
PtQt=5
Python=3.6.1
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 Video'
self.left = 100
self.top = 100
self.width = 640
self.height = 480
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.resize(1800, 1200)
#create a label
label = QLabel(self)
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
convertToQtFormat = QtGui.QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0],
QtGui.QImage.Format_RGB888)
convertToQtFormat = QtGui.QPixmap.fromImage(convertToQtFormat)
pixmap = QPixmap(convertToQtFormat)
resizeImage = pixmap.scaled(640, 480, QtCore.Qt.KeepAspectRatio)
QApplication.processEvents()
label.setPixmap(resizeImage)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())

The problem is that the function that obtains the image is executed only once and not updating the label.
The correct way is to place it inside a loop, but it will result in blocking the main window. This blocking of main window can be solved by using the QThread class and send through a signal QImage to update the label. For example:
import cv2
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication
from PyQt5.QtCore import QThread, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QImage, QPixmap
class Thread(QThread):
changePixmap = pyqtSignal(QImage)
def run(self):
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if ret:
# https://stackoverflow.com/a/55468544/6622587
rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = rgbImage.shape
bytesPerLine = ch * w
convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888)
p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
self.changePixmap.emit(p)
class App(QWidget):
def __init__(self):
super().__init__()
[...]
self.initUI()
#pyqtSlot(QImage)
def setImage(self, image):
self.label.setPixmap(QPixmap.fromImage(image))
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.resize(1800, 1200)
# create a label
self.label = QLabel(self)
self.label.move(280, 120)
self.label.resize(640, 480)
th = Thread(self)
th.changePixmap.connect(self.setImage)
th.start()
self.show()

Updating this for PySide2 and qimage2ndarray
from PySide2.QtCore import *
from PySide2.QtGui import *
import cv2 # OpenCV
import qimage2ndarray # for a memory leak,see gist
import sys # for exiting
# Minimal implementation...
def displayFrame():
ret, frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image = qimage2ndarray.array2qimage(frame)
label.setPixmap(QPixmap.fromImage(image))
app = QApplication([])
window = QWidget()
# OPENCV
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
# timer for getting frames
timer = QTimer()
timer.timeout.connect(displayFrame)
timer.start(60)
label = QLabel('No Camera Feed')
button = QPushButton("Quiter")
button.clicked.connect(sys.exit) # quiter button
layout = QVBoxLayout()
layout.addWidget(button)
layout.addWidget(label)
window.setLayout(layout)
window.show()
app.exec_()
# See also: https://gist.github.com/bsdnoobz/8464000

Thank you Taimur Islam for the question.
Thank you eyllanesc for wonderful answering and I have modified your code little bit. I used PtQt=4 Python=2.7 and I didn't use opencv
import sys
import numpy as np
import flycapture2 as fc2
from PyQt4.QtCore import (QThread, Qt, pyqtSignal)
from PyQt4.QtGui import (QPixmap, QImage, QApplication, QWidget, QLabel)
class Thread(QThread):
changePixmap = pyqtSignal(QImage)
def __init__(self, parent=None):
QThread.__init__(self, parent=parent)
self.cameraSettings()
def run(self):
while True:
im = fc2.Image()
self.c.retrieve_buffer(im)
a = np.array(im)
rawImage = QImage(a.data, a.shape[1], a.shape[0], QImage.Format_Indexed8)
self.changePixmap.emit(rawImage)
def cameraSettings(self):
print(fc2.get_library_version())
self.c = fc2.Context()
numberCam = self.c.get_num_of_cameras()
print(numberCam)
self.c.connect(*self.c.get_camera_from_index(0))
print(self.c.get_camera_info())
m, f = self.c.get_video_mode_and_frame_rate()
print(m, f)
print(self.c.get_property_info(fc2.FRAME_RATE))
p = self.c.get_property(fc2.FRAME_RATE)
print(p)
self.c.set_property(**p)
self.c.start_capture()
class App(QWidget):
def __init__(self):
super(App,self).__init__()
self.title = 'PyQt4 Video'
self.left = 100
self.top = 100
self.width = 640
self.height = 480
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.resize(800, 600)
# create a label
self.label = QLabel(self)
self.label.move(0, 0)
self.label.resize(640, 480)
th = Thread(self)
th.changePixmap.connect(lambda p: self.setPixMap(p))
th.start()
def setPixMap(self, p):
p = QPixmap.fromImage(p)
p = p.scaled(640, 480, Qt.KeepAspectRatio)
self.label.setPixmap(p)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())

Related

Open new window for webcam in PyQt5

I want to make Webcam gui so that when I click the cam on button the second window pops up and video will start.
When I click the return button the video should stop and go to mainwindow, but when i try, I can't see video, even if the flag is printed.
import threading
import cv2
import threading
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtTest import *
from PyQt5 import QtWidgets
from PyQt5 import QtGui
from PyQt5 import QtCore
running = False
class MyApp(QMainWindow, QWidget):
def __init__(self):
super().__init__()
self.second_UI = QDialog()
self.label = QtWidgets.QLabel()
self.first_UI()
self.show()
def first_UI(self):
btn_start = QPushButton("cam on", self)
btn_start.move(50, 50)
btn_start.clicked.connect(self.cam_start)
btn_start.clicked.connect(self.second_exc)
self.sb = self.statusBar()
self.sb.showMessage('Ready')
# Window setting
self.setWindowTitle('Select Servo Motor')
self.setGeometry(300, 300, 1024, 768)
self.show()
def cam_run(self):
global running
print("Flag1")
self.cap = cv2.VideoCapture(0)
# 'http://192.168.66.1:9527/videostream.cgi?loginuse=admin&loginpas=admin')
self.wid = 500
self.hei = 500
self.label.resize(self.wid, self.hei)
while running:
print("Flag2")
self.ret, self.img = self.cap.read()
if self.ret:
self.img = cv2.cvtColor(self.img, cv2.COLOR_BGR2RGB)
self.h, self.w, self.c = self.img.shape
self.qImg = QtGui.QImage(self.img.data, self.w, self.h, self.w*self.c,
QtGui.QImage.Format_RGB888)
self.pixmap = QtGui.QPixmap.fromImage(self.qImg)
self.label.setPixmap(self.pixmap)
print("Flag3")
self.cap.release()
print("Thread end.")
def cam_start(self): # , UI_param):
#UI_param = self.second_UI
global running
running = True
self.th = threading.Thread(target=self.cam_run)
self.th.start()
print("started...")
def second_exc(self):
self.close()
self.cam_run
return_btn = QPushButton('Return', self.second_UI)
return_btn.move(50, 700) # set position
# return_btn.resize(return_btn.sizeHint())
return_btn.clicked.connect(self.first_UI)
self.second_UI.setWindowTitle('Select User Mode')
self.second_UI.setGeometry(300, 300, 1024, 768)
self.second_UI.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex_ = MyApp()
sys.exit(app.exec_())
Look at the following coding. It does what you are aiming for. I would recommend to create ui with qt designer and not fumble around with coding.
import cv2
import sys
from PyQt5 import uic
from PyQt5.QtWidgets import QMainWindow, QApplication
cap = cv2.VideoCapture(0)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
uic.loadUi(r"main_window.ui", self)
self.btn_start_cam.clicked.connect(self.start_cam)
self.btn_return.clicked.connect(self.stop_cam)
def start_cam(self):
#Initialize video capture
#scaling factor
scaling_factor = 0.5
ret, frame = cap.read()
# Resize the frame
frame = cv2.resize(frame, None, fx=scaling_factor,
fy=scaling_factor, interpolation=cv2.INTER_AREA)
# Display the image
cv2.imshow('Webcam', frame)
def stop_cam(self):
# Release the video capture object
cap.release()
# Close all active windows
cv2.destroyAllWindows()
if __name__ == "__main__":
app = QApplication(sys.argv)
myapp = MainWindow()
myapp.show()
sys.exit(app.exec_())

How to Run Multiple Cameras live in a single window using Python PYQT Desktop?

Here is my code, It's Flashing When I runs it bur working both cameras, Also It is a Very difficult for me to put the camera display correctly one camera on left and other on right but tried a lot to do so. Actually I am a Beginner right now. It a Python Code in PYQT5 with OpenCV(Python) in it. I am going to use it on Raspberry.
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.VBL = QVBoxLayout()
self.showMaximized()
self.FeedLabel = QLabel()
self.VBL.addWidget(self.FeedLabel)
self.setGeometry(0, 0, 1920, 1000)
self.VBL1 = QVBoxLayout()
# self.showMaximized()
# self.FeedLabel = QLabel()
# self.VBL1.addWidget(self.FeedLabel)
self.VBL1.setGeometry(QtCore.QRect(0, 0, 900, 1000))
self.setLayout(self.VBL)
self.VBL2 = QVBoxLayout()
# self.showMaximized()
# self.FeedLabel = QLabel()
# self.VBL2.addWidget(self.FeedLabel)
self.setGeometry(QtCore.QRect(QPoint(100, 200), QSize(11, 16)))
# self.setGeometry()
self.setLayout(self.VBL)
# self.CancelBTN = QPushButton(Cancel)
# self.CancelBTN.clicked.connect(self.CancelFeed)
# self.VBL.addWidget(self.CancelBTN)
# self.frame = QtWidgets.QFrame(self)
# self.frame.setGeometry(QtCore.QRect(1, 1, 200, 200))
# self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
# self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.Worker1 = Worker1()
self.Worker1.start()
self.Worker1.ImageUpdate1.connect(self.ImageUpdateSlot1)
self.setLayout(self.VBL1)
self.Worker2 = Worker2()
self.Worker2.start()
self.Worker2.ImageUpdate.connect(self.ImageUpdateSlot)
self.setLayout(self.VBL2)
def ImageUpdateSlot(self, Image):
self.FeedLabel.setPixmap(QPixmap.fromImage(Image))
def ImageUpdateSlot1(self, Image):
self.FeedLabel.setPixmap(QPixmap.fromImage(Image))
def CancelFeed(self):
self.Worker1.stop()
class Worker1(QThread):
ImageUpdate1 = pyqtSignal(QImage)
def run(self):
self.ThreadActive = True
Capture = cv2.VideoCapture(0)
while self.ThreadActive:
ret, frame = Capture.read()
if ret:
Image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
FlippedImage = cv2.flip(Image, 1)
ConvertToQtFormat = QImage(FlippedImage.data, FlippedImage.shape[1], FlippedImage.shape[0], QImage.Format_RGB888)
Pic = ConvertToQtFormat.scaled(960, 1080)
self.ImageUpdate1.emit(Pic)
def stop(self):
self.ThreadActive = False
self.quit()
class Worker2(QThread):
ImageUpdate = pyqtSignal(QImage)
def run(self):
self.ThreadActive = True
Capture = cv2.VideoCapture(1)
while self.ThreadActive:
ret, frame = Capture.read()
if ret:
Image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
FlippedImage = cv2.flip(Image, 1)
ConvertToQtFormat = QImage(FlippedImage.data, FlippedImage.shape[1], FlippedImage.shape[0], QImage.Format_RGB888)
Pic = ConvertToQtFormat.scaled(400, 800)
self.ImageUpdate.emit(Pic)
def stop(self):
self.ThreadActive = False
self.quit()
if __name__ == "__main__":
App = QApplication(sys.argv)
Root = MainWindow()
Root.show()
sys.exit(App.exec())

How to display live camera video from opencv in pyqt5? [duplicate]

Try to link PyQt and Opencv video feed, can't understand how to apply while loop for continuously streaming video. It just take a still picture.Please can anyone help to solve the problem.
PtQt=5
Python=3.6.1
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 Video'
self.left = 100
self.top = 100
self.width = 640
self.height = 480
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.resize(1800, 1200)
#create a label
label = QLabel(self)
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
convertToQtFormat = QtGui.QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0],
QtGui.QImage.Format_RGB888)
convertToQtFormat = QtGui.QPixmap.fromImage(convertToQtFormat)
pixmap = QPixmap(convertToQtFormat)
resizeImage = pixmap.scaled(640, 480, QtCore.Qt.KeepAspectRatio)
QApplication.processEvents()
label.setPixmap(resizeImage)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
The problem is that the function that obtains the image is executed only once and not updating the label.
The correct way is to place it inside a loop, but it will result in blocking the main window. This blocking of main window can be solved by using the QThread class and send through a signal QImage to update the label. For example:
import cv2
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication
from PyQt5.QtCore import QThread, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QImage, QPixmap
class Thread(QThread):
changePixmap = pyqtSignal(QImage)
def run(self):
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if ret:
# https://stackoverflow.com/a/55468544/6622587
rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = rgbImage.shape
bytesPerLine = ch * w
convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888)
p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
self.changePixmap.emit(p)
class App(QWidget):
def __init__(self):
super().__init__()
[...]
self.initUI()
#pyqtSlot(QImage)
def setImage(self, image):
self.label.setPixmap(QPixmap.fromImage(image))
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.resize(1800, 1200)
# create a label
self.label = QLabel(self)
self.label.move(280, 120)
self.label.resize(640, 480)
th = Thread(self)
th.changePixmap.connect(self.setImage)
th.start()
self.show()
Updating this for PySide2 and qimage2ndarray
from PySide2.QtCore import *
from PySide2.QtGui import *
import cv2 # OpenCV
import qimage2ndarray # for a memory leak,see gist
import sys # for exiting
# Minimal implementation...
def displayFrame():
ret, frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image = qimage2ndarray.array2qimage(frame)
label.setPixmap(QPixmap.fromImage(image))
app = QApplication([])
window = QWidget()
# OPENCV
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
# timer for getting frames
timer = QTimer()
timer.timeout.connect(displayFrame)
timer.start(60)
label = QLabel('No Camera Feed')
button = QPushButton("Quiter")
button.clicked.connect(sys.exit) # quiter button
layout = QVBoxLayout()
layout.addWidget(button)
layout.addWidget(label)
window.setLayout(layout)
window.show()
app.exec_()
# See also: https://gist.github.com/bsdnoobz/8464000
Thank you Taimur Islam for the question.
Thank you eyllanesc for wonderful answering and I have modified your code little bit. I used PtQt=4 Python=2.7 and I didn't use opencv
import sys
import numpy as np
import flycapture2 as fc2
from PyQt4.QtCore import (QThread, Qt, pyqtSignal)
from PyQt4.QtGui import (QPixmap, QImage, QApplication, QWidget, QLabel)
class Thread(QThread):
changePixmap = pyqtSignal(QImage)
def __init__(self, parent=None):
QThread.__init__(self, parent=parent)
self.cameraSettings()
def run(self):
while True:
im = fc2.Image()
self.c.retrieve_buffer(im)
a = np.array(im)
rawImage = QImage(a.data, a.shape[1], a.shape[0], QImage.Format_Indexed8)
self.changePixmap.emit(rawImage)
def cameraSettings(self):
print(fc2.get_library_version())
self.c = fc2.Context()
numberCam = self.c.get_num_of_cameras()
print(numberCam)
self.c.connect(*self.c.get_camera_from_index(0))
print(self.c.get_camera_info())
m, f = self.c.get_video_mode_and_frame_rate()
print(m, f)
print(self.c.get_property_info(fc2.FRAME_RATE))
p = self.c.get_property(fc2.FRAME_RATE)
print(p)
self.c.set_property(**p)
self.c.start_capture()
class App(QWidget):
def __init__(self):
super(App,self).__init__()
self.title = 'PyQt4 Video'
self.left = 100
self.top = 100
self.width = 640
self.height = 480
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.resize(800, 600)
# create a label
self.label = QLabel(self)
self.label.move(0, 0)
self.label.resize(640, 480)
th = Thread(self)
th.changePixmap.connect(lambda p: self.setPixMap(p))
th.start()
def setPixMap(self, p):
p = QPixmap.fromImage(p)
p = p.scaled(640, 480, Qt.KeepAspectRatio)
self.label.setPixmap(p)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())

Video Playback speed is faster than expected pyQt5 and Opencv

i am working on an Opencv project and when trying to add the gui for it, i wanted to use PyQt because i am familiar with it.
in this code
import cv2
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication
from PyQt5.QtCore import QThread, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QImage, QPixmap
class Thread(QThread):
changePixmap = pyqtSignal(QImage)
def run(self):
cap = cv2.VideoCapture("../Testing-Video.mp4")
while True:
ret, frame = cap.read()
if ret:
rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = rgbImage.shape
bytesPerLine = ch * w
convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine,
QImage.Format_RGB888)
p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
self.changePixmap.emit(p)
class App(QWidget):
def __init__(self):
super().__init__()
self.left=0
self.top=0
self.width=600
self.height=800
self.initUI()
#pyqtSlot(QImage)
def setImage(self, image):
self.label.setPixmap(QPixmap.fromImage(image))
def initUI(self):
self.setWindowTitle("Testing PyQt")
self.setGeometry(self.left, self.top, self.width, self.height)
self.resize(800, 600)
# create a label
self.label = QLabel(self)
self.label.resize(640, 480)
th = Thread(self)
th.changePixmap.connect(self.setImage)
th.start()
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())
which is something i didn't write myself, it's slightly adjusted from here , anyways using the Camera video capture, it works perfectly but when using any other video media, the playback is extremely fast,
should i use a timer to call the frames constantly? better than using signal and slots?

PyQt5 Paint Circle Over Video in QLabel

I want to draw a circle that displays over a video at the cursor location when pressing the mouse. The video is playing in a QLabel object that is in a MainWindow. I’m using OpenCV to read frames from the webcam at 10 fps. I’m converting the frames to QPixmap and displaying them in the QLabel object (self.vidWindow).
In the code below, the circle is painted immediately when the MainWindow is launched (not what I want) and is then covered up by the video stream. Text displays in the mask Qlabel object and a message is printed in the MainWindow when the mouse button is pressed.
Can I draw a circle in a QLabel object? If so, should I use the mask QLabel object or is there a way to overlay directly over the video in the self.vidWindow?
In the minimalized version of the code, the video displays, but an error is triggered when I try to draw the ellipse.
import sys, cv2
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel
from PyQt5.QtGui import QImage, QPixmap, QPainter, QPen, QFont
from PyQt5.QtCore import QTimer, Qt, QCoreApplication
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.statusBar().showMessage('Ready')
self.setGeometry(50, 50, 800, 600)
self.setWindowTitle('Statusbar')
self.vidWindow = QLabel(self)
self.vidWindow.setGeometry(20, 20, 640, 480)
self.maskWindow = QLabel(self)
self.maskWindow.setGeometry(20, 20, 640, 480)
self.maskWindow.setStyleSheet('background-color: rgba(0,0,0,0%)')
font = QFont()
font.setPointSize(18)
font.setBold(True)
font.setWeight(75)
self.maskWindow.setFont(font)
self.maskWindow.setText('Message is on the mask Qlabel object')
self.msgLabel = QLabel(self)
self.msgLabel.setGeometry(675, 300, 100, 20)
self.cap = cv2.VideoCapture(0)
self.pix = QImage()
self.timer = QTimer()
self.frame_rate = 5
self.show()
self.start()
def nextFrameSlot(self):
ret, frame = self.cap.read()
if ret == True:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img = QImage(frame,frame.shape[1], frame.shape[0], QImage.Format_RGB888)
img = img.scaled(640, 480, Qt.KeepAspectRatio)
self.pix = QPixmap.fromImage(img)
self.vidWindow.setPixmap(self.pix)
def mousePressEvent(self, QMouseEvent):
self.msgLabel.setText('Mouse Clicked!')
def paintEvent(self, QMouseEvent):
e = QMouseEvent
painter = QPainter(self)
painter.setPen(QPen(Qt.green, 4, Qt.SolidLine))
painter.drawEllipse(e.x(), e.y(), 100)
def start(self):
rate = int(1000.0 / self.frame_rate)
self.timer.setTimerType(Qt.PreciseTimer)
self.timer.timeout.connect(self.nextFrameSlot)
self.timer.start(rate)
def closeEvent(self, event):
if self.cap.isOpened():
self.cap.release()
self.vidWindow.clear()
QCoreApplication.quit()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainWindow()
sys.exit(app.exec_())
Although QPainter is used to paint a widget it will not work for this case since it paints the "MainWindow" that is below its children as the QLabels. There are at least 2 possible solutions:
Create a custom QLabel and detect the click and paint the circle,
Create a QLabel that shows a QPixmap that has the circle and move it based on the mouse information.
In this case I will implement the second method:
import sys, cv2
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel
from PyQt5.QtGui import QImage, QPixmap, QPainter, QPen, QFont
from PyQt5.QtCore import QTimer, Qt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.statusBar().showMessage("Ready")
self.setGeometry(50, 50, 800, 600)
self.setWindowTitle("Statusbar")
self.vidWindow = QLabel(self)
self.vidWindow.setGeometry(20, 20, 640, 480)
self.maskWindow = QLabel(self)
self.maskWindow.setGeometry(20, 20, 640, 480)
self.maskWindow.setStyleSheet("background-color: rgba(0,0,0,0%)")
font = QFont()
font.setPointSize(18)
font.setBold(True)
font.setWeight(75)
self.maskWindow.setFont(font)
self.maskWindow.setText("Message is on the mask Qlabel object")
self.msgLabel = QLabel(self)
self.msgLabel.setGeometry(675, 300, 100, 20)
self.marker_label = QLabel(self)
pixmap = QPixmap(100, 100)
pixmap.fill(Qt.transparent)
painter = QPainter(pixmap)
painter.setPen(QPen(Qt.green, 4, Qt.SolidLine))
painter.drawEllipse(pixmap.rect().adjusted(4, 4, -4, -4))
painter.end()
self.marker_label.setPixmap(pixmap)
self.marker_label.adjustSize()
self.marker_label.hide()
self.marker_label.raise_()
self.cap = cv2.VideoCapture(0)
self.timer = QTimer()
self.frame_rate = 5
self.show()
self.start()
def nextFrameSlot(self):
ret, frame = self.cap.read()
if ret == True:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img = QImage(frame, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
img = img.scaled(640, 480, Qt.KeepAspectRatio)
pix = QPixmap.fromImage(img)
self.vidWindow.setPixmap(pix)
def mousePressEvent(self, event):
self.msgLabel.setText("Mouse Clicked!")
if self.vidWindow.rect().contains(event.pos()):
self.marker_label.move(event.pos() - self.marker_label.rect().center())
self.marker_label.show()
super().mousePressEvent(event)
def start(self):
rate = int(1000.0 / self.frame_rate)
self.timer.setTimerType(Qt.PreciseTimer)
self.timer.timeout.connect(self.nextFrameSlot)
self.timer.start(rate)
def closeEvent(self, event):
if self.cap.isOpened():
self.cap.release()
super().closeEvent(event)
if __name__ == "__main__":
app = QApplication(sys.argv)
ex = MainWindow()
sys.exit(app.exec_())

Categories

Resources