基于 Raspberry Pi 的 IoT 图像采集实战:在 IoT-For-Beginners 中使用 PiCamera 捕获水果质检图像
2026/9/16 15:42:12 网站建设 项目流程

基于 Raspberry Pi 的 IoT 图像采集实战:在 IoT-For-Beginners 中使用 PiCamera 捕获水果质检图像

【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners

本篇技术指南以开源课程项目 IoT-For-Beginners 中《从 IoT 设备检测水果质量》一课为背景,完整讲解如何为 Raspberry Pi 安装 Raspberry Pi Camera Module、解决 Raspberry Pi OS Bullseye 下 PiCamera 的兼容性问题,并通过 Python 编写采集程序,将水果图像捕获为 JPEG 二进制数据。读完本文后,你将掌握 MIPI-CSI 相机硬件的接线方法、旧版相机模式(legacy camera mode)的启用命令,以及基于BytesIO的内存图像捕获与落盘流程,为后续调用 Custom Vision 图像分类器打下基础。

硬件准备:Raspberry Pi Camera Module

本节课程为 Raspberry Pi 添加的传感器是官方 Raspberry Pi Camera Module。这颗摄像头专为 Raspberry Pi 设计,通过 Pi 主板上的专用 CSI(Camera Serial Interface)接口连接,而非 USB。

需要特别说明的是,该相机使用的 CSI 协议由 Mobile Industry Processor Interface Alliance(MIPI)联盟定义,称为MIPI-CSI(Camera Serial Interface),是专门用于传输图像的串行接口协议。与温湿度、光照等传感器输出单个数值不同,图像数据量要大得多,因此相机普遍通过 SPI、CSI 这类适合大数据量传输的协议与主控通信。

课程主文档 2-check-fruit-from-device 课程 README 中指出,相机传感器本质上是数字传感器,通常依赖通信库完成图像数据的传输。大多数相机传感器采用光电二极管阵列(Active-Pixel Sensor,最常见的是 CMOS 传感器),镜头将场景光线聚焦到传感器上,数百万个光电二极管把落在各自位置的光记录为像素数据。

相机物理连接:六步完成排线接线

Raspberry Pi 相机通过扁平排线(ribbon cable)连接到主板。以下是课程文档给出的完整连接步骤,全程要求Pi 处于关机状态

  1. 关闭 Raspberry Pi 电源
  2. 将排线接入相机模块:轻轻拉动相机卡座上黑色塑料卡扣使其略微弹出,将排线插入插槽——蓝色一面朝向远离镜头方向,金属引脚朝向镜头方向。排线完全插入后,将黑色卡扣推回原位。官方还提供了演示动画,位于 Raspberry Pi "Getting Started with the Camera module" 文档中。
  3. 取下 Grove Base Hat(扩展板),以便腾出操作空间。
  4. 将排线穿过 Grove Base Hat 上的相机开孔,注意排线蓝色一面要朝向标记为A0、A1等的模拟端口方向。
  5. 将排线插入 Pi 主板的相机端口:再次拉起黑色卡扣,插入排线后推回卡扣。此时排线蓝色一面应朝向 USB 与以太网端口。

  1. 重新装回 Grove Base Hat

接线完成后,相机即通过 CSI 接口与 Raspberry Pi 建立硬件连接,接下来进入软件配置与编程环节。

启用旧版相机模式:适配 Raspberry Pi OS Bullseye

这是本课程文档重点强调的关键兼容性步骤。随着 Raspberry Pi OS Bullseye 的发布,系统自带的相机软件栈发生了变更,导致 Python 库 PiCamera默认无法工作。虽然官方正在开发替代方案 PiCamera2,但截至本文档编写时该库尚不可用。因此,当前可行的方案是:

  • 将 Pi 切换到legacy camera mode(旧版相机模式),使 PiCamera 正常工作;
  • 相机 CSI 端口默认是被禁用的,而启用旧版相机软件会自动同时启用该端口

操作步骤如下:

  1. 启动 Raspberry Pi 并等待系统完全启动。
  2. 启动 VS Code(可直接在 Pi 上运行,也可通过 Remote SSH 扩展远程连接)。
  3. 在终端中执行以下两条命令:
sudo raspi-config nonint do_legacy 0 sudo reboot

第一条命令通过raspi-config的非交互式接口(nonint)将 legacy camera 设置切换为启用(参数0),第二条命令重启 Pi 使配置生效。

  1. 等待 Pi 重启完成后,重新启动 VS Code,继续后续编程。

编写相机采集程序

安装 PiCamera 库

在终端中为pi用户的家目录创建项目文件夹fruit-quality-detector,并在其中创建app.py文件。然后用 pip 安装 PiCamera Python 库:

pip3 install picamera

导入依赖

app.py顶部添加如下导入:

import io import time from picamera import PiCamera
  • io:用于创建内存二进制缓冲对象BytesIO
  • time:用于在相机启动期间休眠等待;
  • PiCamera:PiCamera 库的相机操作类。

