Multiple camera feeds not working with PyQt5 threading: - python-3.x

I have a data collection software that requires camera feeds from two different camera sources one is a Brio webcam & the other one is an IP webcam connected via USB tethering.
Now when I edited the code for streaming two multiple videos it was showing just one & not from the other.
The code is given below:
import sys
import cv2
#from gsp import GstreamerPlayer
import datetime
from pyfirmata import util, Arduino
from PyQt5 import QtCore, QtGui
import openpyxl
from openpyxl import load_workbook
from PyQt5.QtCore import pyqtSlot, QThread, pyqtSignal
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QLayout, QDialog, QApplication, QMainWindow, QFileDialog, QPushButton, QWidget, QLabel
from PyQt5.uic import loadUi
import xlrd
from xlutils.copy import copy
import serial
import xlsxwriter
from xlwt import Workbook
sys.setrecursionlimit(15000)
# For the camera feed
class Thread(QThread):
changePixmap = pyqtSignal(QImage)
def run(self):
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if ret:
rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
convertToQtFormat = QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0], QImage.Format_RGB888)
p = convertToQtFormat.scaled(256, 181)
self.changePixmap.emit(p)
class Thread1(QThread):
changePixmap = pyqtSignal(QImage)
def run(self):
cap = cv2.VideoCapture('http://192.168.42.129:8080/video')
while True:
ret, frame = cap.read()
if ret:
rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
convertToQtFormat = QImage(
rgbImage.data, rgbImage.shape[1], rgbImage.shape[0], QImage.Format_RGB888)
p1 = convertToQtFormat.scaled(111, 181)
self.changePixmap.emit(p1)
The calling functions in the main are as follows:
#pyqtSlot(QImage)
def setImage(self, image):
self.webcam.setPixmap(QPixmap.fromImage(image))
#pyqtSlot(QImage)
def setImage1(self, image):
self.webcam_2.setPixmap(QPixmap.fromImage(image))
def initUI(self):
th = Thread(self)
th1 = Thread1(self)
th1.changePixmap1.connect(self.setImage1)
th.changePixmap.connect(self.setImage)
th.start()
I am new to python programming can anyone tell me what I am doing wrong here? I tried the other approach of doing the streaming in a function & setting streams up but this was not a conventional approach as my application kept crashing due to the while loop*( I guess)*.
If I use one source at a time it works but I can't seem to get them working at a time.

I got it worked around as I wasn't adding
thread.start()
function before.

Related

How can I access images from qrc.py into reportlab?

I have converted "image_fonts.qrc" into image_fonts_rc.py file. It has one image named as "image.png"
How can I use an image into reportlab PDF in Python from qrc.py file.
File image_fonts.qrc
<RCC>
<qresource prefix="image_fonts">
<file>image.png</file>
<file>logo.png</file>
</qresource>
</RCC>
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/image_fonts/logo.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
I used above the lines, but I get an error. Please find the below error.
TypeError: expected str, bytes or os.PathLike object, not QIcon
Minimal Example:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtSql import *
from PyQt5 import uic
import sys
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, PageTemplate, TableStyle, Paragraph, Image, Spacer, Frame, Paragraph, Flowable
import image_fonts_rc
class UI(QMainWindow):
def __init__(self):
super(UI, self).__init__()
uic.loadUi("test_images.ui", self)
self.show()
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/image_fonts/logo.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
doc = SimpleDocTemplate("images.pdf", pagesize=A4, rightMargin=40, leftMargin=40, topMargin=20, bottomMargin=20, title ="Images")
width, height = A4
document = []
logo = icon
imgw = imgh = 80
im = (Image(logo, width=imgw, height=imgh))
document.append(im)
doc.build(document)
app = QApplication(sys.argv)
window = UI()
app.exec_()
It is not necessary to use QPixmap or QIcon but you must get the bytes from the image as in my previous answer:
from io import BytesIO
from PyQt5 import QtCore
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Image
import image_fonts_rc
def convert_qrc_to_bytesio(filename):
file = QtCore.QFile(filename)
if not file.open(QtCore.QIODevice.ReadOnly):
raise RuntimeError(file.errorString())
return
f = BytesIO(file.readAll().data())
return f
doc = SimpleDocTemplate(
"images.pdf",
pagesize=A4,
rightMargin=40,
leftMargin=40,
topMargin=20,
bottomMargin=20,
title="Images",
)
width, height = A4
document = []
logo = convert_qrc_to_bytesio(":/image_fonts/logo.png")
imgw = imgh = 80
im = Image(logo, width=imgw, height=imgh)
document.append(im)
doc.build(document)

