Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Language Bindings
  4. Picamera significant delay and low FPS, but low CPU and memory usage
Forum Updated to NodeBB v4.3 + New Features

Picamera significant delay and low FPS, but low CPU and memory usage

Scheduled Pinned Locked Moved Unsolved Language Bindings
python
3 Posts 2 Posters 2.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • W Offline
    W Offline
    Walorda
    wrote on last edited by A Former User
    #1

    I am trying to integrate a camera view inside pyqt GUI, only this is running very slow with a 2-4sec delay and very low fps. So far i have used Qtimer but the speed was terrible, so i tried Qthreading as recommended by some one else but this did not improve at all. Does any one know what i am doing wrong in my code ?

    class cameraThread(QThread): 
        def __init__(self, guiobject):
            QThread.__init__(self)
            self.camera = PiCamera()
            self.guiobject = guiobject
        def __del__(self):
            self.wait()
        def run(self):
            while True:
    
                self.camera
                rawCapture = PiRGBArray(self.camera)
    
                self.camera.capture(rawCapture, format="rgb")
                image = rawCapture.array
    
    
                cvRGBImg = image
                qimg = QtGui.QImage(cvRGBImg.data, cvRGBImg.shape[1], cvRGBImg.shape[0], QtGui.QImage.Format_RGB888)
                qpm = QtGui.QPixmap.fromImage(qimg)
                self.guiobject.labelcamera.setPixmap(qpm)
    
    
    class ExampleApp(QtWidgets.QMainWindow, design.Ui_MainWindow):
        def __init__(self, parent=None):
            super(ExampleApp, self).__init__(parent)
            self.setupUi(self)
            self.button.clicked.connect(self.camerarun)
            self.threading = getPostsThread(self)
        def camerarun(self):
            self.threading.start()
    
    1 Reply Last reply
    0
    • jazzycamelJ Offline
      jazzycamelJ Offline
      jazzycamel
      wrote on last edited by
      #2

      There are a few issues I can identify with your code, the most important one is that you should not be passing a reference to the GUI object into another thread (I'm quite surprised this runs actually!), but as a result of this you may not actually be spawning a thread, which is probably why you are not seeing a performance increase.

      Also, subclassing QThread() is not the ideal or recommended way to implement threading with Qt, despite the documentation implying this. It's actually better to construct a QObject() and then move it into QThread() when ready.

      Finally, when communicating between threads (i.e. the GUI thread and the camera thread) you should not be directly referencing objects, but instead indirectly connect them via Qt's Signal/Slot mechanism which is guaranteed to be thread-safe.

      The following example (demonstrating all of the above) should do what you want and hopefully be a bit quicker:

      from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal, QThread
      from PyQt5.QtGui import QImage, QPixmap
      from PyQt5.QtWidgets import qApp, QWidget, QVBoxLayout, QPushButton, QLabel
      
      from picamera import PiCamera, PiRGBArray
      
      class Camera(QObject):
          frameCaptured=pyqtSignal(QPixmap)
      
          def __init__(self):
              super().__init__()
      
              self._looping=False
              self._camera=PiCamera()
      
          @pyqtSlot()
          def loop(self):
              self._looping=True
              while self._looping:
                  rawCapture=PiRGBArray(self._camera)
                  self._camera.capture(rawCapture, format="rgb")
                  image=rawCapture.array
                  qImage=QImage(image.data, image.shape[1], image.shape[0], QImage.Format_RGB888)
                  pixmap=QPixmap.fromImage(qImage)
                  self.frameCaptured.emit(pixmap)
      
          @pyqtSlot()
          def stop(self):
              self._looping=False
      
      class Gui(QWidget):
          def __init__(self, parent=None, **kwargs):
              super().__init__(parent, **kwargs)
      
              self._thread=QThread()
              qApp.aboutToQuit.connect(self._thread.quit)
              self._camera=Camera()
              self._camera.moveToThread(self._thread)
              self._thread.start()
      
              l=QVBoxLayout(self)
              l.addWidget(QPushButton("Start", self, clicked=self._camera.loop))
      
              self._cameraLabel=QLabel(self)
              self._camera.frameCaptured.connect(self._cameraLabel.setPixmap)
              l.addWidget(self._cameraLabel)
      
      if __name__=="__main__":
          from sys import argv, exit
          from PyQt5.QtWidgets import QApplication
      
          a=QApplication(argv)
          g=Gui()
          g.show()
          exit(a.exec_())
      

      A quick disclaimer: I don't have a Pi with a camera handy, so I can't test that bit, but the threading part definitely works with a stub for picamera.

      Hope this helps :o)

      For the avoidance of doubt:

      1. All my code samples (C++ or Python) are tested before posting
      2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
      1 Reply Last reply
      2
      • W Offline
        W Offline
        Walorda
        wrote on last edited by Walorda
        #3

        @jazzycamel said in Picamera significant delay and low FPS, but low CPU and memory usage:

        Thanks this worked i also changed the camera parameters so it runs even faster.

        self._camera=PiCamera(sensor_mode=4,resolution='640x480',framerate=40).
        

        Now the only problem is when i try to capture using the worker thread is not responding to the signal ,this is also happening with the stop function its not responding to a button click or custom emit signal to stop the camera it just keeps running

        @pyqtSlot()
        def snapshot(self):
           self._looping=False
           self._camera.capture('image.jpg')
           self._looping=True
        
        stopcamera = pyqtSignal()
        
        self._thread = QThread()
        self.stopcamera.connect(self._camera.stop)
        self._thread.start()
        
        
        
        self.CameraSnap.clicked.connect(self._camera.snapshot)
        self.CameraBack.clicked.connect(self.functionstopcamera)
        
        
        def functionstopcamera(self):
                self.stopcamera.emit()
        
        
        
        
        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved