2023-简单点-树莓派picamera2介绍和要点

requirements简介

  1. 树莓派OS Bullsye和之后的的images镜像 默认运行libcamera camera stack,这是Picamera2所必需的。可以通过打开一个命令窗口并输入:
libcamera-hello
  1. 截至2022年9月中旬,Picamera2已预装在所有树莓派操作系统图像中。您可以通过完整的系统更新来更新,或通过终端:
sudo apt install -y python3-picamera2
  1. 对于树莓派OS用户,上面的下载将包含所有的X Windows和GUI依赖项,但这些将在树莓派OS Lite中被省略。如果OS Lite用户希望使用这些功能,他们应该运行:
sudo apt install -y python3-pyqt5 python3-opengl

preview windows预览窗口

四种预览窗口

  • QtGL
  • QT
  • DRM/KMS
  • NULL

窗口可以进行调整,可以进行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

GtGL preview【有 x windwows情况下 + 硬件加速】

  • 这个预览窗口使用Qt GUI工具包实现,并使用GLES硬件图形加速。当使用X Windows时,它是在屏幕上显示图像的最有效的方式,我们会在几乎所有的Picamera2库3.1中推荐它。预览窗口参数是指需要X Windows时的9种情况。
from picamera2 import Picamera2, Preview
picam2 = Picamera2()
picam2.start_preview(Preview.QTGL)

当图像需要显示在远程显示器上(未连接到Pi)时,不建议使用QtGL预览窗口

Qt preview【软件加速】

  • 与QtGL预览一样,这个窗口也使用Qt框架实现,但这次使用的是软件渲染,而不是3D硬件加速。因此,它在计算上是昂贵的,并且应该尽可能地避免使用

当使用VNC时:

  • 如果你还有一个显示器直接连接到树莓派,QtGL(硬件加速)窗口工作充分。
  • 如果你没有一个显示器直接连接到Pi,QtGL预览将工作得很差,此时应该使用Qt预览窗口
from picamera2 import Picamera2, Preview
picam2 = Picamera2()
picam2.start_preview(Preview.QT)

总之什么时候用呢:

  • Qt预览的主要用例是: 使用X转发或使用VNC远程桌面软件在另一台联网的计算机上显示预览窗口。在这些条件下,3d-硬件加速实现要么根本不工作,要么工作得不是很好。

DRM/KMS preview【没有 x windwows情况下】

  • 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上。

NULL preview

通常是预览窗口通过接收相机图像,将其传递给应用程序中间商 传递,用户不再需要它们时再回收这些缓冲区,从而驱动自由摄像头系统。其结果是,即使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)
  • 值得注意的是,如果您停止预览,然后没有重新启动另一个,或者没有立即启动另一个,就不会发生任何特别糟糕的情况。所有可用的缓冲区将被自由相机图像填充。但是没有预览运行,没有任何东西会读出这些图像并回收缓冲区,所以libcamera只会停止。当预览重新启动时,正常的操作将恢复,从那些仍在排队等待读取之前的的相机图像开始读取。
  • 许多程序员都会熟悉事件循环的概念。每种类型的预览窗口都实现了一个事件循环,以将帧从相机中pop出队列,因此当没有其他事件循环(如Qt提供的事件循环)运行时,NULL预览将执行此功能。

preview的一些其他特征

  1. 设置窗口title
from picamera2 import Picamera2
picam2 = Picamera2()
picam2.start(show_preview=True)
picam2.title_fields = ["ExposureTime", "AnalogueGain"]

配置camera

一旦创建了一个Picamera2对象,一般的模式是必须为相机生成一个配置,该配置必须应用于相机系统(使用Picamera2.configure方法),然后就可以启动相机系统。

  • [设置配置,应用配置,启动相机]
  • 一旦创建了一个配置对象,应用程序就可以在调用picam2.configure 之前自由地更改该对象的建议参数。配置只是Python字典,我们很容易检查它们并查看它们在说什么。
  1. Picamera2.create_preview_configuration将生成一个适合于在显示器上显示相机预览图像的配置,或在捕获静止图像之前
  2. Picamera2.create_still_configuration将生成一个适合捕获高分辨率静止图像的配置
  3. Picamera2.create_video_configuration将生成一个适合录制视频文件的配置

配置的细节

ISP二刀流 + 原始流 = 三刀流
注意每把刀都是不一样的! [不一样在于格式]
在这里插入图片描述
事件的顺序如下:

  1. 在左边是相机模块,它通过flat ribbon cable将图像传送到Pi。照相机提供的图像不是人类可以看到的图像,但需要做大量的工作来清理它们,并产生一幅真实的图像。
  2. Pi上一个称为CSI-2接收器的硬件将传入的相机图像传输到内存中。
  3. Pi有一个图像信号处理器(ISP),它可以从内存中读取该图像。它对从相机接收到的像素执行所有这些清洗和处理步骤。
  4. ISP可以为相机的每一个输入帧产生最多两个输出图像。我们将其中一个指定为主映像main image,它可以是RGB或YUV格式。
  5. 第二幅图像是一幅较低分辨率的图像,通常被称为 lore image;它必须是YUV格式的。它也必须不大于主图像。
  6. 最后,从传感器接收到并直接写入存储器的图像数据也可以发送到应用程序。这叫做原始图像–bayer 阵列图。
  7. 对于lores流,实际上只使用了“YUV420”。

因此,Picamera2的配置分为:

  • 全局适用于Picamera2系统和跨整个ISP的一般参数。
  • ISP中的每个流配置,以确定主流和循环流的输出格式和大小。我们注意到,主流总是被定义并交付给应用程序,如果应用程序没有显式地请求一个流,则使用默认值。
  • 此外,原始流与其他流有很大的不同,因为它影响了更直接地驱动图像传感器的模式,因此对此有一些单独的讨论。
  • 通常情况下,配置不包括可以在运行时更改的相机设置(如亮度或对比度)。但是,某些用例有时确实对这些某些控制值有特定的首选项,它们可以作为配置的一部分存储,以便应用配置也会自动应用运行时控件。

捕捉图像capture images

  • capture arrays
  • capture images
  • capture buffers

相机图像通常用numpy数组表示,所以熟悉numpy将会有所帮助。这也是OpenCV使用的表示,因此picamera2、numpy和OpenCV都可以无缝地一起工作。

当捕获图像时,Picamera2函数在其捕获函数中使用以下命名法:

  1. arrays:这些是像素的二维像素数组,通常是操作图像最方便的方法。它们通常是三维的numpy数组,因为每个像素都有几个颜色通道,从而增加了另一个维度。
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")
  1. images:这指的是Python PIL Image对象
from picamera2 import Picamera2
import time
picam2 = Picamera2()
picam2.start()
time.sleep(1)
image = picam2.capture_image("main")
  1. buffers:缓冲区我们只是指整个内存块图像存储为一维numpy数组,但二(或三维)数组形式通常是更有用的。

还有捕获功能,可以将图像直接保存到文件中,并在相机模式之间切换,从而将快速帧率预览与高分辨率捕获相结合。

那么如何进行切换?

切换模式

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')

捕获video

在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是用于处理图像和视频的编码器。以下是它们的详细介绍:

  1. JpegEncoder

    • 编码格式:JPEG。
    • 应用场景:适用于处理静态的JPEG图像,如照片或图像文件。它可以将捕获的图像编码为JPEG格式,以便保存和分享。
  2. MJpegEncoder

    • 编码格式:Motion JPEG。
    • 应用场景:适用于处理连续的JPEG图像序列,如网络摄像头或监控系统的实时视频流。它将连续的JPEG图像编码为视频流,常用于网络传输和实时查看。
  3. H264Encoder

    • 编码格式:H.264。
    • 特点:H.264是一种广泛使用的视频编码标准,提供了高效的视频压缩性能,适合处理高质量和高分辨率的视频。它在许多设备和播放器上都受到支持,并具有较小的文件大小。
    • 应用场景:适用于需要高质量和高压缩性能的视频录制和流媒体应用。它可以生成较小的视频文件,同时保持较高的图像质量。
  4. NullEncoder

    • 功能:NullEncoder实际上并不进行真正的编码操作,而是将输入数据直接复制到输出中。
    • 应用场景:适用于需要直接访问原始图像或视频数据的情况,如实时图像处理或视频流分析。通过将编码器设置为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()

选择建议:

  • 如果你需要处理静态的JPEG图像,选择JpegEncoder。
  • 如果你需要处理连续的JPEG图像序列或实时视频流,选择MJpegEncoder。
  • 如果你需要录制高质量和高压缩性能的视频,选择H264Encoder。
  • 如果你需要直接访问原始图像或视频数据进行实时处理或分析,选择NullEncoder。

输出object

输出对象直接从编码器接收编码的视频帧,并通常将它们转发到文件或网络套接字。输出对象通常由其构造函数生成,不过可以将一个简单的字符串传递给start_encoder和start_recording函数,这将导致自动生成FileOutput对象。

picamera2库中,输出对象用于指定视频录制或图像捕获的输出目标。以下是关于FileOutputFfmpegOutputCircularOutput的具体解释:

  1. 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)  
  1. FfmpegOutput

    • 功能:使用FFmpeg库将视频或图像数据进行编码并写入文件。
    • 应用场景:适用于需要将录制的视频转换为特定格式或进行进一步编码处理的情况。通过指定输出文件格式和编码器设置,FfmpegOutput可以使用FFmpeg库的功能对数据进行编码,并将编码后的数据写入指定的文件中。

输出类将编码的帧转发给FFmpeg进程。这为一些相当复杂的新输出类型打开了大门,包括MP4文件,甚至是音频,但可能需要关于FFmpeg本身的大量知识:

# 从picamera2.outputs模块导入FfmpegOutput类,这个类使用FFmpeg库将视频或图像数据进行编码并写入文件。  
from picamera2.outputs import FfmpegOutput  
# 创建一个FfmpegOutput对象,并指定输出文件名为'test.mp4',同时启用音频编码。这意味着视频和音频数据都将被编码并写入指定的文件。  
output = FfmpegOutput("test.mp4", audio=True)  
  1. 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()  # 停止记录输出。这将停止循环录制功能,并关闭输出文件。

无脑使用高level的api
在这里插入图片描述

