smbxfdbz 发表于 2023-2-27 15:21:47

请大家出谋划策,基于usb摄像头的系统,延迟怎么优化

系统的基本功能是,用usb摄像头进行目标追踪,然后将识别到的坐标通过usb串口发送出来
我用python写了个测试程序,测试从目标进入摄像头,到串口接收到检测坐标的延迟时间为70ms左右
测试程序是用两个线程跑,一个线程读摄像头,一个线程检测目标,两边的帧率都能达到60Hz以上,但延迟却要70ms左右,也就是4帧左右
这个延迟主要是在哪里产生的,如何优化呢,请大家出谋划策一下吧,非常感谢

redworlf007 发表于 2023-2-27 15:42:43

你能不能描述清楚一些,你的usb摄像头接到啥cpu上了?串口数据从哪里usb转串口上出去的。
你描述的一塌糊涂。

lyxer 发表于 2023-2-27 15:43:30

分段测量时间消耗 再看哪里能优化
70ms看着差不多正常

smbxfdbz 发表于 2023-2-27 15:58:09

redworlf007 发表于 2023-2-27 15:42
你能不能描述清楚一些,你的usb摄像头接到啥cpu上了?串口数据从哪里usb转串口上出去的。
你描述的一塌糊涂 ...
(引用自2楼)

就是普通的个人电脑,都是接到电脑usb接口上的
win11系统,i9-12900K cpu

redworlf007 发表于 2023-2-27 16:03:15

smbxfdbz 发表于 2023-2-27 15:58
就是普通的个人电脑,都是接到电脑usb接口上的
win11系统,i9-12900K cpu
(引用自4楼)

你用程序打印下,你的程序拿到图片的时间、检测到物体的时间、算出坐标的时间、串口打印的时间,分别在日志里面写出来或者打印的调试信息里面,看看到底是哪里用的时间长。

smbxfdbz 发表于 2023-2-27 16:04:10

lyxer 发表于 2023-2-27 15:43
分段测量时间消耗 再看哪里能优化
70ms看着差不多正常
(引用自3楼)

已经分不下去了,我是把摄像头放到暗盒里,一开灯,就会拍摄到画面
主要延迟就是从开灯到拍摄到画面这段时间,用opencv,这个部分就只有一行代码,就是cap.read()
这个读与摄像头帧率是同步的,可以达到60fps,但从开灯到读到画面,却要用掉4帧左右的时间,主要是想优化这个延时

smbxfdbz 发表于 2023-2-27 16:08:43

redworlf007 发表于 2023-2-27 16:03
你用程序打印下,你的程序拿到图片的时间、检测到物体的时间、算出坐标的时间、串口打印的时间,分别在日 ...
(引用自5楼)

参考楼上回复
就是从开灯,到摄像头读取到亮的画面,延迟特别久,但这个部分只有一行cap.read代码(用opencv)
也就是延迟都发生在底层驱动部分,这部分对应用软件根本不可见,有什么办法优化呢?

locky_z 发表于 2023-2-27 16:13:57

多大分辨率?例如高清USB2.0摄像头,在电脑上看,就是6-10帧左右。

智涅 发表于 2023-2-27 16:14:59

开灯这个方法测试可能不严谨吧?灯太暗的时候影响曝光时间吧?
我们以前测试是用个毫秒表在显示器上面跳,摄像头对着,画面同样再显示器上面显示,用手机录像
回放看视频的时候可以看到画面两个毫秒表之间的时间差

smbxfdbz 发表于 2023-2-27 16:22:30

智涅 发表于 2023-2-27 16:14
开灯这个方法测试可能不严谨吧?灯太暗的时候影响曝光时间吧?
我们以前测试是用个毫秒表在显示器上面跳, ...
(引用自9楼)

我是把曝光时间固定进行测试,结合示波器测量开灯信号与串口指令的时间差
感觉还是比较严谨的,开关灯,曝光时间不会变化的

你这种测试方法感觉也不太准,因为显示器的刷新率一般也就是60Hz,刷新一帧都要16ms了,精确不到ms级的测量

smbxfdbz 发表于 2023-2-27 16:23:50

locky_z 发表于 2023-2-27 16:13
多大分辨率?例如高清USB2.0摄像头,在电脑上看,就是6-10帧左右。
(引用自8楼)

我用的是高帧率摄像头,1280x720分辨率,读帧率能到120Hz

boyiee 发表于 2023-2-27 16:49:01

用显示器显示一个毫秒级别的数字时间表, 然后把各阶段的图片同时抓图,就知道是哪个步骤产生的延时了。

fengyuganyu 发表于 2023-2-27 17:45:01

可以用DirectShow打开摄像头试试

vtte 发表于 2023-2-27 17:52:38

不要用cv,用pygame开摄像头快得多

wxw123321 发表于 2023-2-27 23:46:20

可以试试修改opencv的代码,把MAX_V4L_BUFFERS降低

iamseer 发表于 2023-2-28 09:05:36

