videocapture的bug
Published in:2024-06-16 |
Words: 2k | Reading time: 10min | reading:
<html lang="zh-CN">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <body class="nodata " style="">    
 
    <main style="width:100%">  
    <div class="blog-content-box"> 
        <div class="article-title-box">
            <h1 class="title-article" id="articleContentId">opencv读取摄像头不是实时的处理方法</h1>
        </div><div id="article_content" class="article_content clearfix">
    <link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/kdoc_html_views-1a98987dfd.css">
    <link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-044f2cf1dc.css">
         
            <div id="content_views" class="markdown_views prism-atom-one-dark">
                <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                    <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                </svg>
                <pre data-index="0" class="set-code-show prettyprint"><code class="prism language-python has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">cap <span class="token operator">=</span> cv2<span class="token punctuation">.</span>VideoCapture<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>

cap.read()

  • 1
  • 2

读取的不是实时的画面 ,存在延迟 怎么处理

如果你使用的是OpenCV库,你可以通过将缓冲区大小设置为更小的值来减小延迟。默认情况下,缓冲区大小是16,但可以通过在cv2.VideoCapture()中传递参数来更改。例如:

cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)

  • 1
  • 2
  • 3

这将把缓冲区大小减小到1,从而减小延迟。但是,如果你将缓冲区大小设置得太小,你可能会遇到画面卡顿或丢帧的问题。

另一种方式是使用多线程或异步处理来实现更快的画面更新。你可以在一个线程中读取摄像头的帧,并将它们传递到另一个线程或进程中进行处理和显示。这将使你能够更快地处理帧并减少延迟。但是,这需要更多的编程和计算资源,并可能会增加代码的复杂性。

下面是一个基本的多线程处理OpenCV视频帧的例子:

import cv2
import threading
class VideoCapture:
    def __init__(self, src=0):
        self.cap = cv2.VideoCapture(src)
        self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
        self.grabbed, self.frame = self.cap.read()
        self.started = False
        self.read_lock = threading.Lock()

<span class="token keyword">def</span> <span class="token function">start</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">if</span> self<span class="token punctuation">.</span>started<span class="token punctuation">:</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'VideoCapture already started'</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> <span class="token boolean">None</span>
    self<span class="token punctuation">.</span>started <span class="token operator">=</span> <span class="token boolean">True</span>
    self<span class="token punctuation">.</span>thread <span class="token operator">=</span> threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>self<span class="token punctuation">.</span>update<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    self<span class="token punctuation">.</span>thread<span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> self

<span class="token keyword">def</span> <span class="token function">update</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">while</span> self<span class="token punctuation">.</span>started<span class="token punctuation">:</span>
        grabbed<span class="token punctuation">,</span> frame <span class="token operator">=</span> self<span class="token punctuation">.</span>cap<span class="token punctuation">.</span>read<span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">with</span> self<span class="token punctuation">.</span>read_lock<span class="token punctuation">:</span>
            self<span class="token punctuation">.</span>grabbed <span class="token operator">=</span> grabbed
            self<span class="token punctuation">.</span>frame <span class="token operator">=</span> frame

<span class="token keyword">def</span> <span class="token function">read</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">with</span> self<span class="token punctuation">.</span>read_lock<span class="token punctuation">:</span>
        grabbed <span class="token operator">=</span> self<span class="token punctuation">.</span>grabbed
        frame <span class="token operator">=</span> self<span class="token punctuation">.</span>frame
    <span class="token keyword">return</span> grabbed<span class="token punctuation">,</span> frame

<span class="token keyword">def</span> <span class="token function">stop</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
    self<span class="token punctuation">.</span>started <span class="token operator">=</span> <span class="token boolean">False</span>
    self<span class="token punctuation">.</span>thread<span class="token punctuation">.</span>join<span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token keyword">def</span> <span class="token function">__exit__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> exc_type<span class="token punctuation">,</span> exc_value<span class="token punctuation">,</span> traceback<span class="token punctuation">)</span><span class="token punctuation">:</span>
    self<span class="token punctuation">.</span>cap<span class="token punctuation">.</span>release<span class="token punctuation">(</span><span class="token punctuation">)</span>

if name == main:
cap = VideoCapture(0).start()
while True:
grabbed, frame = cap.read()
if not grabbed:
break
cv2.imshow(‘frame’, frame)
if cv2.waitKey(1) & 0xFF == ord(‘q’):
break
cap.stop()
cv2.destroyAllWindows()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

这个例子使用了一个VideoCapture类,该类在一个线程中不断读取摄像头帧,并将它们保存在一个共享的grabbed和frame变量中。在主程序中,我们通过调用start()方法来启动线程,然后不断读取帧并在窗口中显示它们,直到用户按下’q’键退出。最后,我们调用stop()方法来停止线程并释放资源。

需要注意的是,这个例子仅仅是一个基本的框架,你可能需要对其进行修改和扩展以适应你的具体应用场景。例如,你可以添加一个另一个线程来处理帧,然后显示处理后的结果,以此来减少延迟。

          </main>     
   </body>
   </html>