[Raspberry Pi] 樹莓派縮時攝影 Time-lapse photography

  • 2253
  • 0
  • 2018-12-26

github好看版

利用樹莓派做縮時攝影,流程如下:

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