3

2 つのビデオ ファイルを読み込んで、別々の Windows で同時に表示しようとしています。これは私のコードです:

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()

何が起こっているかというと、Thread 2 Windowだけが表示されています。スレッド 1 は、 max_retries 制限(私の場合は 10)を超えてビデオを読み取ろうとした後に終了します。問題は、別々のcvVideoオブジェクトを作成しても、それらを同時に使用できないように見えることです。何が問題なのですか?

4

1 に答える 1

3

*編集: 以下にコードを残しますが、コーデックに問題があると思いますか? xvid コーデック (サンプルの Megamind.avi がエンコードされているもの) をインストールすると、プログラムは、megamind ビデオを実行するいずれかまたは両方のスレッドで正常に動作します。メガマインドのビデオをシングル スレッド バージョンで実行することはできますか?

これが役立つ場合に備えて、opencvビデオコーデックに関するSOの投稿です。これが私が使用したxvidダウンロードです(k-liteは機能しませんでした)。


あなたが書いたコードは基本的に私にとってはうまくいきます。あなたと試してみたい他の人のために、私は次のことをしました:

  • 適用された PEP 8 勧告
  • 不要な読み取り試行コードを削除しました(これにより、作業中のビデオの最後のフレームの後に誤解を招くスレッドの再読み取り警告も削除されます)
  • おそらくopencvを持つ誰もが持っているビデオファイルを使用しました
  • 少なくとも私のシステムではopencvにとって重要ではないように思われるスレッドロックを削除しました
  • 他のいくつかの小さなものを移動しました

read_attempt メソッドを価値あるものにする VideoCapture.read で発生する他のエラーがあるかもしれませんが、ドキュメントで言及されている 2 つのエラーしか見つかりませんでした。それらについては、コードがすでにテストしている false を返すだけです。

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()
于 2013-04-03T16:31:42.150 に答える