<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[IMX 287 opencv python多线程多相机硬触发帧率下降]]></title><description><![CDATA[<p dir="auto">如题，通过v4l2设置帧率为最大之后，单线程多相机的帧率与外部硬触发频率基本一致，但是波动比较大。然后使用如下代码进行多线程多相机采集，帧率远低于外部硬触发频率。</p>
<pre><code>import cv2
import argparse
import subprocess
import time
import numpy as np

import numpy as np
import cv2
import threading
from copy import deepcopy

thread_lock = threading.Lock()
thread_exit = False

class VideoThread(threading.Thread):
    def __init__(self, camera_id, img_height, img_width):
        super(VideoThread, self).__init__()
        self.camera_id = camera_id
        self.img_height = img_height
        self.img_width = img_width
        self.frame = np.zeros((img_height, img_width, 3), dtype=np.uint8)

    def get_frame(self):
        return deepcopy(self.frame)

    def run(self):
        global thread_exit
        cap = cv2.VideoCapture(self.camera_id)
        cap.set(cv2.CAP_PROP_FRAME_WIDTH, self.img_width)
        cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self.img_height)
        frame_num = 0
        timestampes = []
        while not thread_exit:
            ret, frame = cap.read()
            if ret:
                #thread_lock.acquire()
                self.frame = frame
                if frame_num == 0:
                    time_start = time.perf_counter()
                frame_num = frame_num + 1
                #thread_lock.release()
                print('get' + self.camera_id[-6:] + f'frame {frame_num}')
            else:
                thread_exit = True
            time_end = time.perf_counter()
            time_ms = (time_end - time_start)*1000
            timestampes.append(time_ms)
            if frame_num &gt;= 3000:
                thread_exit = True
                timestampes = np.array(timestampes)
                np.save(self.camera_id[-6:] + '.npy', timestampes)
        cap.release()


def main():
    # Set up command-line argument parser
    parser = argparse.ArgumentParser(description='Real-time display of GREY image from mv-cam')
    parser.add_argument('--roix', type=int, default=0, help='roi start x (default: 0)')
    parser.add_argument('--roiy', type=int, default=0, help='roi start y (default: 0)')
    parser.add_argument('--width', type=int, default=704, help='image width (default: 640)')
    parser.add_argument('--height', type=int, default=544, help='image height (default: 480)')
    parser.add_argument('--fps', type=int, default=320, help='frame rate (default: 30)')
    parser.add_argument('--pixelformat', type=int, default=12, help='pixel format (default: 12)')

    args = parser.parse_args()
    
    v4l2_cmd = f"v4l2-ctl --set-ctrl roi_x={args.roix}"
    subprocess.run(v4l2_cmd, shell=True)
    
    v4l2_cmd = f"v4l2-ctl --set-ctrl roi_y={args.roiy}"
    subprocess.run(v4l2_cmd, shell=True)
    
    v4l2_cmd = f"v4l2-ctl --set-fmt-video=width={args.width},height={args.height}"
    subprocess.run(v4l2_cmd, shell=True)
    
    v4l2_cmd = f"v4l2-ctl --set-ctrl frame_rate={args.fps}"
    subprocess.run(v4l2_cmd, shell=True)

    v4l2_cmd = "v4l2-ctl --set-ctrl low_latency_mode=1"
    subprocess.run(v4l2_cmd, shell=True)

    v4l2_cmd = f"v4l2-ctl --set-ctrl pixelformat=XY{args.pixelformat}"
    subprocess.run(v4l2_cmd, shell=True)

    #v4l2_cmd = "v4l2-ctl --set-ctrl exposure_auto=1"
    #subprocess.run(v4l2_cmd, shell=True)

    #v4l2_cmd = "v4l2-ctl --set-ctrl exposure_absulute=20"
    #subprocess.run(v4l2_cmd, shell=True)

    v4l2_cmd = "v4l2-ctl --set-ctrl trigger_mode=1"
    subprocess.run(v4l2_cmd, shell=True)

    v4l2_cmd = "v4l2-ctl --set-ctrl trigger_src=1"
    subprocess.run(v4l2_cmd, shell=True)

    v4l2_cmd = "v4l2-ctl --set-ctrl vi_time_out_disable=1"
    subprocess.run(v4l2_cmd, shell=True)


    global thread_exit
    img_height = args.height
    img_width = args.width

    thread_0 = VideoThread('/dev/video0', img_height, img_width)
    thread_1 = VideoThread('/dev/video1', img_height, img_width)
    thread_0.start()
    thread_1.start()
    #frame_num = 0
    while not thread_exit:
        #thread_lock.acquire()
        #frame_0 = thread_0.get_frame()
        #print(f'get cam0 {frame_num}')
        #frame_1 = thread_1.get_frame()
        #print(f'get cam1 {frame_num}')
        #thread_lock.release()
        #thread_0.join()
        #thread_1.join()
        #frame_num = frame_num + 1
        #if frame_num &gt;= 3000:
            #thread_exit = True
        pass
    print('done!')
    # Release resources
    v4l2_cmd = "v4l2-ctl --set-ctrl vi_time_out_disable=0"
    subprocess.run(v4l2_cmd, shell=True)

if __name__ == '__main__':
    main()
</code></pre>
]]></description><link>http://forum.veye.cc/topic/613/imx-287-opencv-python多线程多相机硬触发帧率下降</link><generator>RSS for Node</generator><lastBuildDate>Mon, 17 Aug 2026 20:03:37 GMT</lastBuildDate><atom:link href="http://forum.veye.cc/topic/613.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 20 Jun 2024 08:15:38 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to IMX 287 opencv python多线程多相机硬触发帧率下降 on Wed, 26 Jun 2024 09:32:02 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/etherealhorizon" aria-label="Profile: etherealhorizon">@<bdi>etherealhorizon</bdi></a></p>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/etherealhorizon" aria-label="Profile: etherealhorizon">@<bdi>etherealhorizon</bdi></a> said in <a href="/post/4264">IMX 287 opencv python多线程多相机硬触发帧率下降</a>:</p>
<blockquote>
<p dir="auto">最后是用python多进程为每个相机分别subprocess运行v4l2-ctl命令行然后读取--stream-mmap --verbose的时间戳</p>
</blockquote>
<p dir="auto">这个时间戳不够准确，如果你的算法对事件准确性要求不高，也可以先这样用。</p>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/etherealhorizon" aria-label="Profile: etherealhorizon">@<bdi>etherealhorizon</bdi></a> said in <a href="/post/4264">IMX 287 opencv python多线程多相机硬触发帧率下降</a>:</p>
<blockquote>
<p dir="auto">还想请教一下怎么做real time binning，就是实时地将2x2或者4x4的像素值求和再保存，我们的c水平比较烂哈哈。</p>
</blockquote>
<p dir="auto">这个我们也缺乏实际经验。不好意思。</p>
]]></description><link>http://forum.veye.cc/post/4265</link><guid isPermaLink="true">http://forum.veye.cc/post/4265</guid><dc:creator><![CDATA[veye_xumm]]></dc:creator><pubDate>Wed, 26 Jun 2024 09:32:02 GMT</pubDate></item><item><title><![CDATA[Reply to IMX 287 opencv python多线程多相机硬触发帧率下降 on Wed, 26 Jun 2024 08:48:37 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/veye_xumm" aria-label="Profile: veye_xumm">@<bdi>veye_xumm</bdi></a> 经过一番尝试后没能找到，最后是用python多进程为每个相机分别subprocess运行v4l2-ctl命令行然后读取--stream-mmap --verbose的时间戳，目前一切顺利。还想请教一下怎么做real time binning，就是实时地将2x2或者4x4的像素值求和再保存，我们的c水平比较烂哈哈。</p>
]]></description><link>http://forum.veye.cc/post/4264</link><guid isPermaLink="true">http://forum.veye.cc/post/4264</guid><dc:creator><![CDATA[EtherealHorizon]]></dc:creator><pubDate>Wed, 26 Jun 2024 08:48:37 GMT</pubDate></item><item><title><![CDATA[Reply to IMX 287 opencv python多线程多相机硬触发帧率下降 on Sun, 23 Jun 2024 03:03:23 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/etherealhorizon" aria-label="Profile: etherealhorizon">@<bdi>etherealhorizon</bdi></a> said in <a href="/post/4240">IMX 287 opencv python多线程多相机硬触发帧率下降</a>:</p>
<blockquote>
<p dir="auto">感谢提醒，更换multi-processing之后帧率就正常了。另一个问题是v4l2-python的版本已经多年没有更新，无法直接获取时间</p>
</blockquote>
<p dir="auto">好。<br />
驱动层中，v4l2_buffer-&gt;timestamp在接收到一帧数据时打上的时间戳。这个值通过v4l2获取buffer的接口是能读到的。你可以查一下v4l-python能不能正常获取此值？</p>
]]></description><link>http://forum.veye.cc/post/4241</link><guid isPermaLink="true">http://forum.veye.cc/post/4241</guid><dc:creator><![CDATA[veye_xumm]]></dc:creator><pubDate>Sun, 23 Jun 2024 03:03:23 GMT</pubDate></item><item><title><![CDATA[Reply to IMX 287 opencv python多线程多相机硬触发帧率下降 on Fri, 21 Jun 2024 13:31:02 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/veye_xumm" aria-label="Profile: veye_xumm">@<bdi>veye_xumm</bdi></a><br />
感谢提醒，更换multi-processing之后帧率就正常了。另一个问题是v4l2-python的版本已经多年没有更新，无法直接获取时间戳，不知道有没有解决方案或者比较成熟的c++案例？</p>
]]></description><link>http://forum.veye.cc/post/4240</link><guid isPermaLink="true">http://forum.veye.cc/post/4240</guid><dc:creator><![CDATA[EtherealHorizon]]></dc:creator><pubDate>Fri, 21 Jun 2024 13:31:02 GMT</pubDate></item><item><title><![CDATA[Reply to IMX 287 opencv python多线程多相机硬触发帧率下降 on Fri, 21 Jun 2024 02:35:08 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/etherealhorizon" aria-label="Profile: etherealhorizon">@<bdi>etherealhorizon</bdi></a><br />
我查到一些信息，希望对你有一定的帮助：</p>
<ul>
<li>
<p dir="auto">python线程<br />
在Python中，线程确实只能实现逻辑独立，但不能真正做到并发运行。这是由于Python的全局解释器锁（Global Interpreter Lock, GIL）导致的。<br />
因此要做到并发，需要用多进程。</p>
</li>
<li>
<p dir="auto">cv2的cap.read()函数，涉及到内存拷贝。<br />
读取到的帧数据通常以原始格式存储（例如 YUV 或 RGB 格式）。OpenCV 需要将这些原始数据转换为 <code>cv::Mat</code> 类型，以便在 OpenCV 中进行处理。 这个转换过程涉及到将原始数据复制到新的内存缓冲区中，并按照 OpenCV 的内部格式进行排列。这个地方应该是你程序的性能节点。</p>
</li>
</ul>
<p dir="auto">如果你的嵌入式平台是多核，建议采用多进程来并发运算。</p>
]]></description><link>http://forum.veye.cc/post/4235</link><guid isPermaLink="true">http://forum.veye.cc/post/4235</guid><dc:creator><![CDATA[veye_xumm]]></dc:creator><pubDate>Fri, 21 Jun 2024 02:35:08 GMT</pubDate></item><item><title><![CDATA[Reply to IMX 287 opencv python多线程多相机硬触发帧率下降 on Fri, 21 Jun 2024 01:09:21 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/etherealhorizon" aria-label="Profile: etherealhorizon">@<bdi>etherealhorizon</bdi></a><br />
下面这点代码是我用工具辅助生成的，仅作参考</p>
<pre><code># Function to set buffer count
def set_buffer_count(device, buffer_count):
    fd = os.open(device, os.O_RDWR)
    req = v4l2.v4l2_requestbuffers()
    req.count = buffer_count
    req.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE
    req.memory = v4l2.V4L2_MEMORY_MMAP
    fcntl.ioctl(fd, v4l2.VIDIOC_REQBUFS, req)
    print(f'Number of buffers set: {req.count}')
    os.close(fd)
