0

I have a set of four IP cameras that stream over RTSP. I'm trying to read from all four cameras by creating four separate camera threads that continually read from the stream and then display on an OpenCV window. But so far I can read one single image and it won't display on the window. Below is the code:

import cv2
import threading


class CameraThread(threading.Thread):
    def __init__(self, address, camera_id):
        super(CameraThread, self).__init__()
        self.camid = camera_id
        self.addr  = address
        self.cap   = cv2.VideoCapture(self.addr)
        self.win   = f'Camera {self.camid}'
        cv2.namedWindow(self.win, cv2.WINDOW_NORMAL)

    def show(self, im):
        cv2.imshow(self.win, im)
        key = cv2.waitKey(1)

        if key == ord('q'):
            self.finish()

    def finish(self):
        self.cap.release()
        cv2.destroyWindow(self.win)

    def capture(self):
        if self.cap.isOpened():
            ok, im = self.cap.read()
            print('captured')

        while True:
            #cv2.imshow(self.win, im)
            ok, im = self.cap.read()
            print('capped')
            self.show(im)

            if not ok:
                break

        print('done')
        self.finish()

    def run(self):
        self.capture()


def main():
    url = 'rtsp://user:pwd@host:port/defaultPrimary-2?streamType=u'

    t0 = CameraThread(url, '0')
    t0.start()

if __name__ == '__main__':
    main()

The code is almost verbatim from this SO post.

I have tried without threading and I can get a single video to stream and display. I also thought that maybe OpenCV GUI didn't work because work because I'm updating the GUI outside of the main thread.

Does anyone know why this doesn't work and have suggestions for a better way to do this?

noel
  • 2,257
  • 3
  • 24
  • 39
  • Do you want to show the threads in 4 different windows or in one single window? I recommend separating the code used to capture the video frames and the code used to display the captured frames. – Josh Sharkey Feb 05 '20 at 05:13
  • I also noticed before the second print statement: you aren't accessing the class variabls with the `self` keyword. Shouldn't it be `self.cap.read()` ? – Josh Sharkey Feb 05 '20 at 05:16
  • @JoshSharkey that actually works. Good idea. Can you explain why in your answer perhaps? – noel Feb 05 '20 at 05:17
  • Sure, which suggestion are you referring to? – Josh Sharkey Feb 05 '20 at 05:18
  • NVM I just realized what was happening. I just never caught it because Python just let me define a new variable, because I forgot self and didn't give me any indications. – noel Feb 05 '20 at 05:22
  • So adding `self` fixed the issue? – Josh Sharkey Feb 05 '20 at 05:29
  • 1
    Almost. It enters the loop now at least, but it still won't display and imshow is blocking so I only get two images. I think it might be best to make a ring buffer and do the display stuff in the main thread. Right? – noel Feb 05 '20 at 05:32
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/207235/discussion-between-josh-sharkey-and-noel). – Josh Sharkey Feb 05 '20 at 05:36

0 Answers0