libcamera-hello
sudo apt install -y python3-picamera2
sudo apt install -y python3-pyqt5 python3-opengl
四种预览窗口
窗口可以进行调整,可以进行transform,flip和截取部分
from picamera2 import Picamera2, Preview
from libcamera import Transform
picam2 = Picamera2()
picam2.start_preview(Preview.QTGL, x=100, y=200, width=800, height=600,
transform=Transform(hflip=1))
picam2.start()
有以下操作:
• Transform() - 等价转换,默认
• Transform(hflip=1) - horizontal flip 水平反转
• Transform(vflip=1) - vertical flip 垂直翻转
• Transform(hflip=1, vflip=1) - horizontal and vertical flip (equivalent to a 180 degree rotation)180°翻转
重要的是要意识到,这里讨论的transform对从相机接收到的实际图像没有任何影响
接下来的重点是 QtGL | Qt | DRM/KMS preview
from picamera2 import Picamera2, Preview
picam2 = Picamera2()
picam2.start_preview(Preview.QTGL)
当图像需要显示在远程显示器上(未连接到Pi)时,不建议使用QtGL预览窗口
当使用VNC时:
from picamera2 import Picamera2, Preview
picam2 = Picamera2()
picam2.start_preview(Preview.QT)
总之什么时候用呢:
DRM/KMS预览窗口用于X窗口不运行时,相机系统可以在显示屏上租用一个“layer”来显示图形。
因为X Windows未运行,所以无法使用鼠标移动或调整此窗口的大小。DRM/KMS预览版将是树莓派OS Lite用户的自然选择。它也强烈推荐给低功率的树莓派,因为通过X Windows显示堆栈进行预览(例如每秒30帧)代价昂贵。
from picamera2 import Picamera2, Preview
picam2 = Picamera2()
picam2.start_preview(Preview.DRM)
如果您没有运行或挂起X-Winidows,但仍然有一个显示屏连接着树莓派,您可以登录到Pi而不需要x转发,并使用DRM/KMS预览实现。画面将出现在直接连接到Pi的显示器上。
总之,x-windows应该是将树莓派的图像 转发到remote类似的软件级别app上。
通常是预览窗口通过接收相机图像,将其传递给应用程序中间商 传递,用户不再需要它们时再回收这些缓冲区,从而驱动自由摄像头系统。其结果是,即使preview图像没有被展示,仍然需要运行一些东西才能接收这些相机图像,然后返回这些相机图像。这正是null preview 所做的。它什么也不显示;它只是驱动着摄像系统。实际上,如果还没有preview运行,只要相机系统启动(picam2.start()),空预览就会自动启动,这就是为什么必须提前启动替代预览窗口!!
from picamera2 import Picamera2, Preview
import time
picam2 = Picamera2()
config = picam2.create_preview_configuration()
picam2.configure(config)
picam2.start()
time.sleep(2)
picam2.stop_preview()
picam2.start_preview(True)
time.sleep(2)
from picamera2 import Picamera2
picam2 = Picamera2()
picam2.start(show_preview=True)
picam2.title_fields = ["ExposureTime", "AnalogueGain"]
一旦创建了一个Picamera2对象,一般的模式是必须为相机生成一个配置,该配置必须应用于相机系统(使用Picamera2.configure方法),然后就可以启动相机系统。
ISP二刀流 + 原始流 = 三刀流
注意每把刀都是不一样的! [不一样在于格式]
事件的顺序如下:
因此,Picamera2的配置分为:
相机图像通常用numpy数组表示,所以熟悉numpy将会有所帮助。这也是OpenCV使用的表示,因此picamera2、numpy和OpenCV都可以无缝地一起工作。
当捕获图像时,Picamera2函数在其捕获函数中使用以下命名法:
from picamera2 import Picamera2
import time
picam2 = Picamera2()
picam2.start()
time.sleep(1)
The Picamera2 Library
6.1. Capturing images 31
array = picam2.capture_array("main")
from picamera2 import Picamera2
import time
picam2 = Picamera2()
picam2.start()
time.sleep(1)
image = picam2.capture_image("main")
还有捕获功能,可以将图像直接保存到文件中,并在相机模式之间切换,从而将快速帧率预览与高分辨率捕获相结合。
那么如何进行切换?
from picamera2 import Picamera2
import time
picam2 = Picamera2()
capture_config = picam2.create_still_configuration()
picam2.start(show_preview=True)
time.sleep(1)
array = picam2.switch_mode_and_capture_array(capture_config, "main")
这将切换到高分辨率捕获模式,并返回numpy数组,然后将自动切换回预览模式,无需任何用户干预。
当然如果不自动切回去原模式呢?也是可以的:
from picamera2 import Picamera2
import time
picam2 = Picamera2()
preview_config = picam2.create_preview_configuration()
capture_config = picam2.create_still_configuration()
picam2 = picam2.configure(preview_config)
picam2.start(show_preview=True)
time.sleep(1)
picam2.switch_mode(capture_config)
array = picam2.capture_array("main")
picam2.switch_mode(preview_config)
预览切拍照,直接存为文件
from picamera2 import Picamera2
import time
picam2 = Picamera2()
capture_config = picam2.create_still_configuration()
picam2.start(show_preview=True)
time.sleep(1)
picam2.switch_mode_and_capture_file(capture_config, "image.jpg")
存储于内存缓冲中
from picamera2 import Picamera2
import io
import time
picam2 = Picamera2()
picam2.start()
time.sleep(1)
data = io.BytesIO()
picam2.capture_file(data, format='jpeg')
在Picamera2中,捕获和编码视频的过程基本上是自动的。应用程序只需要定义它要使用什么来压缩图像数据的编码器,以及它希望如何输出这个压缩的数据流。将到达的相机图像转发到编码器,编码器再将结果直接发送到请求的输出,这对用户来说是完全透明的。编码和输出都发生在一个单独的线程从相机处理,以最大限度地减少丢弃相机帧的风险。这是第一个捕捉10秒钟视频的例子:
# 导入H264Encoder类,用于视频编码
from picamera2.encoders import H264Encoder
# 导入Picamera2类,这是与Raspberry Pi相机硬件交互的主要类
from picamera2 import Picamera2
# 导入time模块,用于控制录制时长
import time
# 创建一个Picamera2对象,通过这个对象我们可以控制相机硬件
picam2 = Picamera2()
# 创建一个视频配置对象,这个对象包含了相机录制视频时所需要的所有配置信息
video_config = picam2.create_video_configuration()
# 使用上面创建的视频配置对象来配置相机硬件
picam2.configure(video_config)
# 创建一个H264Encoder对象,设置比特率为10000000,这意味着视频的质量会相对较高
encoder = H264Encoder(bitrate=10000000)
# 设置输出文件名为"test.h264"
output = "test.h264"
# 开始录制视频,使用上面创建的编码器和输出文件名
picam2.start_recording(encoder, output)
# 让程序暂停10秒钟,这10秒钟内,相机将持续录制视频
time.sleep(10)
# 停止录制视频
picam2.stop_recording()
上面的start_recording和stop_recording是high level集成的函数,其实也可以自己自由细粒度操作:
# 启动编码器,准备开始视频录制。encoder是之前创建好的编码器对象,output是输出文件名。
picam2.start_encoder(encoder, output)
# 启动相机硬件,开始捕获视频流并进行编码。这一步必须在start_encoder之后调用,以确保编码器已经准备好。
picam2.start()
# 停止相机硬件,结束视频捕获。这一步通常在你想停止录制视频时调用。
picam2.stop()
# 停止编码器,结束视频编码。这一步通常在stop之后调用,以确保所有的视频数据都已经被正确地写入文件。
picam2.stop_encoder()
# 从picamera2.encoders模块导入H264Encoder和Quality类。H264Encoder是用于视频编码的类,Quality是用于设置视频质量的类。
from picamera2.encoders import H264Encoder, Quality
# 从picamera2模块导入Picamera2类,这是与Raspberry Pi相机硬件交互的主要类。
from picamera2 import Picamera2
# 导入time模块,它提供了一个跨平台的方式来让程序暂停执行一段时间,常用于添加延时。
import time
# 创建一个Picamera2对象,通过这个对象我们可以控制相机硬件。
picam2 = Picamera2()
# 使用create_video_configuration方法创建一个视频配置对象,这个对象包含了相机录制视频时所需要的所有默认配置信息。
# 然后使用configure方法应用这些默认配置到相机硬件。
picam2.configure(picam2.create_video_configuration())
# 创建一个H264Encoder对象,没有指定任何参数,所以它将使用默认设置进行视频编码。
encoder = H264Encoder()
# 使用start_recording方法开始录制视频。这个方法需要三个参数:编码器对象、输出文件名和视频质量。
# 在这里,我们使用之前创建的编码器对象,将输出文件名设置为'test.h264',并将视频质量设置为高品质(Quality.HIGH)。
picam2.start_recording(encoder, 'test.h264', Quality.HIGH)
# 使用time模块的sleep方法让程序暂停执行10秒钟。在这10秒钟内,相机将持续录制视频。
time.sleep(10)
# 使用stop_recording方法停止录制视频。此时,相机将停止捕获视频,并将已经捕获并编码的视频数据写入文件。
picam2.stop_recording()
在picamera2
库中,JpegEncoder、MJpegEncoder、H264Encoder和NullEncoder是用于处理图像和视频的编码器。以下是它们的详细介绍:
JpegEncoder:
MJpegEncoder:
H264Encoder:
NullEncoder:
# 导入Picamera2类,这是用于与Raspberry Pi相机硬件进行交互的主要类。
from picamera2 import Picamera2
# 导入Encoder类,这是用于视频编码的基类,尽管在本例中实际上使用的是原始数据(不进行编码)。
from picamera2.encoders import Encoder
# 导入time模块,用于添加延时。
import time
# 创建一个Picamera2对象,通过这个对象我们可以控制相机硬件。
picam2 = Picamera2()
# 使用create_video_configuration方法创建一个视频配置对象。这里传入raw={}和encode="raw"参数,指定配置为原始数据格式。
config = picam2.create_video_configuration(raw={}, encode="raw")
# 使用configure方法应用这些配置到相机硬件。
picam2.configure(config)
# 创建一个Encoder对象。在这个特定的例子中,我们实际上并不对视频进行编码,而是直接保存原始数据。
encoder = Encoder()
# 使用start_recording方法开始录制视频。指定编码器对象、输出文件名以及使用原始数据格式。这将使相机开始捕获视频并将其保存为指定的原始数据文件。
picam2.start_recording(encoder, "test.raw")
# 使用time模块的sleep方法让程序暂停执行5秒钟。在这5秒钟内,相机将持续录制视频。
time.sleep(5)
# 使用stop_recording方法停止录制视频。此时,相机将停止捕获视频,并将已经捕获的原始数据写入文件。
picam2.stop_recording()
选择建议:
输出对象直接从编码器接收编码的视频帧,并通常将它们转发到文件或网络套接字。输出对象通常由其构造函数生成,不过可以将一个简单的字符串传递给start_encoder和start_recording函数,这将导致自动生成FileOutput对象。
在picamera2
库中,输出对象用于指定视频录制或图像捕获的输出目标。以下是关于FileOutput
、FfmpegOutput
和CircularOutput
的具体解释:
FileOutput:
FileOutput
会将数据写入指定的文件中。写入文件:
# 从picamera2.outputs模块导入FileOutput类,这个类用于将视频或图像数据写入文件。
from picamera2.outputs import FileOutput
# 创建一个FileOutput对象,并指定输出文件名为'test.h264'。
output = FileOutput('test.h264')
写入内存:
# 导入FileOutput类。
from picamera2.outputs import FileOutput
# 导入io模块,它提供了一个流式的I/O接口。
import io
# 创建一个BytesIO对象,它是一个可以读写二进制数据的内存缓冲区。
buffer = io.Bytes()
# 创建一个FileOutput对象,并使用前面创建的内存缓冲区作为输出目标。这样,视频或图像数据将被写入内存缓冲区而不是文件。
output = FileOutput(buffer)
写入UDP套接字:
# 导入FileOutput类。
from picamera2.outputs import FileOutput
# 导入socket模块,它提供了网络通信的功能。
import socket
# 创建一个UDP套接字,并连接到指定的IP地址和端口。这里使用"REMOTEIP"作为占位符,实际使用时需要替换为实际的IP地址。
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
sock.connect(("REMOTEIP", 10001))
# 通过套接字的makefile方法创建一个二进制文件流,用于发送数据。
stream = sock.makefile("wb")
# 创建一个FileOutput对象,并使用前面创建的网络流作为输出目标。这样,视频或图像数据将被发送到指定的网络地址和端口。
output = FileOutput(stream)
FfmpegOutput:
FfmpegOutput
可以使用FFmpeg库的功能对数据进行编码,并将编码后的数据写入指定的文件中。输出类将编码的帧转发给FFmpeg进程。这为一些相当复杂的新输出类型打开了大门,包括MP4文件,甚至是音频,但可能需要关于FFmpeg本身的大量知识:
# 从picamera2.outputs模块导入FfmpegOutput类,这个类使用FFmpeg库将视频或图像数据进行编码并写入文件。
from picamera2.outputs import FfmpegOutput
# 创建一个FfmpegOutput对象,并指定输出文件名为'test.mp4',同时启用音频编码。这意味着视频和音频数据都将被编码并写入指定的文件。
output = FfmpegOutput("test.mp4", audio=True)
CircularOutput:
CircularOutput
可以在达到限制时循环覆盖最早的数据,从而实现循环录制的效果。这在一些需要长时间连续录制的应用中很有用,比如安全监控等。这些输出对象提供了不同的功能和灵活性,以适应各种应用场景和需求。选择适当的输出对象可以帮助更好地控制视频录制和图像捕获的输出方式,并满足特定的项目需求。
循环录制:
# 从picamera2.encoders模块导入H264Encoder类,这个类用于将视频编码为H.264格式。
from picamera2.encoders import H264Encoder
# 从picamera2.outputs模块导入CircularOutput类,这个类实现循环录制的功能。
from picamera2.outputs import CircularOutput
# 从picamera2模块导入Picamera2类,这是与Raspberry Pi相机硬件交互的主要类。
from picamera2 import Picamera2
# 创建一个Picamera2对象,通过这个对象我们可以控制相机硬件。
picam2 = Picamera2()
# 使用create_video_configuration方法创建一个视频配置对象,并使用默认的配置信息对相机进行配置。
picam2.configure(picam2.create_video_configuration())
# 创建一个H264Encoder对象,用于将视频编码为H.264格式。
encoder = H264Encoder()
# 创建一个CircularOutput对象,用于实现循环录制的功能。此时还没有指定输出文件。
output = CircularOutput()
# 使用start_recording方法开始录制视频。指定编码器对象和输出目标为前面创建的对象。这将使相机开始捕获视频并将其编码后发送到指定的输出目标。
picam2.start_recording(encoder, output)
# 当需要开始记录输出时,包括前5秒钟的内容:
output.fileoutput = "file.h264" # 指定输出文件名为'file.h264'。
output.start() # 开始记录输出到指定的文件。这将触发循环录制的功能,当达到指定的文件大小限制时,会覆盖最早的数据并继续录制。
# 之后可以通过以下方式停止录制:
output.stop() # 停止记录输出。这将停止循环录制功能,并关闭输出文件。