Initial commit
This commit is contained in:
14
EXAMPLE.config.json
Normal file
14
EXAMPLE.config.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"real_days": 0,
|
||||||
|
"real_hours": 0,
|
||||||
|
"real_mins": 30,
|
||||||
|
"real_seconds": 0,
|
||||||
|
"target_length_min": 0,
|
||||||
|
"target_length_sec": 30,
|
||||||
|
"target_fps": 30,
|
||||||
|
"camera_ip": "192.168.2.231",
|
||||||
|
"camera_port": 3400,
|
||||||
|
"camera_username": "henrypump",
|
||||||
|
"camera_password": "HPCamera1903",
|
||||||
|
"output_file": "test1.avi"
|
||||||
|
}
|
||||||
45
README.txt
Normal file
45
README.txt
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
In this folder are two files: EXAMPLE.config.json and timelapse_maker.EXAMPLE
|
||||||
|
|
||||||
|
EXAMPLE.config.json is an example config file. The config file looks like the following:
|
||||||
|
|
||||||
|
{
|
||||||
|
"real_days": 0,
|
||||||
|
"real_hours": 0,
|
||||||
|
"real_mins": 30,
|
||||||
|
"real_seconds": 0,
|
||||||
|
"target_length_min": 0,
|
||||||
|
"target_length_sec": 30,
|
||||||
|
"target_fps": 30,
|
||||||
|
"camera_ip": "192.168.2.231",
|
||||||
|
"camera_port": 3400,
|
||||||
|
"camera_username": "henrypump",
|
||||||
|
"camera_password": "HPCamera1903",
|
||||||
|
"output_file": "test1.avi"
|
||||||
|
}
|
||||||
|
|
||||||
|
Where:
|
||||||
|
real_days: the number of real time days to capture images
|
||||||
|
real_hours: the number of real time hours to capture images
|
||||||
|
real_mins: the number of real time minutes to capture images
|
||||||
|
real_seconds: the number of real time seconds to capture images
|
||||||
|
target_length_min: the number of minutes the output file should be (this is used in conjunction with target_length_sec to get the full length of the output)
|
||||||
|
target_length_sec: the number of seconds the output file should be (this is used in conjunction with target_length_min to get the full length of the output)
|
||||||
|
target_fps: the frames per second the output file should be run at (10fps is choppy, 15fps is less-choppy, 24fps is cinematic, 30fps is smooth, 60fps is really smooth)
|
||||||
|
camera_ip: the ip address of the camera (the " marks are important)
|
||||||
|
camera_port: the port number for the camera
|
||||||
|
camera_username: the username to login to the camera (the " marks are important)
|
||||||
|
camera_password: the password to login to the camera (the " marks are important)
|
||||||
|
output_file: the name of the output file (the " marks are important also be sure to include .avi else Windows won't recognize it)
|
||||||
|
|
||||||
|
The name of the config file should be:
|
||||||
|
config.json
|
||||||
|
|
||||||
|
Once the config file is setup just double click timelapse_maker.exe and the software should run itself.
|
||||||
|
Some caveats:
|
||||||
|
The software is only guaranteed for Panasonic iPro cameras
|
||||||
|
The software will not recover in anyway in the event of a windows reboot or the software being closed.
|
||||||
|
The software is better suited to longer run times ie: setting longer real time runs is better than shorter ones
|
||||||
|
The software defaults to making a timelapse folder in its current folder where it stores all the images once the video is made this folder can be deleted
|
||||||
|
DO NOT close the window else you'll have to start over, the images won't be lost but the run will be skewed
|
||||||
|
The software processes all the images in the timelapse folder regardless of what run they are from
|
||||||
|
Technically the software could be run remotely and given a public IP that is port forwarded but is NOT recommened
|
||||||
BIN
timelapse_maker.exe
Normal file
BIN
timelapse_maker.exe
Normal file
Binary file not shown.
93
timelapse_maker.py
Normal file
93
timelapse_maker.py
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import requests
|
||||||
|
from requests.auth import HTTPDigestAuth
|
||||||
|
import time
|
||||||
|
from cv2 import VideoWriter, imread, VideoWriter_fourcc
|
||||||
|
import numpy as np
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import progressbar
|
||||||
|
from natsort import natsorted
|
||||||
|
|
||||||
|
def calc_interframetime(real_days,real_hours,real_mins,real_seconds,target_length_min,target_length_sec,target_fps):
|
||||||
|
#converts real time inputs into seconds
|
||||||
|
rd = real_days*24*60*60
|
||||||
|
rh = real_hours*60*60
|
||||||
|
rm = real_mins*60
|
||||||
|
rs = rd+rh+rm+real_seconds
|
||||||
|
#calculate the target frames for the final output
|
||||||
|
target_frames = (target_length_min*60 + target_length_sec) * target_fps
|
||||||
|
#calculate the wait time between frames
|
||||||
|
spf = rs/target_frames
|
||||||
|
return target_frames,spf
|
||||||
|
|
||||||
|
#url = 'https://httpbin.org/digest-auth/auth/user/pass'
|
||||||
|
def makevideo():
|
||||||
|
|
||||||
|
PERSIST = {}
|
||||||
|
try:
|
||||||
|
with open("config.json", 'r') as persist_file:
|
||||||
|
PERSIST = json.load(persist_file)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
target_frames,interframe_time = calc_interframetime(
|
||||||
|
PERSIST['real_days'],
|
||||||
|
PERSIST['real_hours'],
|
||||||
|
PERSIST['real_mins'],
|
||||||
|
PERSIST['real_seconds'],
|
||||||
|
PERSIST['target_length_min'],
|
||||||
|
PERSIST['target_length_sec'],
|
||||||
|
PERSIST['target_fps'])
|
||||||
|
try:
|
||||||
|
now = time.time()
|
||||||
|
with open('timelapse/{}.jpg'.format(now), 'wb') as handle:
|
||||||
|
pass
|
||||||
|
os.remove('timelapse/{}.jpg'.format(now))
|
||||||
|
except:
|
||||||
|
os.mkdir('timelapse')
|
||||||
|
print("Number of frames:{}\nReal Time between frames: {} seconds".format(target_frames,interframe_time))
|
||||||
|
|
||||||
|
#for every frame in the range of target_frames
|
||||||
|
for x in progressbar.progressbar(range(target_frames),prefix='Collecting Photos: '):
|
||||||
|
#open a file and pull the current picture from the camera
|
||||||
|
now = time.time()
|
||||||
|
try:
|
||||||
|
with open('timelapse/{}.jpg'.format(now), 'wb') as handle:
|
||||||
|
response = requests.get("http://" + PERSIST['camera_ip'] + ":" + str(PERSIST['camera_port']) + "/cgi-bin/camera",
|
||||||
|
auth=HTTPDigestAuth(PERSIST['camera_username'],PERSIST['camera_password']),stream=True)
|
||||||
|
if not response.ok:
|
||||||
|
print(response)
|
||||||
|
|
||||||
|
for block in response.iter_content(1024):
|
||||||
|
if not block:
|
||||||
|
break
|
||||||
|
|
||||||
|
handle.write(block)
|
||||||
|
except:
|
||||||
|
print("\nMissed frame {} check connection/settings to camera!".format(x))
|
||||||
|
os.remove('timelapse/{}.jpg'.format(now))
|
||||||
|
if x != target_frames-1 and interframe_time-(time.time()-now) > 0:
|
||||||
|
#wait the calculated time between frames minus the processing time for this frame to start again
|
||||||
|
time.sleep(interframe_time-(time.time()-now))
|
||||||
|
|
||||||
|
|
||||||
|
#filenames = natsorted(filenames)
|
||||||
|
img_array = []
|
||||||
|
|
||||||
|
#load the pictures with cv2
|
||||||
|
for filename in progressbar.progressbar(glob.glob('timelapse/*.jpg'),prefix='Loading Photos: '): #filenames:
|
||||||
|
img = imread(filename)
|
||||||
|
height, width, _ = img.shape
|
||||||
|
size = (width,height)
|
||||||
|
img_array.append(img)
|
||||||
|
|
||||||
|
#setup the video format
|
||||||
|
out = VideoWriter(PERSIST['output_file'], VideoWriter_fourcc(*'MP42'), PERSIST['target_fps'], size)
|
||||||
|
|
||||||
|
#output the video
|
||||||
|
for i in progressbar.progressbar(range(len(img_array)),prefix='Processing Video: '):
|
||||||
|
out.write(img_array[i])
|
||||||
|
out.release()
|
||||||
|
makevideo()
|
||||||
|
input("Press ENTER to exit program")
|
||||||
Reference in New Issue
Block a user