关注一下这个问题。我之前也遇到了。

https://stackoverflow.com/questions/54460797/how-to-disable-buffer-in-opencv-camera

好像我当时的方法是反复读直到读不出来,这样可以部分回避缓存的影响。

honami520 发表于 2023-2-28 09:17:04

本帖最后由 honami520 于 2023-2-28 09:18 编辑

我以前做过一次USB摄像头的项目,当时就发现光线暗的时候帧率会降低,最后自己总结是曝光的问题,然后就没管了。
当时用的qt+opencv来做的。现象是拿手在摄像头前晃动,然后画面显示到液晶屏上面。白天的时候延迟小,晚上光线暗手就跟不上画面了

smbxfdbz 发表于 2023-2-28 09:45:54

vtte 发表于 2023-2-27 17:52
不要用cv,用pygame开摄像头快得多
(引用自14楼)

你实测过对比过吗?
我用pygame测试,用同样的测试方法,用pygame的get_image()方法,帧率上不去,只能到40多帧,但是用opencv的VideoCapture.read(),帧率能到80多,摄像头本身是能到120帧的
还有个奇怪的问题,即使在单独的线程里,用pygame读摄像头,也会严重挤占cpu资源,导致图像检测线程帧率严重下降,整个程序占用的cpu资源始终在10%以下
但是用opencv读摄像头,图像检测线程的帧率会快很多,整个程序占用的cpu资源能到18%
用pygame,测试帧率在40多,延迟时间在120ms左右
用opencv,测试帧率能到80多,延迟时间在80ms左右

如何改进呢,帮忙分析一下吧
下面是分别使用opencv和pygame读摄像头的代码

#使用opencv
def read_cam():
    # 创建相机对象
    # 设置相机
    cap1 = cv2.VideoCapture(701)
    cap1.set(3, 1280)
    cap1.set(4, 720)

    cap2 = cv2.VideoCapture(700)
    cap2.set(3, 1280)
    cap2.set(4, 720)
    print("曝光:", cap1.get(15), cap2.get(15))

    cnt = 0;
    time_last = time.time()
    while True:
      # 读取摄像头图像
      ret1, frame1 = cap1.read()
      ret2, frame2 = cap2.read()
      height, width = frame1.shape[:2]
      # 高度裁剪为32的整数倍
      cropped_frame1 = frame1
      cropped_frame2 = frame2
      # 垂直拼接和缩放图像
      frame_lr = cv2.vconcat()
      frame_lr = cv2.resize(frame_lr,(640,704))
      # read_cam.frame = frame_lr
      frame_queue.put(frame_lr)
      # 统计帧率
      cnt = cnt + 1;
      if(cnt == 99):
            cnt = 0;
            time_interval = time.time()-time_last
            time_last = time.time()
            fps = 100/time_interval
            fps = round(fps,1)
            print("read_cam帧率:",fps,np.size(frame_lr),np.shape(frame_lr))

#使用pygame
def read_cam():
    # 创建相机对象
    # 设置相机
    pygame.init()
    pygame.camera.init()

    # 获取摄像头列表
    cam_list = pygame.camera.list_cameras()
    if not cam_list:
      print('没有找到摄像头!')
      quit()

    # 选择第一个摄像头
    cam1 = pygame.camera.Camera(cam_list,(1280,720))
    cam2 = pygame.camera.Camera(cam_list,(1280,720))
    cam1.start()
    cam2.start()

    cnt = 0;
    time_last = time.time()
    while True:
      # 读取摄像头图像
      image1 = cam1.get_image() # 阻塞等待摄像头响应
      image1 = pygame.transform.rotate(image1, 90)
      cv_image1 = cv2.cvtColor(pygame.surfarray.array3d(image1),cv2.COLOR_RGB2BGR)

      image2 = cam2.get_image()# 阻塞等待摄像头响应
      image2 = pygame.transform.rotate(image2, 90)
      cv_image2 = cv2.cvtColor(pygame.surfarray.array3d(image2),cv2.COLOR_RGB2BGR)

      height, width = cv_image1.shape[:2]
      # 高度裁剪为32的整数倍
      cropped_frame1 = cv_image1
      cropped_frame2 = cv_image2
      # 垂直拼接和缩放图像
      frame_lr = cv2.vconcat()
      frame_lr = cv2.resize(frame_lr,(640,704))
      # read_cam.frame = frame_lr
      frame_queue.put(frame_lr)
      # 统计帧率
      cnt = cnt + 1;
      if(cnt == 99):
            cnt = 0;
            time_interval = time.time()-time_last
            time_last = time.time()
            fps = 100/time_interval
            fps = round(fps,1)
            print("read_cam帧率:",fps)

智涅 发表于 2023-2-28 11:27:02

哦对了,我之前测试,python里头的多线程只会用一个cpu核,真正要想把性能干爆需要用【多进程】{:titter:}
页: [1]
查看完整版本: 请大家出谋划策,基于usb摄像头的系统,延迟怎么优化