利用樹莓派做縮時攝影,流程如下:
1. 接上webcam透過fswebcam抓圖
攝影機可以先到 RPi USB Webcams 看前人們將各款webcam裝在樹莓派會不會有問題
安裝截圖軟體「sudo apt-get install fswebcam」
下指令「fswebcam -r 1280x720 -S 60 --banner-colour '#FF000000' --line-colour '#FF000000' --timestamp '%Y-%m-%d %H:%M' --font 'sans:32' ‵date +%Y%m%d%H%M`.jpg」
當中Skip 60 frame讓webcam先自動對焦調整畫面,抓第61張圖
另外把資訊欄位底色設成透明,改timestamp格式跟字型大小
2. 把fswebcam寫入shell script再用crontab定時執行抓圖先說
在/home/pi/建立Timelapse資料夾裝這project東西,然後寫一個capturePhoto.sh如下:
#!/bin/bash
# Information:
# 用crontab排程此程式(最高頻率每分鐘),自動將webcam畫面截圖到photo資料夾
# 依日期建立資料夾,而圖片以「yyyymmddHHMM.jpg」的方式命名
# logitec c920 webcam 在fswebcam看似最高15fps
#
# History:
# 20181224 @Richard begin
# Foler name
FolderName=`date +%Y%m%d`;
# 建立資料夾,帶-p表示資料夾存在的話忽略,不存在則建立
mkdir -p /home/pi/Timelapse/photo/$FolderName
# 已當下日期命名圖片檔
DATE=`date +%Y%m%d%H%M`;
# 透過fswebcam截圖,先skip 60張圖讓webcam先自動對焦完成
# 將banner設定成透明,並加入時間戳記與調整字型
fswebcam -r 1280x720 -S 60 --banner-colour '#FF000000' --line-colour '#FF000000' --timestamp '%Y-%m-%d %H:%M' --font 'sans:32' /home/pi/Timelapse/photo/$FolderName/$DATE.jpg
# return 0 to system
exit 0
抓取時會自動建立/home/pi/Timelapse/photo/yyyymmdd資料夾,將圖片存在裡面
「crontab -e」設定每分鐘執行,進入config後加一列排程在下面「*/1 * * * * /home/pi/Timelapse/capturePhoto.sh > /dev/null 2 > &1」
儲存後顯示成功訊息:「crontab: installing new crontab」
若排程有問題沒有被執行,到「/var/log/syslog」看系統回傳訊息
p.s. 查網路很多資料有人用python或是motion
沒用python的原因是因為time.sleep會累加延遲,不是真的"準點定時拍攝"。ex: 程式前面雜項跑3秒後,time.sleep(10),這樣會整個delay13秒
如果要「import os」的時間判斷,那while無窮迴圈跑在那邊抓時間判斷滿耗資源的。
另一個motion其實滿方便的,如果要"每秒"拍攝目前想到的只有用motion。
crontab最快頻率也只有每分鐘一次,選shell script式因為彈性比較高。
3. 利用avconv/ffmpeg/gstreamer等影像處理,將圖片透過H.264壓縮輸出成影像檔
由於之前使用avconv做串流很耗效能的經驗,直接選gstreamer了
不過omxh264ecn或x264enc編碼器都可以,老樣子openMax H.264硬體加速還是讓影片產出速度快一些!
在樹莓派上執行720p*1000圖片 => 720p10fps影片,omxh264enc約30秒,x264enc約3分鐘
omxh264ecn:「gst-launch-1.0 multifilesrc location="./temp/%05d.jpg" caps="image/jpeg,framerate=10/1" ! jpegdec ! videoconvert ! omxh264enc ! h264parse ! matroskamux ! filesink location="$beginDate\_$days.mkv"」
x264enc:「gst-launch-1.0 multifilesrc location="./temp/%05d.jpg" caps="image/jpeg,framerate=10/1" ! jpegdec ! x264enc ! matroskamux ! filesink location="$beginDate\_$days.mkv"」
如果要調整h.264編碼畫質,在另外調qp值(參考資料8),ex:「 ! x264enc quantizer=1 ! 」,數值越小圖片細節保留越多。
還有很多參數可以調,詳情google~
寫成outputVideo.sh丟在/home/pi/Timelapse
#!/bin/bash
# outputVideo.sh
# Information:
# 將照片複製到temp,重新命名後輸出影片檔
# 參數:
# -b string,日期(yyyymmdd,預設當日)
# -d int, 天數(預設1天)
# -f int, framerate
# -e string, 編碼方式"omxh264enc" or "x264enc"
# 執行時會到「./photo/yyyymmdd」對該日期名稱的資料夾圖片重新編號放置到「./temp」
# 最後再用gstreamer將所有圖片輸出成mkv影片!
# History:
# 20181224 @Richard begin
# 參數預設值
beginDate=$(date -d "$1" +%Y%m%d);
days=1;
fr=10;
enc='omxh264enc';
while getopts ":b:d:f:e:" opt; do
case $opt in
b) beginDate="$OPTARG"
;;
d) days="$OPTARG"
;;
f) fr="$OPTARG"
;;
e) enc="$OPTARG"
;;
\?) echo "Invalid option -$OPTARG" >&2
exit 1;
;;
esac
done
# 顯示讀入參數值
printf "Argument begin date is %s\n" "$beginDate";
printf "Argument days is %s\n" "$days";
printf "Argument frame rate is %s\n" "$fr";
printf "Argument encode type is %s\n" "$enc";
# 判斷給入days,做不同動作
if [ $days == 1 ]; then
echo "對單日輸出一個影片"
# 讀取名單檔案,重新編號搬移到temp資料夾
ls ./photo/$beginDate/*.jpg | awk 'BEGIN{
a=0
}{
printf "cp -f %s ./temp/%05d.jpg\n", $0, a++
}' | bash;
elif [ $days -ge 2 ]; then
echo "對日期區間輸出一個影片";
# 跑迴圈讀取photo裡面各日期的資料夾
for((i=0; i<days;i++))
do
# 讀取資料夾名稱
readFolderName=$(date -d "$beginDate $i day" +%Y%m%d);
# 讀取名單檔案,重新編號搬移到temp資料夾
ls ./photo/$readFolderName/*.jpg | awk 'BEGIN{
# 資料夾已存在檔案數量做初始編號,檔名繼續連號下去
"ls ./temp/*.jpg | wc -l" | getline a;
}{
printf "cp -f %s ./temp/%05d.jpg\n", $0, a++
}' | bash;
done
else
echo "請輸入正整數的天數";
exit 1;
fi
# 輸出影片︰Create H.264 video from images by gstreamer, omxh264enc use less time than x264enc
if [ $enc == "omxh264enc" ]; then
gst-launch-1.0 multifilesrc location="./temp/%05d.jpg" caps="image/jpeg,framerate=$fr/1" ! jpegdec ! videoconvert ! omxh264enc ! h264parse ! matroskamux ! filesink location="$beginDate\_$days.mkv";
elif [ $enc == "x264enc" ]; then
gst-launch-1.0 multifilesrc location="./temp/%05d.jpg" caps="image/jpeg,framerate=$fr/1" ! jpegdec ! videoconvert ! x264enc ! matroskamux ! filesink location="$beginDate\_$days.mkv";
fi
# 刪除暫存區中的被改名的圖片
rm -rf ./temp/*;
exit 0;
4. 輸出影片
給定參數1.日期 2.抓取資料的天數,如果都不給就預設當天
輸出指定日期影片:「/home/pi/Timelapse/outputVideo.sh -b 2018-12-25 」(輸出2018年12月25日當日的縮時影片)
輸出日期區間影片:「/home/pi/Timelapse/outputVideo.sh -b 2018-12-25 -d 10」(意思是2018年12月25日為初始日(含),匯出10天長度的影片)
參考資料:
1. Script要怎麼每當整點就執行一次指令?, https://www.ptt.cc/bbs/Linux/M.1316098032.A.53C.html
2. fswebcam command options, http://manpages.ubuntu.com/manpages/bionic/man1/fswebcam.1.html
3. Create timelapse videos using gstreamer tools (h.264), http://www.tal.org/tutorials/timelapse-video-gstreamer
4. 利用 RASPBERRY PI 3 MODEL B 與 USB WEBCAM 進行縮時攝影(Python), https://blog.everlearn.tw/%E7%95%B6-python-%E9%81%87%E4%B8%8A-raspberry-pi/%E5%88%A9%E7%94%A8-raspberry-pi-3-model-b-%E8%88%87-usb-webcam-%E9%80%B2%E8%A1%8C%E7%B8%AE%E6%99%82%E6%94%9D%E5%BD%B1
5. Contact Privacy Timelapse with fswebcam and avconv, http://www.kupply.com/timelapse-with-fswebcam-and-avconv/
6. Creating a timelapse clip with avconv, https://techedemic.com/2014/09/18/creating-a-timelapse-clip-with-avconv/
7. How to get FFMPEG to join non-sequential image files? (skip by 3s), https://video.stackexchange.com/questions/7300/how-to-get-ffmpeg-to-join-non-sequential-image-files-skip-by-3s/7320
8. 量化参数 quantization parameter以及HEVC中QP详解, https://blog.csdn.net/liangjiubujiu/article/details/80569391
9. Passing named arguments to shell scripts, https://unix.stackexchange.com/questions/129391/passing-named-arguments-to-shell-scripts