Answers:
这是我可以获得(平均)50ms结果的唯一方法。我到处寻找解决方案。1秒对于我的运动传感器项目来说太慢了。
@Dave Jones的项目帮助我弄清楚了如何做。
仅2个文件:
一个始终运行的守护程序和一个客户端。
守护程序是您设置所有相机设置的地方。
python picam-daemon.py
import threading
import os, io, base64, time, socket, picamera, daemon
import daemon.runner
MAX_LENGTH = 50 # max length of any possible entry from "client"
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # setup socket
PORT = 10000 # port 10000
HOST = '127.0.0.1' # runs on local host
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # this allows us to override port, prevents error
serversocket.bind((HOST, PORT)) # lock server to this port and host
serversocket.listen(10) # max 10 clients
# Waits for commands, such as "snap" and "ack"
# Runs over "sockets"
def handle(clientsocket):
while 1:
buf = clientsocket.recv(MAX_LENGTH)
# Receive the SNAP command. Take a picture with PiCam.
if buf == 'snap':
start = time.time()
camera.capture('/home/pi/ir/picam-latest-snap.jpg')
finish = start - time.time()
print finish
print 'Picture Taken!'
if buf == 'ack':
print 'Ping: Hello!'
if len(buf) == 0: break
# Camera is always loaded here
# The "magic" is in the camThread, this allows a picture to be captured, then it gracefully closed the camera connection and reopens it. This produces very fast captures (54ms vs 1.5s!)
while 1:
# setup camera
camera = picamera.PiCamera()
camera.resolution = (640, 480)
#camera.zoom = (0.2, 0.2, 1.0, 1.0)
camera.exposure_mode = 'sports'
print('Camera server running')
# accept connections from outside, in order to receive commands
(clientsocket, address) = serversocket.accept()
ct = threading.Thread(target=handle, args=(clientsocket,))
ct.run() # this can be run(), because it can be scaled.
print 'Camera thread starting.'
camThread = threading.Thread()
while camThread.is_alive():
camThread.join(1)
camThread.run() # this must be start(), otherwise PiCam will crash. This is because PiCam cannot receive more than 1 connection.
print 'Camera thread ended'
camera.close() # Gracefully close PiCam if client disconnects
(在第二个终端中)python picam-client.py
import socket
import sys
HOST = '127.0.0.1'
PORT = 10000
s = socket.socket()
s.connect((HOST, PORT))
print s
while 1:
msg = raw_input("Command To Send: ")
if msg == "close":
s.close()
sys.exit(0)
s.send(msg)
我发布此答案的原因是,我在Google中找到了这个答案,试图自己找到答案。我找不到一个,所以我不得不深入研究一些项目,然后自己想出一些办法。
您需要将超时指定为0。
从raspistill帮助
-timeout "Time (in ms) before takes picture and shuts down (if not specified, set to 5s)
要测试命令执行所需的时间,您可以使用“时间”
time raspistill -o /home/pi/test55.jpg -ex sports --nopreview --timeout 0
-t
选项。如@Cerin所述,如果设置得太低,这会以某种方式破坏图像。老实说,Raspberry Pi的文档中关于此选项的信息太少,导致错误的假设,认为超时是简单的“延迟” /“时间触发”,而事实并非如此。
我在.bash_profile中指定了以下别名,以方便快捷地拍摄照片:
alias shot='SHOTTIME=$(date +"%Y-%m-%d_%H%M") && raspistill -o shot-$SHOTTIME.jpg --nopreview --exposure sports --timeout 1
每当我shot
在命令行上键入时,都会保存带有时间戳的图像,例如shot-2016-02-27_0934.jpg
。
--timeout 1
论点(?),如果这么快我也会感到惊讶-但由于我(尚未)使我的系统处于这样一种状态,它需要对谁试图解锁我的前端进行快照,我真的不能挑剔的门!8-)尽管很好地使用了命令行(假设已经设置了时钟)-包括首先将具有最高有效值的日期时间戳放在首位,以便字母数字排序顺序与日期排序顺序相同!
您可能想看一下compoundpi项目(完整披露:我是作者)。它旨在通过相机模块触发大量Pi的捕获,并使用UDP广播数据包使它们之间的触发尽可能地接近。每个Pi上都会运行一个守护进程,该守护进程将启动摄像机并在收到包含CAPTURE命令的UDP数据包时触发捕获(其他命令可用于配置摄像机;该协议已被详细记录)。使用以太网进行设置是理想的选择,但是wifi也可以使用,尽管在这种情况下(由于数据包丢失/可变的延迟),您可能必须使用延时功能来获得良好的同步。
我不能说它已经过100 Pi的测试-目前使用它的最大设置涉及20,但我想听听涉及更大规模的任何问题。
该项目包括一个命令行客户端,一个GUI客户端(写在Qt的,所以应该在Linux / MAC / Windows上工作,但它只有在这一点上Ubuntu的测试,它仍然无证),和基于Python的客户端库的编写批处理作业。