3

I am trying to read to 2 Video Files and show them in separate Windows Simultaneously. This is my code:

import threading
import cv2
threadLock=threading.Lock()
class myThread (threading.Thread):
    maxRetries=20
    def __init__(self, threadID, name,video_url):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.video_url=video_url

    def attemptRead(self,cvVideo):
        threadLock.acquire()
        (isRead,cvImage)=cvVideo.read()
        threadLock.release()
        if isRead==False:
            count=1
            while isRead==False and count<myThread.maxRetries:
                threadLock.acquire()
                (isRead,cvImage)=cvVideo.read()
                threadLock.release()
                print self.name+' try no: ',count
                count+=1
        return (isRead,cvImage)

    def run(self):
        print "Starting " + self.name
        windowName = self.name
        cv2.namedWindow(windowName)
        cvVideo = cv2.VideoCapture(self.video_url)


        while True:
            (isRead,cvImage)=self.attemptRead(cvVideo)
            if isRead==False:
                break
            cv2.imshow(windowName,cvImage)
            key=cv2.waitKey(50)
            if key==27:
                break

        cv2.destroyWindow(windowName)
        print self.name + "Exiting"

def main():
    thread1 = myThread(1, "Thread1",'C:/Traffic Pics/Videos/Panjim Capture.mp4')
    thread2 = myThread(2, "Thread2",'C:/Traffic Pics/Videos/Miramar Capture.mp4')

    thread1.start()
    thread2.start()

print "Exiting Main Thread"

if __name__ == '__main__':
    main()

What's happening is that, only the Thread 2 Window is showing. Thread 1 exits after attempting to read the video beyond the max_retries limit(10 in my case). The problem is that although I create separate cvVideo objects, I can't seem to use them simultaneously. What could be the problem?

Colenso Castellino
  • 900
  • 2
  • 13
  • 23
  • Just a basic question, but did you get the video reading/display code working in a single thread first? Could you post that? – KobeJohn Apr 03 '13 at 15:01
  • Ooh yes.. A single thread is running fine. The code will be exactly the same. Just comment the **thread2.start()** I have even mentioned it in my question that "One Window is showing". – Colenso Castellino Apr 03 '13 at 15:24
  • 1
    I finally found `tree.avi` in the sample folder. I get both videos running with no problem and then it keeps attempting to read after the video finishes... Are you sure both of your paths are valid? Try swapping the file names and see if the other video window shows up instead. – KobeJohn Apr 03 '13 at 15:33
  • I've experimented with different Videos and different formats. What worked for me is only the **tree.avi** in the samples folder. Why is this? I tried with .wmv and .mp4 formats and the Multi-threading does not work. Can someone explain why? – Colenso Castellino Apr 03 '13 at 16:40
  • Can you link to some short wmv or mp4 video files that work? I'm having trouble digging anything up that opencv can read. – KobeJohn Apr 03 '13 at 16:51
  • There's a Megamind.avi in the samples folder which does not work either. Here's a link to it in the .git repository: https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/HighGUI/video-input-psnr-ssim/video – Colenso Castellino Apr 03 '13 at 17:03

1 Answers1

4

*edit: I'll leave the code below, but I guess you have a codec problem? I installed the xvid codec (which is what the sample Megamind.avi is encoded with) and the program works fine with either or both threads running the megamind video. Can you get the megamind video to run in the single threaded version?

Here is an SO post on opencv video codecs in case it helps. Here is the xvid download that I used (k-lite didn't work for me).


The code you wrote basically works for me. For you and anyone else that wants to try, I did the following:

  • applied PEP 8 recommendations
  • removed the unnecessary read attempt code (which also removes the misleading thread re-read warnings after the last frame of a working video)
  • used a video file that perhaps everyone with opencv has
  • removed the thread locking which didn't seem to matter to opencv at least on my system
  • moved a few other little things around

There may be other errors that come up with VideoCapture.read that would make a read_attempt method worthwhile, but I could only find the two errors the docs mention. For those it just returns false which the code already tests for.

import os
import threading

import cv2

my_opencv_path = "C:/opencv2.4.3"
video_path_1 = os.path.join(my_opencv_path, "samples", "cpp", "tutorial_code",
                            "HighGUI", "video-input-psnr-ssim", "video",
                            "Megamind.avi")
video_path_2 = os.path.join(my_opencv_path, "samples", "c", "tree.avi")
assert os.path.isfile(video_path_1)
assert os.path.isfile(video_path_2)


class MyThread (threading.Thread):
    maxRetries = 20

    def __init__(self, thread_id, name, video_url, thread_lock):
        threading.Thread.__init__(self)
        self.thread_id = thread_id
        self.name = name
        self.video_url = video_url
        self.thread_lock = thread_lock

    def run(self):
        print "Starting " + self.name
        window_name = self.name
        cv2.namedWindow(window_name)
        video = cv2.VideoCapture(self.video_url)
        while True:
            # self.thread_lock.acquire()  # These didn't seem necessary
            got_a_frame, image = video.read()
            # self.thread_lock.release()
            if not got_a_frame:  # error on video source or last frame finished
                break
            cv2.imshow(window_name, image)
            key = cv2.waitKey(50)
            if key == 27:
                break
        cv2.destroyWindow(window_name)
        print self.name + " Exiting"


def main():
    thread_lock = threading.Lock()
    thread1 = MyThread(1, "Thread 1", video_path_1, thread_lock)
    thread2 = MyThread(2, "Thread 2", video_path_2, thread_lock)
    thread1.start()
    thread2.start()
    print "Exiting Main Thread"

if __name__ == '__main__':
    main()
Community
  • 1
  • 1
KobeJohn
  • 7,390
  • 6
  • 41
  • 62
  • Thanks for the information about the errors and the extra code. However, the code you provided doesn't work either. As I mentioned in my earlier comments, Multi-threading only seems to work with the **tree.avi** file in the samples folder. It doesn't work for anything else. Maybe this is just an issue on my system, even so, what could be the reason behind this? Some Codec issues maybe? – Colenso Castellino Apr 03 '13 at 16:51
  • Please check my edit. After installing the codec, everything is fine with Megamind for me. – KobeJohn Apr 03 '13 at 18:35
  • Thank you very much! It was a codec problem after all! :D I installed K-lite Mega Codec pack and can now see both the windows opening and playing the videos. Thanks again! – Colenso Castellino Apr 04 '13 at 04:35