树莓派(Raspberry Pi)中PiCamera+OpenCV的使用
参考:
Raspberry Pi:https://www.raspberrypi.org/
Index of Packages:https://pypi.python.org/pypi/picamera
最新版本是 picamera 1.13
:http://picamera.readthedocs.io/en/release-1.13/
主要内容
- 简单测试相机模块是否可以使用
- 使用
picamera
进行图像拍摄 capture
和capture_continuous
介绍- 使用
picamera
进行视频录制 picamera + OpenCV
OpenCV
无法操作树莓派原装摄像头解决方法
简单测试相机模块是否可以使用
使用命令 raspistill
可以测试树莓派相机模块,最简单的语句如下:
raspistill -o te.jpg
功能:打开摄像头预览,几秒后拍摄一张照片
使用 picamera
进行图像拍摄
picamera
进行图像拍摄
使用 picamera
之前注意不要把文件名保存为 picamera.py
When trying out these scripts do not name your file picamera.py.
Naming scripts after existing Python modules will cause errors when you try and import those modules
(because Python checks the current directory before checking other paths).
打开摄像头进行预览
代码:
# -*- coding: utf-8 -*-
from time import sleep
from picamera import PiCamera
def open_preview():
with PiCamera() as camera:
camera.resolution = (320, 240)
camera.start_preview()
sleep(5)
if __name__ == '__main__':
open_preview()
函数 open_preview()
用于打开摄像头进行预览
首先,获取一个 PiCamera
对象:
with PiCamera() as camera:
可以设置摄像头的分辨率,当前设为宽 320
,高 240
:
camera.resolution = (320, 240)
打开摄像头进行预览:
camera.start_preview()
暂停 5
秒,即预览 5
秒:
sleep(5)
Note: 当结束摄像头操作后,务必确保调用 close
方法结束,有两种函数结构
camera = PiCamera()
try:
# do something with the camera
pass
finally:
camera.close()
或者
with PiCamera() as camera:
# do something with the camera
pass
否则,有可能下次会无法打开,出现以下问题:
mmal: mmal_vc_component_enable: failed to enable component: ENOSPC
mmal: camera component couldn't be enabled
mmal: main: Failed to create camera component
mmal: Failed to run camera app. Please check for firmware updates
此为个人推测,摄像头并没有及时关闭导致(可通过相机模块的红灯判断摄像头是否开启)
对摄像头有一些常用的操作,比如设置分辨率,帧率,是否左右翻转,上下翻转:
def open_preview2():
with PiCamera() as camera:
camera.resolution = (320, 240)
camera.framerate = 24
camera.hflip = True
camera.vflip = True
camera.start_preview()
sleep(5)
使用 picamera
还可以进行更多复杂功能的设置,比如设定摄像头的 ISO
,曝光时间,亮度,对比度等等,可查看文档
拍摄图像
在预览的过程中可以将图片保存下来,函数实现如下:
def capture_preview():
with PiCamera() as camera:
camera.resolution = (320, 240)
camera.start_preview()
for i in range(5):
sleep(i)
camera.capture(str(i) + ".jpg", resize=(80, 60))
函数 capture_preview()
仅比 open_preview()
多了一条捕获图像函数:
camera.capture(str(i) + ".jpg")
还可以在捕获图像的时候进行图像缩放:
camera.capture("te.jpg", resize=(80, 60))
函数功能:捕获图像,命名为 te.jpg
,同时缩放至宽 80
,高 60
Note:当获取到 PiCamera()
对象后,就已经打开摄像头了,所以并不一定需要调用 camera.start_preview()
进行预览后才能保存图像
def capture_preview2():
"""
打开摄像头,5秒后捕获一张图像
:return:
"""
with PiCamera() as camera:
camera.resolution = (320, 240)
sleep(5)
camera.capture("no_preview.jpg")
capture
和 capture_continuous
介绍
capture
和 capture_continuous
介绍
函数 capture
原型:
capture(output, format=None, use_video_port=False, resize=None, splitter_port=0, bayer=False, **options)
源码:capture
功能:从摄像头中捕获图像,保存在 output
关键参数介绍:
output
- 输出,如果为字符串,则作为文件名使用,比如te.jpg
,te2.png
等;如果不是字符串,那么必须是一个可读对象format
- 保存图像格式,默认为空,不为空,可使用以下格式:
函数 capture
支持图像格式如下:
'jpeg' - Write a JPEG file
'png' - Write a PNG file
'gif' - Write a GIF file
'bmp' - Write a Windows bitmap file
'yuv' - Write the raw image data to a file in YUV420 format
'rgb' - Write the raw image data to a file in 24-bit RGB format
'rgba' - Write the raw image data to a file in 32-bit RGBA format
'bgr' - Write the raw image data to a file in 24-bit BGR format
'bgra' - Write the raw image data to a file in 32-bit BGRA format
'raw' - Deprecated option for raw captures; the format is taken from the deprecated raw_format attribute
Note:当 output
指定图像格式后,如果 format
设置格式与其不一致,无法得到正常图像
use_video_port
- 使用摄像头的图像或者视频端口进行图像捕获,默认为False
,表示使用图像端口。图像端口捕获速度慢(打开预览可知,捕获时会出现停顿现象),但是图像质量高;如果想要快速的捕获图像,使用视频端口,那么设为True
如果想要不断捕获图像进行处理,使用图像端口如下:
# -*- coding: utf-8 -*-
from time import sleep
from picamera import PiCamera
def capture_images():
"""
不断捕获图像
:return:
"""
with PiCamera() as camera:
camera.resolution = (320, 240)
sleep(2)
num = 0
while True:
camera.capture(str(num) + ".jpg")
print num
num += 1
if __name__ == '__main__':
capture_images()
想要速度更快,可以使用视频端口进行
camera.capture(str(num) + ".jpg", use_video_port=True)
picamera
也提供了一个不断捕获图像的函数 capture_continuous
函数原型:
capture_continuous(output, format=None, use_video_port=False, resize=None, splitter_port=0, burst=False, bayer=False, **options)
功能:不断从相机中捕获图像,该函数返回一个无穷迭代器。
参数 output
- 如果是字符串,函数设定了两个替代项用于保存不同图像
- {counter} - a simple incrementor that starts at 1 and increases by 1 for each image taken
- {timestamp} - a datetime instance
使用方法比如:image{counter}.jpg
,image{counter:02d}.jpg
,image{timestamp}.jpg
具体可查看文档
示例函数:
import time
import picamera
with picamera.PiCamera() as camera:
camera.start_preview()
try:
for i, filename in enumerate(
camera.capture_continuous('image{counter:02d}.jpg')):
print(filename)
time.sleep(1)
if i == 59:
break
finally:
camera.stop_preview()
其他参数同 capture
一致
使用 picamera
进行视频录制
picamera
进行视频录制
def record_video():
"""
录制视频
:return:
"""
with PiCamera() as camera:
camera.resolution = (320, 240)
camera.start_preview()
camera.start_recording('my.h264')
camera.wait_recording(10)
camera.stop_recording()
函数 record_video
进行视频录制
首先获取 PiCamera
对象:
with PiCamera() as camera:
可以设置分辨率,当前设为 (320, 240)
camera.resolution = (320, 240)
打开预览,便于视频录制:
camera.start_preview()
开始录制,录制内容保存为 my.h264
:
camera.start_recording('my.h264')
设置录制时间,当前录制 10
秒视频:
camera.wait_recording(10)
关闭摄像头,结束录制:
camera.stop_recording()
函数 start_recording
支持视频格式如下:
'h264' - Write an H.264 video stream
'mjpeg' - Write an M-JPEG video stream
'yuv' - Write the raw video data to a file in YUV420 format
'rgb' - Write the raw video data to a file in 24-bit RGB format
'rgba' - Write the raw video data to a file in 32-bit RGBA format
'bgr' - Write the raw video data to a file in 24-bit BGR format
'bgra' - Write the raw video data to a file in 32-bit BGRA format
Note:函数 start_preview
同样也不是必须的
picamera + OpenCV
picamera + OpenCV
经常使用 OpenCV
进行图像处理,需要 picamera
得到的图像转换为 OpenCV
能够处理的 numpy array
格式
捕获图像并显示:
# -*- coding: utf-8 -*-
import time
import picamera
import numpy as np
import cv2
with picamera.PiCamera() as camera:
camera.resolution = (320, 240)
camera.framerate = 24
time.sleep(2)
image = np.empty((240 * 320 * 3,), dtype=np.uint8)
camera.capture(image, 'bgr')
image = image.reshape((240, 320, 3))
cv2.imshow("img", image)
cv2.waitKey(0)
使用视频端口(use_video_port=True
)就无法捕获图像了,没搞懂
视频流:
# -*- coding: utf-8 -*-
import time
import picamera
import numpy as np
import cv2
with picamera.PiCamera() as camera:
camera.resolution = (320, 240)
camera.framerate = 24
time.sleep(2)
while True:
image = np.empty((240 * 320 * 3,), dtype=np.uint8)
camera.capture(image, format='bgr')
image = image.reshape((240, 320, 3))
cv2.imshow("img", image)
cv2.waitKey(1)
上面这个效果不佳,使用 capture_continuous
:
# -*- coding: utf-8 -*-
import io
from time import sleep
import picamera
import numpy as np
import cv2
with picamera.PiCamera() as camera:
camera.resolution = (320, 240)
sleep(1)
stream = io.BytesIO()
for foo in camera.capture_continuous(stream, format='jpeg', use_video_port=True):
data = np.fromstring(stream.getvalue(), dtype=np.uint8)
image = cv2.imdecode(data, cv2.CV_LOAD_IMAGE_UNCHANGED)
cv2.imshow("img", image)
cv2.waitKey(1)
# Truncate the stream to the current position (in case
# prior iterations output a longer image)
stream.truncate()
stream.seek(0)
picamera
也提供了 PIRGBArray
对象,用来保存 RGB
图像
类原型:
class picamera.array.PiRGBArray(camera, size=None)
源码:PIRGBArray
捕获单张:
# -*- coding: utf-8 -*-
import picamera
import picamera.array
with picamera.PiCamera() as camera:
with picamera.array.PiRGBArray(camera) as output:
camera.capture(output, 'rgb')
print('Captured %dx%d image' % (
output.array.shape[1], output.array.shape[0]))
print type(output.array)
得到的 output.array
就是 numpy.ndarray
类型,可直接用于 opencv
处理
不过 opencv
中图像格式是 bgr
,所以还需要进行转换:
dst = cv2.cvtColor(output.array, cv2.COLOR_RGB2BGR)
Note:在 capture
函数中设置图像格式为 bgr
没有作用
如果想要重复使用 output
,需要在下次捕获前使用函数 truncate(0)
:
# -*- coding: utf-8 -*-
import picamera
import picamera.array
with picamera.PiCamera() as camera:
with picamera.array.PiRGBArray(camera) as output:
camera.resolution = (1280, 720)
camera.capture(output, 'rgb')
print('Captured %dx%d image' % (
output.array.shape[1], output.array.shape[0]))
output.truncate(0)
camera.resolution = (640, 480)
camera.capture(output, 'rgb')
print('Captured %dx%d image' % (
output.array.shape[1], output.array.shape[0]))
完整代码如下:
# -*- coding: utf-8 -*-
import picamera
import picamera.array
import cv2
from time import sleep
with picamera.PiCamera() as camera:
camera.resolution = (320, 240)
sleep(1)
with picamera.array.PiRGBArray(camera) as output:
# camera.capture(output, 'rgb', use_video_port=True)
for foo in camera.capture_continuous(output, 'rgb', use_video_port=True):
print('Captured %dx%d image' % (
output.array.shape[1], output.array.shape[0]))
dst = cv2.cvtColor(output.array, cv2.COLOR_RGB2BGR)
cv2.imshow("img", dst)
cv2.waitKey(1)
output.truncate(0)
OpenCV
无法操作树莓派原装摄像头解决方法
OpenCV
无法操作树莓派原装摄像头解决方法
可以直接使用 opencv
调用摄像头
# -*- coding: utf-8 -*-
import cv2
cap = cv2.VideoCapture(0)
# cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 320)
# cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 240)
while True:
# get a frame
ret, frame = cap.read()
print "frame.shape: {}".format(frame.shape)
# show a frame
cv2.imshow("capture", frame)
cv2.waitKey(1)
但可能会出现无法打开摄像头,原因:树莓派摄像头模块没有video0
解决方法:
cd /etc/modules-load.d/
sudo vim modules.conf
加入 bcm2835-v4l2
重启,即可