real-time plotting to a TK window using python3

I am trying to plot in real-time to a tkinter window in python3.
I am attempting to wrap my window in a class.
my code shows the graph, but data is not being plotted. Here is the code:
#! /usr/bin/python3
# -*- coding: utf-8 -*-
import sys
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib.animation as animation
import tkinter
import time
import numpy as np
matplotlib.use("TkAgg")
class Window(tkinter.Frame):
def __init__(self, master = None):
tkinter.Frame.__init__(self, master)
self.master = master
self.master.grid()
self.fig = Figure(figsize=(5,5), dpi=100)
self.ax = self.fig.add_subplot(111)
self.t, self.y = [], []
self.init_window()
self.ani = animation.FuncAnimation(self.fig, self.animate, interval=1000)
def init_window(self):
# set window title
self.master.title("PlotSomething")
# run show_graph
self.show_graph()
def animate(self):
self.t.append(time.time())
self.y.append(np.random.random())
self.ax.clear()
self.ax.plot(self.t,self.y)
def show_graph(self):
canvas = FigureCanvasTkAgg(self.fig, self.master)
canvas.get_tk_widget().grid(row=1, column=1)
canvas.draw()
def client_exit(self):
sys.exit()
def main(args):
root = tkinter.Tk()
app = Window(root)
root.mainloop()
return 0
if __name__=="__main__":
sys.exit(main(sys.argv[1:]))
Please let me know what the issue is.
Bonus if you can help me get the real-time plot stuff into a separate class that I can call with my tkinter window.
I obviously need some learning on how to create and call classes using tkinter.
As always thank you for your support!

pyqt5 video widget and table widget side by side

