0. 功能实现

准备做一个摄像头定时拍照的程序,当一个监控,如果选择录像,会占用大量的存储空间,循环存储也存不了太久。

拍照可以节省空间,16G能循环半个月,一直拍照会有大量重复的照片,不好找关键照片,而且也会加大存储了。

因此使用python编写根据画面变化定时拍照程序

1. 准备

准备一个带CSI接口的树莓派摄像头,与树莓派连接,并启用摄像头

#启用摄像头
sudo raspi-config
#选择 interface ... camera ... enable ... yes#测试
raspistill -o image.jpg

2. 代码

#!/usr/bin/pythonimport StringIO
import subprocess
import os
import time
from datetime import datetime
from PIL import Image# Motion detection settings:
# Threshold          - how much a pixel has to change by to be marked as "changed"
# Sensitivity        - how many changed pixels before capturing an image, needs to be higher if noisy view
# ForceCapture       - whether to force an image to be captured every forceCaptureTime seconds, values True or False
# filepath           - location of folder to save photos
# filenamePrefix     - string that prefixes the file name for easier identification of files.
# diskSpaceToReserve - Delete oldest images to avoid filling disk. How much byte to keep free on disk.
# cameraSettings     - "" = no extra settings; "-hf" = Set horizontal flip of image; "-vf" = Set vertical flip; "-hf -vf" = both horizontal and vertical flip
threshold = 10
sensitivity = 20
forceCapture = True
forceCaptureTime = 60 * 60 # Once an hour
filepath = "/home/pi/picam"
filenamePrefix = "capture"
diskSpaceToReserve = 256 * 1024 * 1024 # Keep 40 mb free on disk
cameraSettings = ""# settings of the photos to save
saveWidth   = 1600
saveHeight  = 1200
saveQuality = 75 # Set jpeg quality (0 to 100)# Test-Image settings
testWidth = 100
testHeight = 75# this is the default setting, if the whole image should be scanned for changed pixel
testAreaCount = 1
testBorders = [ [[1,testWidth],[1,testHeight]] ]  # [ [[start pixel on left side,end pixel on right side],[start pixel on top side,stop pixel on bottom side]] ]
# testBorders are NOT zero-based, the first pixel is 1 and the last pixel is testWith or testHeight# with "testBorders", you can define areas, where the script should scan for changed pixel
# for example, if your picture looks like this:
#
#     ....XXXX
#     ........
#     ........
#
# "." is a street or a house, "X" are trees which move arround like crazy when the wind is blowing
# because of the wind in the trees, there will be taken photos all the time. to prevent this, your setting might look like this:# testAreaCount = 2
# testBorders = [ [[1,50],[1,75]], [[51,100],[26,75]] ] # area y=1 to 25 not scanned in x=51 to 100# even more complex example
# testAreaCount = 4
# testBorders = [ [[1,39],[1,75]], [[40,67],[43,75]], [[68,85],[48,75]], [[86,100],[41,75]] ]# in debug mode, a file debug.bmp is written to disk with marked changed pixel an with marked border of scan-area
# debug mode should only be turned on while testing the parameters above
debugMode = False # False or True# Capture a small test image (for motion detection)
def captureTestImage(settings, width, height):command = "raspistill %s -w %s -h %s -t 500 -e bmp -n -o -" % (settings, width, height)imageData = StringIO.StringIO()imageData.write(subprocess.check_output(command, shell=True))imageData.seek(0)im = Image.open(imageData)buffer = im.load()imageData.close()return im, buffer# Save a full size image to disk
def saveImage(settings, width, height, quality, diskSpaceToReserve):keepDiskSpaceFree(diskSpaceToReserve)time = datetime.now()filename = filepath + "/" + filenamePrefix + "-%04d%02d%02d-%02d%02d%02d.jpg" % (time.year, time.month, time.day, time.hour, time.minute, time.second)subprocess.call("raspistill %s -w %s -h %s -t 1000 -e jpg -q %s -n -o %s" % (settings, width, height, quality, filename), shell=True)print "Captured %s" % filename# Keep free space above given level
def keepDiskSpaceFree(bytesToReserve):if (getFreeSpace() < bytesToReserve):for filename in sorted(os.listdir(filepath + "/")):if filename.startswith(filenamePrefix) and filename.endswith(".jpg"):os.remove(filepath + "/" + filename)print "Deleted %s/%s to avoid filling disk" % (filepath,filename)if (getFreeSpace() > bytesToReserve):return# Get available disk space
def getFreeSpace():st = os.statvfs(filepath + "/")du = st.f_bavail * st.f_frsizereturn du# Get first image
image1, buffer1 = captureTestImage(cameraSettings, testWidth, testHeight)# Reset last capture time
lastCapture = time.time()while (True):# Get comparison imageimage2, buffer2 = captureTestImage(cameraSettings, testWidth, testHeight)# Count changed pixelschangedPixels = 0takePicture = Falseif (debugMode): # in debug mode, save a bitmap-file with marked changed pixels and with visible testarea-bordersdebugimage = Image.new("RGB",(testWidth, testHeight))debugim = debugimage.load()for z in xrange(0, testAreaCount): # = xrange(0,1) with default-values = z will only have the value of 0 = only one scan-area = whole picturefor x in xrange(testBorders[z][0][0]-1, testBorders[z][0][1]): # = xrange(0,100) with default-valuesfor y in xrange(testBorders[z][1][0]-1, testBorders[z][1][1]):   # = xrange(0,75) with default-values; testBorders are NOT zero-based, buffer1[x,y] are zero-based (0,0 is top left of image, testWidth-1,testHeight-1 is botton right)if (debugMode):debugim[x,y] = buffer2[x,y]if ((x == testBorders[z][0][0]-1) or (x == testBorders[z][0][1]-1) or (y == testBorders[z][1][0]-1) or (y == testBorders[z][1][1]-1)):# print "Border %s %s" % (x,y)debugim[x,y] = (0, 0, 255) # in debug mode, mark all border pixel to blue# Just check green channel as it's the highest quality channelpixdiff = abs(buffer1[x,y][1] - buffer2[x,y][1])if pixdiff > threshold:changedPixels += 1if (debugMode):debugim[x,y] = (0, 255, 0) # in debug mode, mark all changed pixel to green# Save an image if pixels changedif (changedPixels > sensitivity):takePicture = True # will shoot the photo laterif ((debugMode == False) and (changedPixels > sensitivity)):break  # break the y loopif ((debugMode == False) and (changedPixels > sensitivity)):break  # break the x loopif ((debugMode == False) and (changedPixels > sensitivity)):break  # break the z loopif (debugMode):debugimage.save(filepath + "/debug.bmp") # save debug image as bmpprint "debug.bmp saved, %s changed pixel" % changedPixels# else:#     print "%s changed pixel" % changedPixels# Check force captureif forceCapture:if time.time() - lastCapture > forceCaptureTime:takePicture = Trueif takePicture:lastCapture = time.time()saveImage(cameraSettings, saveWidth, saveHeight, saveQuality, diskSpaceToReserve)# Swap comparison buffersimage1 = image2buffer1 = buffer2

