K230基础-摄像头的使用
第十二章 摄像头的使用-K230图像采集与视觉应用实战
🎯 本章目标:
掌握 K230 上摄像头(Camera)的完整使用流程,学会通过 MicroPython(CanMV 风格)进行图像采集、参数配置、图像保存与显示、AI 推理集成,实现从“看到”到“理解”的完整视觉链路。
1. 开发准备:硬件与固件
1.1 硬件要求
- K230 开发板(如 CanMV-K230)
- 摄像头模组:推荐 OV2640(DVP 接口,支持 JPEG/RGB)
- 连接线:FPC 排线或 24Pin DVP 接口线
- 可选外设:
- TFT LCD 屏(用于本地显示)
- SD 卡(用于图像存储)
- 串口/网络模块(用于图像传输)
✅ 接线确认:
- 摄像头正确插入 DVP 接口
- 无反插、松动
1.2 固件要求
确保使用支持摄像头的 CanMV 官方固件(非标准 MicroPython):
- 固件包含
sensor
、image
、lcd
等专用模块 - 支持 OV2640、GC0308 等常见模组
- 可通过
kflash
工具烧录
2. 摄像头初始化与配置
2.1 导入模块
import sensorimport imageimport time
2.2 基础初始化流程
# === 1. 复位摄像头 ===
try:sensor.reset()print("✅ 摄像头复位成功")
except Exception as e:print("❌ 摄像头未检测到:", e)raise# === 2. 设置像素格式 ===
sensor.set_pixformat(sensor.RGB565) # 或 sensor.GRAYSCALE, sensor.JPEG
print("像素格式:", sensor.pixformat())# === 3. 设置分辨率 ===
sensor.set_framesize(sensor.QVGA) # 320x240
# 可选: QQVGA, QVGA, VGA, SVGA, XGA, HD
print("分辨率:", sensor.framesize())# === 4. 跳过前几帧(等待稳定)===
sensor.skip_frames(time=2000) # 等待2秒
print("摄像头初始化完成")
✅ 输出示例:
✅ 摄像头复位成功 像素格式: 1 分辨率: 320x240 摄像头初始化完成
3. 图像采集与处理
3.1 拍摄单帧图像
img = sensor.snapshot()
print(f"图像大小: {img.width()}x{img.height()}")
img
是一个image.Image
对象,支持多种操作。
3.2 图像属性查询
方法 | 说明 |
---|---|
img.width() | 图像宽度 |
img.height() | 图像高度 |
img.size() | 图像字节大小(如 153600) |
img.format() | 格式(RGB565=1, JPEG=2, etc) |
3.3 基础图像处理操作
# 转灰度(仅对 RGB 图像有效)
img.to_grayscale()# 转 RGB(灰度 → RGB)
img.to_rgb565()# 图像旋转(0, 90, 180, 270)
img.rotation_corr(corners=(0, 0, 320, 240), x_translation=0, y_translation=0, zoom=1.0, theta=90)# 图像二值化
img.binary([(threshold, 255)])# 寻找边缘
img.find_edges(image.EDGE_CANNY, threshold=(50, 80))# 画图形
img.draw_rectangle(100, 80, 120, 60, color=(255, 0, 0)) # 红框
img.draw_cross(160, 120, color=(0, 255, 0)) # 绿十字
4. 实战项目一:实时图像采集与信息打印
import sensor
import timesensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=2000)clock = time.clock() # FPS 计算while True:clock.tick()img = sensor.snapshot()# 打印帧信息fps = clock.fps()size_kb = img.size() / 1024print(f"帧: {img.width()}x{img.height()}, 大小: {size_kb:.1f}KB, FPS: {fps:.1f}")time.sleep_ms(100)
📊 输出示例:
帧: 320x240, 大小: 150.0KB, FPS: 15.2 帧: 320x240, 大小: 150.0KB, FPS: 15.1
5. 实战项目二:图像保存到 SD 卡
5.1 挂载 SD 卡(见 SPI 章节)
import os
import sdcard# 初始化 SPI 和 CS(假设已定义)
sd = sdcard.SDCard(spi, cs)
os.mount(sd, "/sd")
5.2 保存图像(JPEG 格式推荐)
import sensor
import image
import time
import os# 初始化摄像头
sensor.reset()
sensor.set_pixformat(sensor.JPEG) # 使用 JPEG 减小体积
sensor.set_framesize(sensor.SVGA) # 800x600
sensor.skip_frames(time=2000)counter = 0
while True:img = sensor.snapshot()# 文件名filename = f"/sd/capture_{counter:04d}.jpg"# 保存img.save(filename, quality=95)print(f"✅ 保存图像: {filename}, 大小: {os.stat(filename)[6]} bytes")counter += 1time.sleep(5) # 每5秒拍一张
✅ 优势:JPEG 格式可将 800x600 图像压缩至 ~50KB
6. 实战项目三:图像显示到 TFT LCD
6.1 初始化 LCD(使用 st7789)
from machine import SPI, Pin
import st7789# SPI 和引脚配置(见 SPI 章节)
spi = SPI(SPI.SPI1, baudrate=40_000_000, polarity=0, phase=0)
cs = Pin(CS_PIN, Pin.OUT, value=1)
dc = Pin(DC_PIN, Pin.OUT, value=0)
rst = Pin(RST_PIN, Pin.OUT, value=1)lcd = st7789.ST7789(spi, 240, 240, reset=rst, dc=dc, cs=cs, rotation=0)
lcd.fill(0) # 清屏
6.2 实时显示摄像头画面(缩放)
import sensor
import timesensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA) # 320x240
sensor.skip_frames(time=2000)while True:img = sensor.snapshot()# 缩放图像以适应 240x240 屏幕img.resize(240, 240)# 转为 RGB565 数组并显示lcd.blit_buffer(img.bytearray(), 0, 0, 240, 240, st7789.RGB565)
✅ 效果:实现“电子眼”实时监控显示。
7. 实战项目四:摄像头 + AI 推理(人脸检测)
7.1 加载人脸检测模型
import KPU as kpu# 加载模型(需提前烧录到开发板)
model = kpu.load(0x300000) # 模型在 Flash 的地址
# 或从文件加载(如果支持):
# model = kpu.load("/sd/face_detect.kmodel")# 设置输入参数
kpu.set_outputs(model, 0, 1, 1, 2) # (layer_idx, H, W, channels)
7.2 人脸检测主循环
import sensor
import image
import timesensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=2000)clock = time.clock()while True:clock.tick()# 拍摄图像img = sensor.snapshot()# AI 推理fmap = kpu.run_with_output(model, img)# 解析结果plist = kpu.fmap_to_list(fmap)if plist:for res in plist:# res: [x, y, w, h, confidence]x, y, w, h = int(res[0]), int(res[1]), int(res[2]), int(res[3])img.draw_rectangle(x, y, w, h, color=(255, 0, 0), thickness=2)img.draw_string(x, y-10, f"Face: {res[4]:.2f}", color=(0, 255, 0))# 可选:显示到 LCD 或通过串口发送fps = clock.fps()img.draw_string(10, 10, f"FPS: {fps:.1f}", color=(255, 255, 255))print(f"检测到 {len(plist)} 个人脸, FPS: {fps:.1f}")
✅ 输出:在图像上画出人脸框和置信度。
8. 高级技巧与优化
8.1 使用 JPEG 模式降低带宽
sensor.set_pixformat(sensor.JPEG)
sensor.set_framesize(sensor.VGA) # 640x480 JPEG 图像仅 ~30KB
适合:
- 低带宽传输
- 大容量存储
- 远程监控
8.2 自动调节图像参数
sensor.set_auto_gain(False) # 关闭自动增益
sensor.set_auto_whitebal(False) # 关闭自动白平衡
sensor.set_brightness(0) # -2~2
sensor.set_contrast(1) # -2~2
sensor.set_saturation(1) # -2~2
✅ 用途:在固定光照环境下优化图像质量。
8.3 定时拍照任务
结合 Timer
实现精准周期拍照:
from machine import Timerdef take_photo(_):img = sensor.snapshot()img.save(f"/sd/photo_{utime.time()}.jpg")Timer(Timer.TIMER0, Timer.CHANNEL0,mode=Timer.MODE_PERIODIC,period=60_000, # 每分钟拍一张callback=take_photo)
9. 常见问题与调试
❌ 问题1:sensor.reset()
超时或失败
排查:
- 摄像头是否支持(OV2640 最稳定)
- DVP 接口是否接触良好
- 固件是否为 CanMV 版本
❌ 问题2:图像花屏、颜色错乱
解决:
- 检查 DVP 数据线顺序
- 降低分辨率测试
- 检查
set_pixformat()
是否匹配
❌ 问题3:AI 推理卡顿
优化:
- 使用
QQVGA
(160x120)输入- 使用 JPEG 格式
- 减少推理频率(如每2秒一次)
10. 性能与限制
参数 | K230 实测性能 |
---|---|
最高分辨率 | VGA(640x480)@15fps |
JPEG 模式 | 支持,大幅降低数据量 |
图像处理 | 支持缩放、滤波、绘图 |
AI 推理输入 | 推荐 QQVGA/QVGA |
内存占用 | QVGA RGB565 ≈ 150KB |
✅ 本章你已掌握:
- 摄像头初始化与参数配置
- 图像采集、处理与显示
- 图像保存到 SD 卡
- 摄像头 + AI 人脸检测实战
- 常见问题排查与优化
🚀 结语:
你已具备使用 K230 构建完整视觉系统的全部能力!可扩展至 物体识别、二维码识别、图像分类、智能监控 等 AIoT 应用。