I want to have a table widget side by side to a video widget and a webview widget. The video and webview widget to be stacked vertically.
I tried to first have table widget and video widget side by side but the video widget is being hidden by the table widget. I'm able to hear audio so the video seems to be running but just doesn't seem to be displaying the video part.
What is wrong in the code?
Pasting the sample code. I'm yet to add the web widget.
import sys
from PyQt5 import QtGui, QtCore
from PyQt5.QtCore import QDir, Qt, QUrl
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import (QMainWindow, QApplication, QWidget, QTableWidget,QVBoxLayout,
QTableWidgetItem, QLabel, QHBoxLayout,QGridLayout)
class Window(QWidget):
def __init__(self,):
super().__init__()
table1 = QTableWidget()
table1.setRowCount(2)
table1.setColumnCount(2)
table1.setItem(0,0, QTableWidgetItem("Cell (1,1)"))
table1.setItem(0,1, QTableWidgetItem("Cell (1,2)"))
table1.setItem(1,0, QTableWidgetItem("Cell (2,1)"))
table1.setItem(1,1, QTableWidgetItem("Cell (2,2)"))
self.VideoWidget = QVideoWidget()
self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
self.player.setMedia(QMediaContent(QUrl.fromLocalFile("test.mp4")))
self.player.play()
self.player.setVideoOutput(self.VideoWidget)
self.layout = QHBoxLayout()
self.layout.addWidget(table1)
self.layout.addWidget(self.VideoWidget)
self.setLayout(self.layout)
self.move(0,0)
self.resize(320, 240)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
app.exec_()
I was able to solve the problem by using QSplitter.
The code is as below:
import sys
from PyQt5 import QtGui, QtCore
from PyQt5.QtCore import QDir, Qt, QUrl
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import (QMainWindow, QApplication, QWidget, QTableWidget,QVBoxLayout,
QTableWidgetItem, QHBoxLayout,QSplitter,QGroupBox)
from PyQt5.QtWebKit import *
from PyQt5.QtWebKitWidgets import *
class Window(QWidget):
def __init__(self,):
super().__init__()
self.v_layout = QVBoxLayout(self)
self.splitter = QSplitter(QtCore.Qt.Horizontal)
self.left = QGroupBox('Left')
self.table1 = QTableWidget()
self.table1.setRowCount(2)
self.table1.setColumnCount(2)
self.table1.setItem(0,0, QTableWidgetItem("Cell (1,1)"))
self.table1.setItem(0,1, QTableWidgetItem("Cell (1,2)"))
self.table1.setItem(1,0, QTableWidgetItem("Cell (2,1)"))
self.table1.setItem(1,1, QTableWidgetItem("Cell (2,2)"))
self.left_layout = QVBoxLayout(self.left)
self.left_layout.addWidget(self.table1)
self.right = QGroupBox('Right')
self.VideoWidget = QVideoWidget()
self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
self.player.setMedia(QMediaContent(QUrl.fromLocalFile("test.mp4")))
self.player.play()
self.player.setVideoOutput(self.VideoWidget)
self.webview = QWebView()
url = "https://www.google.com"
self.webview.load(QUrl(url))
self.right_layout = QVBoxLayout(self.right)
self.right_layout.addWidget(self.webview)
self.right_layout.addWidget(self.VideoWidget)
self.splitter.addWidget(self.left)
self.splitter.addWidget(self.right)
self.v_layout.addWidget(self.splitter)
self.resize(840,680)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
app.exec_()

Reading frames from a folder and display in QGraphicsView in pyqt4

I am trying to read frame for a folder and display in QGraphics view.
import os
import PyQt4
from PyQt4 import QtCore, QtGui
dir = "frames"
for file in os.listdir(dir):
grview = QtGui.QGraphicsView()
scene = QtGui.QGraphicsScene()
#pixmap = QtGui.QPixmap(os.path.join(dir, file))
pixmap = QtGui.QPixmap(file)
item = QtGui.QGraphicsPixmapItem(pixmap)
self.scene.addItem(item)
grview.setScene()
grview.show()
#self.scene.update()
The folder named "frames" contains jpg files and is in the same folder as the code. But still I am not able to read the frames.
I have also tried general display without graphicsview to check if it works using the code below but it too doesn't work.
import cv2
import os
import PyQt4
from PyQt4 import QtGui,QtCore
import matplotlib.pyplot as plt
from PIL import Image
def load_images_from_folder(folder):
images = []
for filename in os.listdir(folder):
img = cv2.imread(os.path.join(folder,filename))
if img is not None:
images.append(img)
return images
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
img = load_images_from_folder('/frames')
image = Image.open(img)
image.show()
I am not able to understand what am I missing. I want to display the images sequentially in QGraphicsView resembling a video and in some particular frame I have to select the object of interest by draw a rectangle around it which has to hold in the subsequent frames as well. Is the task i am attempting possible? if yes any help is appreciated
Sorry, but I have PyQt5.
Try it:
import os
import sys
from PyQt5 import Qt
#from PyQt4 import QtCore, QtGui
class MainWindow(Qt.QMainWindow):
def __init__(self, parent=None):
Qt.QMainWindow.__init__(self, parent)
self.scene = Qt.QGraphicsScene()
self.grview = Qt.QGraphicsView(self.scene)
self.setCentralWidget(self.grview)
dir = "frames"
self.listFiles = os.listdir(dir)
self.timer = Qt.QTimer(self)
self.n = 0
self.timer.timeout.connect(self.on_timeout)
self.timer.start(1000)
self.setGeometry(700, 150, 300, 300)
self.show()
def on_timeout(self):
if self.n < len(self.listFiles):
self.scene.clear()
file = self.listFiles[self.n]
pixmap = Qt.QPixmap("frames\{}".format(file)) # !!! "frames\{}"
item = Qt.QGraphicsPixmapItem(pixmap)
self.scene.addItem(item)
self.grview.setScene(self.scene) # !!! (self.scene)
self.n += 1
else:
self.timer.stop()
app = Qt.QApplication(sys.argv)
GUI = MainWindow()
sys.exit(app.exec_())