3. 实物

树莓派Python实现相机控制,定时与画面变化捕捉拍照相关推荐

  1. python控制树莓派led_Python 控制树莓派 GPIO 输出:控制 LED 灯

    树莓派 GPIO 控制输出的入门应该都是从控制 LED 灯开始的吧. 树莓派版本:Model 3B+ 树莓派系统:Raspbian Stretch with desktop and recommend ...

  2. python控制灯_Python 控制树莓派 GPIO 输出:控制 LED 灯

    树莓派 GPIO 控制输出的入门应该都是从控制 LED 灯开始的吧. 树莓派版本:Model 3B+ 树莓派系统:Raspbian Stretch with desktop and recommend ...

  3. python控制树莓派gpioled,Python 控制树莓派 GPIO 输出:控制 LED 灯

    树莓派 GPIO 控制输出的入门应该都是从控制 LED 灯开始的吧. 树莓派版本:Model 3B+ 树莓派系统:Raspbian Stretch with desktop and recommend ...

  4. 树莓派python控制gpio_树莓派的GPIO控制

    陈拓chentuo@ms.xab.ac.cn 2018.06.09/2018.06.10 从网上下载了几张精美的图片,感谢图片的制作者! 0. 概述 本文介绍树莓派 Zero W的GPIO控制,并用L ...

  5. Python pyglet 自制3D引擎入门(二) -- 绘制立体心形,动画和相机控制

    Python作为目前较广泛的编程语言, 用于制作3D游戏可谓得心应手.本文讲解使用Python pyglet库自制简易3D引擎的方法技巧. 上篇:Python pyglet 自制3D引擎入门(一) – ...

  6. 基于树莓派的智能家居控制系统设计论文参考

    完整论文咨询可WX联系:gyf1842965496 智能家居控制系统功能实现详细介绍:基于树莓派的智能家居控制系统设计https://blog.csdn.net/G1842965496/article ...

  7. 树莓派python编程入门与实战解压密码_树莓派Python编程入门与实战

    目录 第一部分 树莓派编程环境 第1章 配置树莓派 3 1.1 获取树莓派 3 1.1.1 了解树莓派的历史 3 1.1.2 为什么要学习用Python 在树莓派上进行编程 4 1.2 获取树莓派 5 ...

  8. 《树莓派Python编程指南》——2.2 一个Python游戏:猫和老鼠

    本节书摘来自华章计算机<树莓派Python编程指南>一书中的第2章,第2.2节,作者:(美) Alex Bradbury Ben Everard更多章节内容可以访问云栖社区"华章 ...

  9. 阿里云物联网平台体验(树莓派+Python篇)

    阿里云物联网平台体验(树莓派+Python篇) 虽然对阿里云物联网平台比较熟悉了,从一开始就有幸参与了飞凤平台(Link Develop 一站式开发平台的前身)的一些偏硬件接入的工作.但是同时也见证了 ...

  10. 树莓派3B+ 叮当语音控制

    树莓派3B+ 叮当语音控制 智能音箱是一个并不新的产品,但在今年却显得尤为火爆,最近发布的天猫精灵,以99元的价格强势步入人们的生活,然而所谓的智能,无非是基于语音识别技术,联控各大平台的产品,从而实 ...