初始化相机

在导入语句下方添加相机初始化代码:

camera = PiCamera() camera.resolution = (640, 480) camera.rotation = 0 time.sleep(2)

这段代码逐行解释如下:

  • camera = PiCamera():创建 PiCamera 对象;
  • camera.resolution = (640, 480):将采集分辨率设为 640×480。虽然该相机硬件支持最高3280×2464的分辨率,但本项目后续使用的图像分类器输入尺寸很小(227×227),因此完全没有必要采集并传输更大的图像,640×480 已能提供足够细节且显著降低传输开销;
  • camera.rotation = 0:设置图像旋转角度。排线默认从相机底部进入,但若你为了对准待分类物体而旋转了相机(例如将相机倒挂在物体上方),可把该值改为所需旋转度数;
  • time.sleep(2):相机启动需要数秒,此休眠确保初始化完成后再采集。

例如,若把排线悬挂在物体上方、使排线位于相机顶部(即相机倒置),则应设为:

camera.rotation = 180

捕获图像为二进制数据

下面这段代码把相机读取到的 JPEG 数据存入内存对象:

image = io.BytesIO() camera.capture(image, 'jpeg') image.seek(0)
  • io.BytesIO():创建一个内存字节缓冲对象,用于承载二进制数据;
  • camera.capture(image, 'jpeg'):将相机当前画面以 JPEG 格式写入该缓冲对象;
  • image.seek(0)BytesIO内部带有一个位置指针(position indicator),记录当前读写位置,capture写入后指针位于数据末尾,seek(0)将指针移回开头,以便后续一次性读取全部数据。

将图像保存到文件

with open('image.jpg', 'wb') as image_file: image_file.write(image.read())

这段代码以二进制写模式('wb')打开image.jpg,把BytesIO中的全部数据读出并写入文件。使用with语句可确保文件正确关闭。

💁 提示:PiCamera 也支持直接把文件名传给camera.capture,将图像直接写入文件而不经过BytesIO。此处特意选用BytesIO的原因在于——本节课稍后的环节中,需要把这张图像直接发送给图像分类器,内存缓冲对象便于直接作为请求体传递。

运行验证

将相机对准某个物体并运行代码(python3 app.py)。程序执行后,当前目录下会生成image.jpg。在 VS Code 资源管理器中选中该文件即可预览图像。若图像方向不对,调整camera.rotation = 0的数值后重新拍摄即可。

完整可运行代码与源码对照

把上述代码段拼接起来,即得到完整的采集程序:

import io import time from picamera import PiCamera camera = PiCamera() camera.resolution = (640, 480) camera.rotation = 0 time.sleep(2) image = io.BytesIO() camera.capture(image, 'jpeg') image.seek(0) with open('image.jpg', 'wb') as image_file: image_file.write(image.read())

课程文档明确指出,这段完整代码已收录在本仓库的 code-camera/pi/fruit-quality-detector/app.py 中,与你手动编写的版本逐行一致,可直接作为对照或直接运行。

从图像采集到图像分类的衔接

完成图像采集后,本课的后半部分将图像发送给 Custom Vision 分类器。仓库中的 code-classify/pi/fruit-quality-detector/app.py 展示了完整的演进代码——在采集逻辑不变的基础上追加了:

from azure.cognitiveservices.vision.customvision.prediction import CustomVisionPredictionClient from msrest.authentication import ApiKeyCredentials

以及从预测 URL 中拆解出endpointproject_iditeration_name,再调用predictor.classify_image(project_id, iteration_name, image)完成分类、遍历输出各标签概率的流程。可以看到,BytesIO缓冲对象在此处被image.seek(0)重置指针后直接作为classify_image的输入,这正是上文强调"捕获进内存而非直接写文件"的原因所在。

更详细的云端配置(发布迭代、获取 Prediction URL 与 Prediction-Key)参见课程主文档 4-manufacturing/lessons/2-check-fruit-from-device/README.md,Raspberry Pi / 虚拟设备端分类调用完整步骤见 single-board-computer-classify-image.md。课程还建议:若使用设备相机采集的图像与训练图像差异明显(如分辨率、清晰度、色彩不同),应在 Custom Vision 中用设备拍摄的预测图像重新训练模型,以获得更准确的分类结果。

小结

通过本节课程,你完成了 Raspberry Pi 相机硬件接线、Bullseye 系统下的旧版相机模式启用,以及基于 PiCamera 的图像采集程序编写。整个过程的关键要点包括:CSI 端口默认禁用需通过 legacy camera 设置一并开启;采集分辨率应匹配分类器输入尺寸(227×227),640×480 已足够;使用BytesIO而非直接写文件,是为后续将图像交给云端分类器做准备。至此,"编程相机"环节顺利完成,接下来即可进入将采集图像发送至 Custom Vision 进行水果成熟度分类的实战环节。

【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询