3. 初级秘籍

这个秘籍很简单, 无论任何水平的 Python 程序员应该都能够毫无障碍地读懂. 如果你有代码增强或者功能添加方面的建议, 请随时联系我们.

注意
请不要将您自己写的代码命名成 picamera.py, 将名字命名成已经存在 Python 模块, 在该模块被使用时会造成一些错误 (Python 找模块时, 会先搜寻当前目录下的文件, 再搜寻其他目录).

3.1 捕获一张图片到文件

拍一张照片很简单, 你只需要将你要的照片名称传入 capture() 方法就行.

1
2
3
4
5
6
7
8
9
from time import sleep
from picamera import PiCamera

camera = PiCamera()
camera.resolution = (1024, 768)
camera.start_preview()
# 相机准备时间
sleep(2)
camera.capture('foo.jpg')

请注意, 当你用 picamera 打开一个文件时 (像上面一样), 文件将会被刷新和关闭. 所以当 capture() 方法返回时, 数据可以被其他进程访问1.

  1. 原文为 Note that files opened by picamera (as in the case above) will be flushed and closed so that when the capture() method returns, the data should be accessible to other processes. 不是很懂…

3.2 捕获一张图片到数据流

为类文件对象1 (例如 socket(), io.BytesIO 流, 一个现有的打开文件对象2, 等等) 捕获一张图片, 只需要给 capture() 传一个文件名参数即可3.

1
2
3
4
5
6
7
8
9
10
11
from io import BytesIO
from time import sleep
from picamera import PiCamera

# 创建一个内存流
my_stream = BytesIO()
camera = PiCamera()
camera.start_preview()
# 相机准备时间
sleep(2)
camera.capture(my_stream, 'jpeg')

上面情况中, 明确指定了文件格式, BytesIO 对象没有文件名, 所以相机无法自动识别应该使用哪种格式.

需要记住的一点是 (不像指定文件名), 当图像捕获完之后, 流并不会被自动关闭; Picamera 设定为:假如他没有打开流的话, 并不会去关闭它. 然而, 如果对象有 flush 方法, 当 capture 方法返回时会它被自动调用, 这可以确保一旦捕获返回, 其他进程可以访问这些数据, 尽管对象仍然需要被关闭:

1
2
3
4
5
6
7
8
9
10
11
from time import sleep
from picamera import PiCamera

# 明确地打开一个文件叫做 my_image.jpg
my_file = open('my_image.jpg', 'wb')
camera = PiCamera()
camera.start_preview()
sleep(2)
camera.capture(my_file)
# 在这里 my_file.flush()被调用, 但是打开的文件并没有被关闭
my_file.close()

注意, 在上面的情况下, 我们没有必要指定文件格式, 因为格式已经写在了 my_file 里面 (相机会在文件名中寻找文件格式). 就像用 Python 内建的文件流类 (像 BytesIO )一样, 你也可以创建自己的 自定义输出

  1. file-like object
  2. an existing open file object

3.3 捕获一张图片到 PIL Image

这是捕获一张图片到数据流的变体. 首先我们捕获一张图片到 BytesIO (Python 的内存文件流类). 然后我们从文件流起始位置开始把流读入到一个 PIL 图片文件对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from io import BytesIO
from time import sleep
from picamera import PiCamera
from PIL import Image

# Create the in-memory stream
stream = BytesIO()
camera = PiCamera()
camera.start_preview()
sleep(2)
camera.capture(stream, format='jpeg')
# 回到流的起始位置,所以我们才能读取整个流
stream.seek(0)
image = Image.open(stream)

3.4 调整捕获的图片的尺寸

有时, 特别是在对图像执行某种分析或处理的脚本中, 你可能需要一个比当前相机分辨率更小的图片. 尽管这些可以通过一些库像 PIL 或者 OpenCV, 但是用 cature()resize 参数在处理图片时对 GPU 的消耗要小的多:

1
2
3
4
5
6
7
8
9
from time import sleep
from picamera import PiCamera

camera = PiCamera()
camera.resolution = (1024, 768)
camera.start_preview()
# Camera warm-up time
sleep(2)
camera.capture('foo.jpg', resize=(320, 240))

使用 start_recording() 方法录制视频时,也可以指定 resize 参数.

3.5 调整相机参数

或许你需要一系列亮度, 对比度看起来差不多的图片 (举个例子, 在你需要拍一个时间段内的一系列图片时会很有用). 需要使用各种属性以便分析图片的一致性. 尤其是, 你需要确保相机的曝光时间, 白平衡, 和增益都是一致的:

  • 固定曝光时间, 调整 shutter_speed 参数到一个合理的值.
  • 调整 iso 到一个固定的值.
  • 固定曝光增益, 需要调整 analog_gaindigital_gain 到一个合理的值. 然后把 exposure_mode 参数设置为 off.
  • 固定白平衡, 设置 awb_modeoff , 然后设置 awb_gains 为一个 (红色, 蓝色) 的增益元组1.

可能很难去弄明白, 这些参数取什么值才是最合适的. 对 iso 来说, 一个简单的经验法则是, 白天 100-200 最合适, 如果光线比较暗的话, 400-800 可能会更好. 要确定 shutter_speed 的参数, 你可能要查询 exposure_speed 的参数. 对于曝光增益, 在 exposure_mode 设置为 ‘off’ 之前,只要设置 analog_gain 大于就行了. 最后,要确定awb_gains 的合理值,只需查询属性, 同时将 awb_mode 设置为 “off” 以外的其他值. 同样, 这将告诉您相机的白平衡增益, 由自动白平衡算法决定.

下面的脚本提供了一个简明的例子来配置这些设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from time import sleep
from picamera import PiCamera

camera = PiCamera(resolution=(1280, 720), framerate=30)
# 设置 ISO 为一个人合适的值
camera.iso = 100
# 等待增益控制自动设置 (Wait for the automatic gain control to settle)
sleep(2)
# 确定值
camera.shutter_speed = camera.exposure_speed
camera.exposure_mode = 'off'
g = camera.awb_gains
camera.awb_mode = 'off'
camera.awb_gains = g
# 最后根据这些设置, 拍几张照片吧..
camera.capture_sequence(['image%02d.jpg' % i for i in range(10)])