Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Thread / OpenCV Segmentation Fault
Forum Update on Monday, May 27th 2025

Thread / OpenCV Segmentation Fault

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 4 Posters 900 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.
  • L Offline
    L Offline
    LS-KS
    wrote on 23 May 2023, 07:34 last edited by
    #1

    Hello folks,
    I'm trying to visualize some image processing using cv2.
    In general the following code works as intended and I would have started to implement my processing Code. But unfortunately sometimes I get segmentation faults if I repeatedly stop/start the VideoThread.

    I use qml to Image Item with QuickImageProvider to visualize the video feed.

    Interestingly I get console output from receiving signals in my qml file when the VideoThreads quit() method is already called.

    Can anyone help? Google couldn't

    import sys
    import cv2
    from PySide6.QtGui import QImage
    from PySide6.QtCore import Signal, Slot, Qt, QThread
    from PySide6.QtQuick import QQuickImageProvider
    from PySide6.QtQml import QQmlImageProviderBase
    
    
    class VideoThread(QThread):
        frameChanged = Signal(QImage)
    
        def __init__(self, parent=None):
            QThread.__init__(self, parent)
            self.capture = cv2.VideoCapture(0)
            self.capture.set(cv2.CAP_PROP_FPS, 30)
            self.running = True
            self.detecting = False
            # initialize haar cascade face detection
            self.faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
            print("VideoThread initialization finished")
    
        def run(self):
    
            while self.running:
                print("getframe...")
                ret, frame = self.capture.read()
                if ret:
                    if self.detecting:
                        # Convert the frame to grayscale
                        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                        # Detect faces in the frame
                        faces = self.faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)
                        # Draw rectangles around the faces
                        for (x, y, w, h) in faces:
                            cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
                    rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                    h, w, _ = rgbImage.shape
                    qImage = QImage(rgbImage.data, w, h, QImage.Format_RGB888)
                    self.frameChanged.emit(qImage)
                    print("...emitted frame")
    
        def quit(self):
            print("try closing")
            self.running = False
            self.capture.release()
            super().quit()
            super().wait()
            self.deleteLater()
            print("closed")
    
        def start(self):
            print("VideoThread: start")
            self.running = True
            super().start()
            print("VideoThread: started")
    
        def detect(self):
            self.detecting = not self.detecting
    
    
    class VideoPlayer(QQuickImageProvider):
        imageChanged = Signal(QImage)
    
        def __init__(self):
            super().__init__(QQmlImageProviderBase.Image, QQmlImageProviderBase.ForceAsynchronousImageLoading)
            self.videoThread = None
            self.image = None
    
        def requestImage(self, id, size, requestedSize):
            if self.image:
                img = self.image
            else:
                img = QImage(1280, 720, QImage.Format_RGBA8888)
                img.fill(Qt.black)
            return img
    
        @Slot(QImage)
        def updateImage(self, frame):
            print("new image in updateImage")
            self.image = frame
            self.imageChanged.emit(frame)
    
        @Slot()
        def start(self):
            print("Starting Video feed...")
            if not self.videoThread:
                self.videoThread = VideoThread()
                self.videoThread.frameChanged.connect(self.updateImage)
            self.videoThread.running = True
            self.videoThread.start()
    
        @Slot()
        def stop(self):
            print("Finishing Video feed.")
            if self.videoThread:
                self.videoThread.quit()
                # self.videoThread.deleteLater()
                self.videoThread = None
                print("Finished Video feed.")
    
        @Slot()
        def toggleDetection(self):
            self.videoThread.detect()
    
    
    C 1 Reply Last reply 23 May 2023, 16:50
    0
    • L LS-KS
      23 May 2023, 07:34

      Hello folks,
      I'm trying to visualize some image processing using cv2.
      In general the following code works as intended and I would have started to implement my processing Code. But unfortunately sometimes I get segmentation faults if I repeatedly stop/start the VideoThread.

      I use qml to Image Item with QuickImageProvider to visualize the video feed.

      Interestingly I get console output from receiving signals in my qml file when the VideoThreads quit() method is already called.

      Can anyone help? Google couldn't

      import sys
      import cv2
      from PySide6.QtGui import QImage
      from PySide6.QtCore import Signal, Slot, Qt, QThread
      from PySide6.QtQuick import QQuickImageProvider
      from PySide6.QtQml import QQmlImageProviderBase
      
      
      class VideoThread(QThread):
          frameChanged = Signal(QImage)
      
          def __init__(self, parent=None):
              QThread.__init__(self, parent)
              self.capture = cv2.VideoCapture(0)
              self.capture.set(cv2.CAP_PROP_FPS, 30)
              self.running = True
              self.detecting = False
              # initialize haar cascade face detection
              self.faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
              print("VideoThread initialization finished")
      
          def run(self):
      
              while self.running:
                  print("getframe...")
                  ret, frame = self.capture.read()
                  if ret:
                      if self.detecting:
                          # Convert the frame to grayscale
                          gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                          # Detect faces in the frame
                          faces = self.faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)
                          # Draw rectangles around the faces
                          for (x, y, w, h) in faces:
                              cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
                      rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                      h, w, _ = rgbImage.shape
                      qImage = QImage(rgbImage.data, w, h, QImage.Format_RGB888)
                      self.frameChanged.emit(qImage)
                      print("...emitted frame")
      
          def quit(self):
              print("try closing")
              self.running = False
              self.capture.release()
              super().quit()
              super().wait()
              self.deleteLater()
              print("closed")
      
          def start(self):
              print("VideoThread: start")
              self.running = True
              super().start()
              print("VideoThread: started")
      
          def detect(self):
              self.detecting = not self.detecting
      
      
      class VideoPlayer(QQuickImageProvider):
          imageChanged = Signal(QImage)
      
          def __init__(self):
              super().__init__(QQmlImageProviderBase.Image, QQmlImageProviderBase.ForceAsynchronousImageLoading)
              self.videoThread = None
              self.image = None
      
          def requestImage(self, id, size, requestedSize):
              if self.image:
                  img = self.image
              else:
                  img = QImage(1280, 720, QImage.Format_RGBA8888)
                  img.fill(Qt.black)
              return img
      
          @Slot(QImage)
          def updateImage(self, frame):
              print("new image in updateImage")
              self.image = frame
              self.imageChanged.emit(frame)
      
          @Slot()
          def start(self):
              print("Starting Video feed...")
              if not self.videoThread:
                  self.videoThread = VideoThread()
                  self.videoThread.frameChanged.connect(self.updateImage)
              self.videoThread.running = True
              self.videoThread.start()
      
          @Slot()
          def stop(self):
              print("Finishing Video feed.")
              if self.videoThread:
                  self.videoThread.quit()
                  # self.videoThread.deleteLater()
                  self.videoThread = None
                  print("Finished Video feed.")
      
          @Slot()
          def toggleDetection(self):
              self.videoThread.detect()
      
      
      C Offline
      C Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on 23 May 2023, 16:50 last edited by
      #2

      @LS-KS said in Thread / OpenCV Segmentation Fault:

      qImage = QImage(rgbImage.data, w, h, QImage.Format_RGB888)

      Default problem when using this QImage ctor and not reading the docs I would guess: "The buffer must remain valid throughout the life of the QImage and all copies that have not been modified or otherwise detached from the original buffer"

      Make a deep copy of the image.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      SGaistS 1 Reply Last reply 23 May 2023, 18:55
      3
      • C Christian Ehrlicher
        23 May 2023, 16:50

        @LS-KS said in Thread / OpenCV Segmentation Fault:

        qImage = QImage(rgbImage.data, w, h, QImage.Format_RGB888)

        Default problem when using this QImage ctor and not reading the docs I would guess: "The buffer must remain valid throughout the life of the QImage and all copies that have not been modified or otherwise detached from the original buffer"

        Make a deep copy of the image.

        SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on 23 May 2023, 18:55 last edited by
        #3

        Hi,

        Your thread stopping looks wrong. You change running to false and immediately nuke your capture while in fact, the run function might still be doing something. The deallocation should rather happen as cleanup at the end of the run method.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        L 1 Reply Last reply 24 May 2023, 06:50
        1
        • SGaistS SGaist
          23 May 2023, 18:55

          Hi,

          Your thread stopping looks wrong. You change running to false and immediately nuke your capture while in fact, the run function might still be doing something. The deallocation should rather happen as cleanup at the end of the run method.

          L Offline
          L Offline
          LS-KS
          wrote on 24 May 2023, 06:50 last edited by
          #4

          @Christian-Ehrlicher ,
          Thank you for your replys.
          I moved the super().wait() just one line up. And it now never crushes.
          But somehow this way it feels wrong?!?

          I think i will have time to read the docs today.

          @SGaist : what do you mean by 'clean up at the end of the run function'?

          JonBJ 1 Reply Last reply 24 May 2023, 07:18
          0
          • L LS-KS
            24 May 2023, 06:50

            @Christian-Ehrlicher ,
            Thank you for your replys.
            I moved the super().wait() just one line up. And it now never crushes.
            But somehow this way it feels wrong?!?

            I think i will have time to read the docs today.

            @SGaist : what do you mean by 'clean up at the end of the run function'?

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on 24 May 2023, 07:18 last edited by JonB
            #5

            @LS-KS said in Thread / OpenCV Segmentation Fault:

            I moved the super().wait() just one line up. And it now never crushes.

            @SGaist : what do you mean by 'clean up at the end of the run function'?

            I have not analyzed all your code, but I think from your def quit(self) you should move at least the lines

            self.capture.release()
            self.deleteLater()
            

            out and put them as the last lines in def run(self) after the while self.running loop.

            L 1 Reply Last reply 24 May 2023, 08:55
            0
            • JonBJ JonB
              24 May 2023, 07:18

              @LS-KS said in Thread / OpenCV Segmentation Fault:

              I moved the super().wait() just one line up. And it now never crushes.

              @SGaist : what do you mean by 'clean up at the end of the run function'?

              I have not analyzed all your code, but I think from your def quit(self) you should move at least the lines

              self.capture.release()
              self.deleteLater()
              

              out and put them as the last lines in def run(self) after the while self.running loop.

              L Offline
              L Offline
              LS-KS
              wrote on 24 May 2023, 08:55 last edited by
              #6

              @JonB

              Thank you for your reply.

              self.deleteLater()
              

              terminates the whole thread and must stay in the quit() method.

              But moving

              self.capture.release()
              

              into run() method was the solution!

              1 Reply Last reply
              0
              • L LS-KS has marked this topic as solved on 24 May 2023, 08:55

              1/6

              23 May 2023, 07:34

              • Login

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