有待更新。。。。

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 这是一个比较复杂的系统,需要涉及硬件和软件的开发,以下是一个简单的示例代码,仅供参考: 硬件部分: 1. 树莓派3B或3B+主板 2. 树莓派摄像头 3. 温湿度传感器 4. 烟雾传感器 5. 电机或执行器(用于控制仓库门) 软件部分: 1. Python 3.5或以上版本 2. OpenCV和NumPy库(用于图像处理) 3. Adafruit库(用于温湿度传感器) 4. RPi.GPIO库(用于控制电机) 代码实现: 1. 导入所需的库 ```python import cv2 import numpy as np from picamera.array import PiRGBArray from picamera import PiCamera from time import sleep import Adafruit_DHT import RPi.GPIO as GPIO ``` 2. 设置GPIO引脚 ```python GPIO.setmode(GPIO.BOARD) GPIO.setup(11, GPIO.OUT) #设置电机控制引脚为11号引脚 ``` 3. 初始化摄像头 ```python camera = PiCamera() camera.resolution = (640, 480) #设置摄像头分辨率为640x480 camera.framerate = 32 rawCapture = PiRGBArray(camera, size=(640, 480)) ``` 4. 初始化温湿度传感器 ```python DHT_SENSOR = Adafruit_DHT.DHT11 DHT_PIN = 4 ``` 5. 定义图像处理函数 ```python def process_image(image): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #将图像转换为灰度图像 blur = cv2.GaussianBlur(gray, (15, 15), 0) #高斯模糊 _, thresh = cv2.threshold(blur, 127, 255, cv2.THRESH_BINARY) #二值化 contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #查找轮廓 cnt = max(contours, key=cv2.contourArea) #找到最大轮廓 x, y, w, h = cv2.boundingRect(cnt) #计算轮廓的边界矩形 cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) #绘制矩形框 cv2.putText(image, "Grain", (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2) #标记谷粒 return image ``` 6. 启动摄像头并进行循环处理 ```python for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True): image = frame.array processed_image = process_image(image) cv2.imshow("Processed Image", processed_image) key = cv2.waitKey(1) & 0xFF rawCapture.truncate(0) if key == ord("q"): break ``` 7. 温湿度传感器读取函数 ```python def read_dht_sensor(): humidity, temperature = Adafruit_DHT.read(DHT_SENSOR, DHT_PIN) if humidity is not None and temperature is not None: return temperature, humidity else: return None, None ``` 8. 烟雾传感器检测函数 ```python def check_smoke(): #检测烟雾传感器状态 #如果检测到烟雾,返回True,否则返回False ``` 9. 控制电机函数 ```python def control_motor(state): #根据参数state的值控制电机 #如果state为True,打开仓库门;否则关闭仓库门 ``` 完整代码: ```python import cv2 import numpy as np from picamera.array import PiRGBArray from picamera import PiCamera from time import sleep import Adafruit_DHT import RPi.GPIO as GPIO GPIO.setmode(GPIO.BOARD) GPIO.setup(11, GPIO.OUT) camera = PiCamera() camera.resolution = (640, 480) camera.framerate = 32 rawCapture = PiRGBArray(camera, size=(640, 480)) DHT_SENSOR = Adafruit_DHT.DHT11 DHT_PIN = 4 def process_image(image): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (15, 15), 0) _, thresh = cv2.threshold(blur, 127, 255, cv2.THRESH_BINARY) contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cnt = max(contours, key=cv2.contourArea) x, y, w, h = cv2.boundingRect(cnt) cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.putText(image, "Grain", (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2) return image def read_dht_sensor(): humidity, temperature = Adafruit_DHT.read(DHT_SENSOR, DHT_PIN) if humidity is not None and temperature is not None: return temperature, humidity else: return None, None def check_smoke(): #检测烟雾传感器状态 #如果检测到烟雾,返回True,否则返回False pass def control_motor(state): #根据参数state的值控制电机 #如果state为True,打开仓库门;否则关闭仓库门 if state: GPIO.output(11, GPIO.HIGH) else: GPIO.output(11, GPIO.LOW) for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True): image = frame.array processed_image = process_image(image) cv2.imshow("Processed Image", processed_image) key = cv2.waitKey(1) & 0xFF rawCapture.truncate(0) if key == ord("q"): break temperature, humidity = read_dht_sensor() if temperature is not None and humidity is not None: print("Temperature={0:0.1f}*C Humidity={1:0.1f}%".format(temperature, humidity)) if check_smoke(): print("Smoke Detected!") control_motor(False) else: control_motor(True) GPIO.cleanup() cv2.destroyAllWindows() ``` ### 回答2: 基于树莓派摄像头的仓库谷物计量、仓库温湿度和烟雾检测系统的代码如下: ```python import RPi.GPIO as GPIO import Adafruit_DHT import time import picamera import datetime # 设置传感器引脚和型号 DHT_SENSOR_PIN = 14 DHT_SENSOR_MODEL = Adafruit_DHT.DHT11 # 设置烟雾传感器引脚 SMOKE_SENSOR_PIN = 18 # 设置树莓派摄像头和图像保存路径 CAMERA_RESOLUTION = (1024, 768) CAMERA_SAVE_PATH = '/home/pi/images/' # 初始化GPIO设置 GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) # 初始化传感器 def init_sensors(): return Adafruit_DHT.read_retry(DHT_SENSOR_MODEL, DHT_SENSOR_PIN) # 获取温湿度 def get_temperature_humidity(): humidity, temperature = init_sensors() if humidity is not None and temperature is not None: return temperature, humidity else: return False # 获取时间戳作为文件名 def get_timestamp(): return datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") # 拍照并保存图片 def capture_image(): with picamera.PiCamera() as camera: camera.resolution = CAMERA_RESOLUTION camera.capture(CAMERA_SAVE_PATH + 'image_' + get_timestamp() + '.jpg') # 初始化烟雾传感器GPIO def init_smoke_sensor(): GPIO.setup(SMOKE_SENSOR_PIN, GPIO.IN) # 检测烟雾 def check_smoke(): return GPIO.input(SMOKE_SENSOR_PIN) # 主程序入口 if __name__ == '__main__': try: while True: temperature, humidity = get_temperature_humidity() if temperature and humidity: print(f'Temperature: {temperature}°C, Humidity: {humidity}%') if check_smoke(): print('Smoke detected!') capture_image() time.sleep(1) except KeyboardInterrupt: GPIO.cleanup() ``` 此代码使用了Adafruit_DHT库来读取DHT11温湿度传感器的数值,并通过树莓派摄像头拍摄烟雾检测时的图片。代码中定义了初始化传感器、获取温湿度、获取时间戳、拍照保存、初始化烟雾传感器、检测烟雾等函数,同时在主程序入口通过循环实时读取温湿度和检测烟雾状态,并在控制台打印输出。程序支持使用Ctrl+C终止,并在终止时清理GPIO设置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万物琴弦光锥之外

给个0.1,恭喜老板发财

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值