最新文章

  1. bs4爬取的时候有两个标签相同_4.4 爬虫中的bs4数据爬取步骤
  2. Redux专题:实用
  3. react 不能往组件中传入属性的值为 undefined
  4. c语言已知斜率 求倾角,倾斜解的问题
  5. re-for-50-plz-50 寒假逆向生涯(6/100)
  6. CTF杂项之“维吉尼亚密码”
  7. 休眠事实:等于和HashCode
  8. 收到计算机工程与应用的退修通知,《计算机工程与应用》退修意见
  9. 发布时和调试时使用不同的JS
  10. 登录验证---添加验证码验证,Cookie保存功能
  11. fetchxml 汇总_Dynamic CRM 2013学习笔记(十七)JS读写各种类型字段方法及技巧
  12. 计算机二级网站配置参数错误,计算机二级考试最常见的错误集合
  13. qiankun加载react子应用报错[import-html-entry] error occurs while executing normal script
  14. 【Nav2中文网】五、普通教程(九)Groot与行为树互动
  15. 所处网络导致虚拟机的域名解析失败
  16. Uiautomator2 GitHub文档转载
  17. Python中的PIL给图片添加文字
  18. 克服神经网络中的灾难性遗忘(EWC):Overcoming catastrophic forgetting inneural networks
  19. windows11删除此电脑的6个图标,包括视频、图片、文档、下载、音乐、桌面
  20. java 10进制转16进制

热门文章

  1. 计算机组成原理平均cpi怎么算_计算机组成原理-计算机的性能指标及计算题
  2. 塔望食品品牌策划|食品行业怎么讲好品牌故事
  3. INA226+STC89C52RC读取电流电压功率
  4. Pycharm菜单栏消失,(File 、view消失)快速调出来的方法。(Professional Edition 2022版)
  5. On the Efficacy of Knowledge Distillation
  6. 【转载】MAC帧在经过路由器时,其源地址和目的地址会发生改变,路由器的目的地址会出现子在MAC帧中”如何理解?
  7. 阿里云服务器价格表:第7代云服务器ECS收费价格表
  8. 今夜酒店特价与携程的江湖恩怨
  9. 给销售组织分配分销渠道
  10. 11、权重残差图、RLE和NUSE