mplot3d Dynamic Update with PyQt Designer

I'm trying to create a simple GUI that has an embedded mplot3d widget for viewing STL files. I'm currently using PyQt4 with Qt Designer for creating the layout and python 3.6.2. I've used this post as a starting point and I have been able to successfully implement a custom mplot3d widget. However, I would like to be able to dynamically update the mplot3d widget (eg. Click a button to load a new stl file and update the figure/widget). I know this is possible for 2D matplotlib figures using
manager = matplotlib.get_current_fig_manager()
manager.canvas.draw()
to update a regular matplotlib figure. But is this possible for an embedded matplotlib widget? Or a mplot3d custom widget?
Should I write I new method in the QtMplCanvas(FigureCanvas) class? I can't seem to figure out from the
FigureCanvasQTAgg
docs how to update a widget from matplotlibs backend. My code is somewhat long but I'll try to include the relevant bits:
from PyQt4 import QtCore, QtGui
import os
import sys
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4 import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
from mpl_toolkits.mplot3d import Axes3D
from stl import mesh
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
plt.switch_backend('Qt4Agg')
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(1007, 607)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.gridLayout = QtGui.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.line = QtGui.QFrame(self.centralwidget)
self.line.setFrameShape(QtGui.QFrame.VLine)
self.line.setFrameShadow(QtGui.QFrame.Sunken)
self.line.setObjectName(_fromUtf8("line"))
self.gridLayout.addWidget(self.line, 2, 1, 1, 1)
# STL VIEWER
self.graphicsView_STL = MPL_WIDGET_3D(self.centralwidget)
self.graphicsView_STL.setObjectName(_fromUtf8("graphicsView_STL"))
self.gridLayout.addWidget(self.graphicsView_STL, 2, 0, 1, 1)
# File load btn
self.import_tlbtn = QtGui.QToolButton(self.centralwidget)
self.import_tlbtn.setObjectName(_fromUtf8("import_tlbtn"))
self.gridLayout.addWidget(self.import_tlbtn, 1, 0, 1, 1)
#... More Widgets, layouts, etc.
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.import_tlbtn.setText(_translate("MainWindow", "...", None))
self.label_slice.setText(_translate("MainWindow", "Slice", None))
self.label_import.setText(_translate("MainWindow", "Import STL File", None))
... Code from Link
.... New file for connecting methods..
from PyQt4 import QtCore, QtGui
import UI_DED
import sys
import os
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
from stl import mesh
''' CONNECTING METHODS HERE '''
def open_file():
# Open a new file selection window
widget_f = QtGui.QWidget()
widget_f.resize(320, 240)
widget_f.setWindowTitle("Select a file")
filename = QtGui.QFileDialog.getOpenFileName(widget_f, 'Open File', '/')
if filename == '':
pass
else:
your_mesh = mesh.Mesh.from_file(filename)
stl_update(your_mesh)
# Some sort of method for updating the widget
def stl_update():
pass
# Some method for updating canvas....
if __name__ == "__main__":
plt.switch_backend('Qt4Agg')
# Set window from UI_DED
app = QtGui.QApplication(sys.argv)
MainWindow = UI_DED.QtGui.QMainWindow()
ui = UI_DED.Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
# Connect widgets here
# Import STL File
ui.import_tlbtn.clicked.connect(open_file)
# Exit
sys.exit(app.exec_())

Resources