Raspberry Pi 3 使用 720p USB 摄像头提高 FPS
Raspberry Pi 3 Increasing FPS with 720p USB Camera
我在 python 中写了一些代码来打开 USB 摄像头并从中抓取帧。我将我的代码用于 http 流。对于 JPEG 编码,我使用 libturbojpeg 库。为此,我使用 64 位 OS。
product: Raspberry Pi 3 Model B Rev 1.2
serial: 00000000f9307746
width: 64 bits
capabilities: smp cp15_barrier setend swp
我用不同的分辨率做了一些测试。
Resolution FPS Time for encode
640 x 480 ~35 ~0.01
1280 x 720 ~17 ~0.028
这是我的代码
import time
import os
import re
import uvc
from turbojpeg import TurboJPEG, TJPF_GRAY, TJSAMP_GRAY
jpeg = TurboJPEG("/opt/libjpeg-turbo/lib64/libturbojpeg.so")
camera = None
import numpy as np
from threading import Thread
class ProcessJPG(Thread):
def __init__(self, data):
self.jpeg_data = None
self.data = data
super(ProcessJPG, self).__init__()
def run(self):
self.jpeg_data = jpeg.encode((self.data))
def get_frame(self):
self.frame = camera.get_frame()
global camera
dev_list = uvc.device_list()
print("devices: ", dev_list)
camera = uvc.Capture(dev_list[1]['uid'])
camera.frame_size = camera.frame_sizes[2] // set 1280 x 720
camera.frame_rate = camera.frame_rates[0] // set 30 fps
class GetFrame(Thread):
def __init__(self):
self.frame = None
super(GetFrame, self).__init__()
def run(self):
self.frame = camera.get_frame()
_fps = -1
count_to_fps = 0
_real_fps = 0
from time import time
_real_fps = ""
cfps_time = time()
while True:
if camera:
t = GetFrame()
t.start()
t.join()
img = t.frame
timestamp = img.timestamp
img = img.img
ret = 1
t_start = time()
t = ProcessJPG(img)
t.start()
t.join()
jpg = t.jpeg_data
t_end = time()
print(t_end - t_start)
count_to_fps += 1
if count_to_fps >= _fps:
t_to_fps = time() - cfps_time
_real_fps = 1.0 / t_to_fps
cfps_time = time()
count_to_fps = 0
print("FPS, ", _real_fps)
编码行是:jpeg.encode((self.data))
我的问题是,对于 1280 x 720(例如 30fps)分辨率,可以提高 FPS 还是我应该使用更强大的设备?当我在计算期间查看 htop 时,CPU 未 100% 使用。
编辑:
相机格式:
[video4linux2,v4l2 @ 0xa705c0] Raw : yuyv422 : YUYV 4:2:2 : 640x480 1280x720 960x544 800x448 640x360 424x240 352x288 320x240 800x600 176x144 160x120 1280x800
[video4linux2,v4l2 @ 0xa705c0] Compressed: mjpeg : Motion-JPEG : 640x480 1280x720 960x544 800x448 640x360 800x600 416x240 352x288 176x144 320x240 160x120
这是可能的,您不需要更强大的硬件。
* Capture instance will always grab mjpeg conpressed frames from cameras.
当您的代码访问 .img
属性 时,会调用 jpeg2yuv
(请参阅
here 和
here)。然后
您正在使用 jpeg_encode()
重新编码。之后尝试使用 frame.jpeg_buffer
捕获并且根本不要触摸 .img
。
我用 Logitech 查看了 RPi2 上的 pyuvc
C310 做了一个
简化示例,
import uvc
import time
def main():
dev_list = uvc.device_list()
cap = uvc.Capture(dev_list[0]["uid"])
cap.frame_mode = (1280, 720, 30)
tlast = time.time()
for x in range(100):
frame = cap.get_frame_robust()
jpeg = frame.jpeg_buffer
print("%s (%d bytes)" % (type(jpeg), len(jpeg)))
#img = frame.img
tnow = time.time()
print("%.3f" % (tnow - tlast))
tlast = tnow
cap = None
main()
我每帧得到 ~.033s,在 ~8%CPU 下达到 ~30fps。如果我取消注释 #img = frame.img
行,它会上升到 ~.054s/frame 或 ~18fps at 99%CPU(解码时间限制捕获率)。
我在 python 中写了一些代码来打开 USB 摄像头并从中抓取帧。我将我的代码用于 http 流。对于 JPEG 编码,我使用 libturbojpeg 库。为此,我使用 64 位 OS。
product: Raspberry Pi 3 Model B Rev 1.2
serial: 00000000f9307746
width: 64 bits
capabilities: smp cp15_barrier setend swp
我用不同的分辨率做了一些测试。
Resolution FPS Time for encode
640 x 480 ~35 ~0.01
1280 x 720 ~17 ~0.028
这是我的代码
import time
import os
import re
import uvc
from turbojpeg import TurboJPEG, TJPF_GRAY, TJSAMP_GRAY
jpeg = TurboJPEG("/opt/libjpeg-turbo/lib64/libturbojpeg.so")
camera = None
import numpy as np
from threading import Thread
class ProcessJPG(Thread):
def __init__(self, data):
self.jpeg_data = None
self.data = data
super(ProcessJPG, self).__init__()
def run(self):
self.jpeg_data = jpeg.encode((self.data))
def get_frame(self):
self.frame = camera.get_frame()
global camera
dev_list = uvc.device_list()
print("devices: ", dev_list)
camera = uvc.Capture(dev_list[1]['uid'])
camera.frame_size = camera.frame_sizes[2] // set 1280 x 720
camera.frame_rate = camera.frame_rates[0] // set 30 fps
class GetFrame(Thread):
def __init__(self):
self.frame = None
super(GetFrame, self).__init__()
def run(self):
self.frame = camera.get_frame()
_fps = -1
count_to_fps = 0
_real_fps = 0
from time import time
_real_fps = ""
cfps_time = time()
while True:
if camera:
t = GetFrame()
t.start()
t.join()
img = t.frame
timestamp = img.timestamp
img = img.img
ret = 1
t_start = time()
t = ProcessJPG(img)
t.start()
t.join()
jpg = t.jpeg_data
t_end = time()
print(t_end - t_start)
count_to_fps += 1
if count_to_fps >= _fps:
t_to_fps = time() - cfps_time
_real_fps = 1.0 / t_to_fps
cfps_time = time()
count_to_fps = 0
print("FPS, ", _real_fps)
编码行是:jpeg.encode((self.data))
我的问题是,对于 1280 x 720(例如 30fps)分辨率,可以提高 FPS 还是我应该使用更强大的设备?当我在计算期间查看 htop 时,CPU 未 100% 使用。
编辑: 相机格式:
[video4linux2,v4l2 @ 0xa705c0] Raw : yuyv422 : YUYV 4:2:2 : 640x480 1280x720 960x544 800x448 640x360 424x240 352x288 320x240 800x600 176x144 160x120 1280x800
[video4linux2,v4l2 @ 0xa705c0] Compressed: mjpeg : Motion-JPEG : 640x480 1280x720 960x544 800x448 640x360 800x600 416x240 352x288 176x144 320x240 160x120
这是可能的,您不需要更强大的硬件。
* Capture instance will always grab mjpeg conpressed frames from cameras.
当您的代码访问 .img
属性 时,会调用 jpeg2yuv
(请参阅
here 和
here)。然后
您正在使用 jpeg_encode()
重新编码。之后尝试使用 frame.jpeg_buffer
捕获并且根本不要触摸 .img
。
我用 Logitech 查看了 RPi2 上的 pyuvc C310 做了一个 简化示例,
import uvc
import time
def main():
dev_list = uvc.device_list()
cap = uvc.Capture(dev_list[0]["uid"])
cap.frame_mode = (1280, 720, 30)
tlast = time.time()
for x in range(100):
frame = cap.get_frame_robust()
jpeg = frame.jpeg_buffer
print("%s (%d bytes)" % (type(jpeg), len(jpeg)))
#img = frame.img
tnow = time.time()
print("%.3f" % (tnow - tlast))
tlast = tnow
cap = None
main()
我每帧得到 ~.033s,在 ~8%CPU 下达到 ~30fps。如果我取消注释 #img = frame.img
行,它会上升到 ~.054s/frame 或 ~18fps at 99%CPU(解码时间限制捕获率)。