树莓派Camera的使用
参考:
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.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()
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(5)
camera.capture(str(i) + ".jpg", resize=(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(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
进行视频录制
def record_video():
"""
录制视频
:return:
"""
with PiCamera() as camera:
camera.resolution = (320, 240)
camera.start_preview()
camera.start_recording('my.h264')
camera.wait_recording(10) #设置录制时间,当前录制 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
经常使用 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
调用摄像头
# -*- 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
重启,即可
流媒体播放器
尝试使用树莓派搭建流媒体服务器,试过rtsp-server、easydarwin、h5s
后来在网上看到可以使用nginx搭建流媒体服务器,就想着试试,经过调试,还真成功了,具体步骤见下面连接
https://www.cnblogs.com/qiantuo1234/p/6611845.html
感谢博主
这里记录下文中没有提到或讲的不详细的问题
1、nginx可以下载最新版,地址:http://nginx.org/download/
2、要先安装以下这些库,不然会配置或编译会报错
sudo apt-get install libpcre3 libpcre3-dev
sudo apt-get install openssl libssl-dev
sudo apt-get install zlib1g-dev
3、编译可能遇到的两个错误,这两个错误要修改两个文件,文件位置这里说明下
文件 ngx_http_streaming_module.c 在nginx_mod_h264_streaming-2.2.7/src文件夹中
删除Makefile文件中的 -Werror选项,Makefile文件在nginx-1.19.0/objs文件夹中,删除Makefile文件中CFLAGS后面的-Werror选项
4、nginx配置文件说明,连接文章中配置的安装目录为/usr/local/nginx-stream,因此nginx的配置文件也是要在这个目录中配置,位置/usr/local/nginx-stream/conf目录中nginx.conf文件中。
5、nginx中添加的代码说明,我直接使用博主的代码,运行未成功,我改为了以下代码,位置放在nginx.conf文件中的server段,于原有的location同级
location ~* .*.flv$ {
flv;
}
location ~* .*.mp4$ {
mp4;
}
6、启停nginx
sudo /usr/local/nginx-stream/sbin/nginx #启动nginx服务
sudo /usr/local/nginx-stream/sbin/nginx -s stop #停止nginx服务
- 原文作者:Binean
- 原文链接:https://bzhou830.github.io/post/20190104PiCamera/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。