</code></pre>
<p dir="auto">python进行内存拷贝方面，是否存在效率问题？ 这个我不太确定。</p>
<p dir="auto">我们对驱动和c/c++语言比较熟悉一些。像yavta这种代码，是直接使用应用层和驱动层交换内存块的方式实现取图，没有内存拷贝——当然了，应用程序取到之后，进一步进行图像处理，则是另一回事了。</p>
]]></description><link>http://forum.veye.cc/post/4231</link><guid isPermaLink="true">http://forum.veye.cc/post/4231</guid><dc:creator><![CDATA[veye_xumm]]></dc:creator><pubDate>Fri, 21 Jun 2024 01:09:21 GMT</pubDate></item><item><title><![CDATA[Reply to IMX 287 opencv python多线程多相机硬触发帧率下降 on Thu, 20 Jun 2024 10:07:06 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/veye_xumm" aria-label="Profile: veye_xumm">@<bdi>veye_xumm</bdi></a> 测试了200和100fps，实际帧率在67-69左右且不稳定。想请教如何在驱动层做调整？</p>
]]></description><link>http://forum.veye.cc/post/4230</link><guid isPermaLink="true">http://forum.veye.cc/post/4230</guid><dc:creator><![CDATA[EtherealHorizon]]></dc:creator><pubDate>Thu, 20 Jun 2024 10:07:06 GMT</pubDate></item><item><title><![CDATA[Reply to IMX 287 opencv python多线程多相机硬触发帧率下降 on Thu, 20 Jun 2024 09:57:18 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/etherealhorizon" aria-label="Profile: etherealhorizon">@<bdi>etherealhorizon</bdi></a><br />
请问你现在配置的帧率是多少？<br />
我们对于python层面不太懂，不过我觉得如果是调度问题，可以尝试增加驱动层buffer的数量。</p>
]]></description><link>http://forum.veye.cc/post/4229</link><guid isPermaLink="true">http://forum.veye.cc/post/4229</guid><dc:creator><![CDATA[veye_xumm]]></dc:creator><pubDate>Thu, 20 Jun 2024 09:57:18 GMT</pubDate></item></channel></rss>