本来是想配合上一篇写的测距传感器数据打开摄像头录制个50秒实时画面,后来这个测距传感器(因为我是歪用,用来识别范围内的移动物体)给的数据,false alarming还是太高了。于是想到使用本人之前深恶痛绝的opencv来试一试。

很多时候,养寄居蟹就是养一盆土。大概如下吧。

所以也就有动静的时候,偷摸观察下是比较不错的。下面就是自研的小动静侦测录像代码,真是累死。基本就是自己试出来的,采用的数值可以算是一个时间序列上的二次导了吧,表达画面变化的变化速率(只是单位时间不是1秒而已)。

实时拍摄的里面截取了3秒,一起找找寄居蟹,

代码实现如下,文件结构

.
├── output
└── save_key_events.py

2024-05-25: 加了画面带datetime overlay的。

from picamera2 import Picamera2,MappedArray
from picamera2.encoders import H264Encoder
from picamera2.outputs import FileOutput,FfmpegOutput

import time
import cv2
import numpy as np

colour=(120,230,30)
origin=(0,30)
font=cv2.FONT_HERSHEY_SIMPLEX
scale=1
thickness=1
picam2 =Picamera2()
picam2.configure(picam2.create_video_configuration(main={"size": (640,480)}))

def apply_timestamp(request):
    timestamp = time.strftime("%Y%m%d_%H:%M:%S")
    with MappedArray(request,"main") as m:
        cv2.putText(m.array,timestamp,origin,font,scale,colour,thickness)


picam2.pre_callback = apply_timestamp
encoder = H264Encoder()

picam2.start()
print("[INFO] warming up camera...")
t = 0
for t in [0,30]:
    t = t + 1
    time.sleep(1)
print("Ready to go!")
last_mean = 0
skip_flag = 0

try:
    while True:
        if skip_flag > 0: #实际的观测发现,即便撤去画面中模拟的道具,这个二阶比值change_velocity还会有一些不稳定。
            skip_flag = skip_flag - 1
            time.sleep(20)
        frame = picam2.capture_array()
        gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
        current_mean = np.mean(gray)
        current_result = np.abs(current_mean - last_mean)

        if last_mean != 0 :
            change_velocity = min(current_result,previous_result) / max(current_result,previous_result)
            print(change_velocity)
            if change_velocity < 0.6 and change_velocity > 0.1 and skip_flag in [0,3]:
                now = time.strftime("%Y-%m-%d-%H_%M_%S",time.localtime(time.time()))
                if skip_flag == 3:
                    now = "csc_" + now
                fname = "./output/" + now + ".mp4"
                output_file = FfmpegOutput(fname)
                picam2.start_recording(encoder,output=output_file)
                time.sleep(50)
                picam2.stop_recording()
                last_mean = current_mean
                if skip_flag == 0:
                    skip_flag = 4
        if last_mean == 0:
            last_mean = current_mean
        previous_result = current_result
        time.sleep(10)
        picam2.start()
except KeyboardInterrupt:
    picam2.stop_recording()
    cv2.destroyAllWindows()

finally:
    # do a bit of cleanup
    picam2.stop_recording()

最后抄来一个bash控制文件夹大小,删旧文件的。用crontab每隔15分钟,弄一次。

#!/bin/bash
#Usage = sh limit-directory-size.sh /media/computer/mypartition 80 4 ("/media/computer/mypartition" = the directory to be limited / "88"=the percentage of the total partition this directory is allowed to use / "120"=the number of files to be deleted every time the script loops (while $Directory_Percentage > $Max_Directory_Percentage)

#Directory to limit
Watched_Directory=$1
echo "Directory to limit="$Watched_Directory

#Percentage of partition this directory is allowed to use
Max_Directory_Percentage=$2
echo "Percentage of partition this directory is allowed to use="$Max_Directory_Percentage

#Current size of this directory
Directory_Size=$( du -sk "$Watched_Directory" | cut -f1 )
echo "Current size of this directory="$Directory_Size

#Total space of the partition = Used+Available
Disk_Size=$(( $(df $Watched_Directory | tail -n 1 | awk '{print $3}')+$(df $Watched_Directory | tail -n 1 | awk '{print $4}') ))
echo "Total space of the partition="$Disk_Size

#Curent percentage used by the directory
Directory_Percentage=$(echo "scale=2;100*$Directory_Size/$Disk_Size+0.5" | bc | awk '{printf("%d\n",$1 + 0.5)}')
echo "Curent percentage used by the directory="$Directory_Percentage

#number of files to be deleted every time the script loops (can be set to "1" if you want to be very accurate but the script is slower)
Number_Files_Deleted_Each_Loop=$3
echo "number of files to be deleted every time the script loops="$Number_Files_Deleted_Each_Loop

#While the current percentage is higher than allowed percentage, we delete the oldest files
while [ $Directory_Percentage -gt $Max_Directory_Percentage ] ; do
    #we delete the files
    find $Watched_Directory -type f -printf "%T@ %p\n" | sort -nr | tail -$Number_Files_Deleted_Each_Loop | cut -d' ' -f 2- | xargs rm
    #we delete the empty directories
    find $Watched_Directory -type d -empty -delete
    #we re-calculate $Directory_Percentage
    Directory_Size=$( du -sk "$Watched_Directory" | cut -f1 )
    Directory_Percentage=$(echo "scale=2;100*$Directory_Size/$Disk_Size+0.5" | bc | awk '{printf("%d\n",$1 + 0.5)}')
done

难得讲究,以下是参考的文章:

Simple Motion Detection with Python and OpenCV — For Beginners

Motion Detection using OpenCV

用opencv来自动保存关键事件视频片段 - 知乎

using bash - Limit the size of a directory by deleting old files

GitHub 加速计划 / opencv31 / opencv
77.38 K
55.71 K
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:2 个月前 )
c3747a68 Added Universal Windows Package build to CI. 4 天前
9b635da5 - 4 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