opencv python 多线程视频捕获

Posted

技术标签:

【中文标题】opencv python 多线程视频捕获【英文标题】:opencv python Multi Threading Video Capture 【发布时间】:2013-04-03 13:03:18 【问题描述】:

我正在尝试读取 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()

发生的情况是,只有 线程 2 窗口显示线程 1 在尝试读取超出 ma​​x_retries 限制(在我的情况下为 10)的视频后退出。 问题是虽然我创建了单独的 cvVideo 对象,但我似乎无法同时使用它们。 可能是什么问题?

【问题讨论】:

只是一个基本问题,但您是否首先让视频阅读/显示代码在单个线程中工作?可以发一下吗? 哦,是的.. 单个线程运行良好。代码将完全相同。只需评论 thread2.start() 我什至在我的问题中提到“一个窗口正在显示”。 我终于在示例文件夹中找到了tree.avi。我让两个视频都可以正常运行,然后在视频结束后继续尝试阅读...您确定您的两个路径都有效吗?尝试交换文件名,看看是否显示另一个视频窗口。 我尝试了不同的视频和不同的格式。对我有用的只是示例文件夹中的 tree.avi。为什么是这样?我尝试了 .wmv 和 .mp4 格式,但多线程不起作用。有人能解释一下为什么吗? 你能链接到一些短的 wmv 或 mp4 视频文件吗?我无法挖掘 opencv 可以读取的任何内容。 【参考方案1】:

*edit:我将在下面留下代码,但我猜你有编解码器问题?我安装了 xvid 编解码器(这是对示例 Megamind.avi 进行编码的内容),并且该程序可以与运行 megamind 视频的一个或两个线程正常工作。能否让 megamind 视频在单线程版本中运行?

这里是an SO post on opencv video codecs,以防万一。这是我使用的xvid download(k-lite 不适合我)。


你写的代码基本上对我有用。对于您和其他想尝试的人,我做了以下操作:

已应用 PEP 8 建议 删除了不必要的读取尝试代码(这也删除了工作视频最后一帧后误导性线程重新读取警告) 使用了可能每个使用 opencv 的人都使用过的视频文件 删除了至少在我的系统上对 opencv 似乎无关紧要的线程锁定 移动了一些其他的小东西

VideoCapture.read 可能会出现其他错误,这会使 read_attempt 方法值得,但我只能找到 the two errors the docs mention。对于那些它只返回代码已经测试过的 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()

【讨论】:

感谢有关错误和额外代码的信息。但是,您提供的代码也不起作用。正如我在之前的 cmets 中提到的,多线程似乎只适用于示例文件夹中的 tree.avi 文件。它不适用于其他任何东西。也许这只是我系统上的一个问题,即便如此,这背后的原因是什么?可能有一些编解码器问题? 请检查我的编辑。安装编解码器后,Megamind 对我来说一切正常。 非常感谢!毕竟这是一个编解码器问题! :D 我安装了 K-lite Mega Codec 包,现在可以看到打开的窗口和播放视频。再次感谢!

以上是关于opencv python 多线程视频捕获的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV 多线程 (Windows/.NET) 从视频捕获延迟几秒钟

当我使用 rtsp 摄像头流时,opencv 视频捕获滞后

OpenCV C++ 多线程提高帧率

OpenCV 和 Python 多线程 - 在 VideoCapture 对象中搜索

使用 OpenCv 和多线程从 IP 摄像机提供实时视频

在多线程应用程序中使用 opencv waitKey()