Photography on a Budget
Who doesn't love a good time lapse, everything goes all fast like. Clouds zipping through the sky, cars turning into streaks across the image. So I wanted try my hand at making some, but I'm broke as a joke. Therefore I wondered with a bit of code and an old Android phone could I create one? Let have a go!
Shitty Hardware
I had in a box a old Android phone, an HTC Desire S S510e to be exact. It sports:
Screen size: 3.7"
Screen Resolution (pixels): 480 x 800
Operating system: Android 2.1
Camera resolution: 5MP camera
Stand-by time: 17.9 Days
Depth: 1.19cm deep
Height: 11.9cm high
Width: 6cm wide
Autofocus: Yes
Weight (g):130g
FM tuner: FM Radio
Release date: 5 Apr 2011
So a badly smashed screen, but not important. I ended up getting this phone just by asking a friend what they got hanging around in a drawer.
Camera Application
Now the normal camera is not going to do. So I am gonna use IP Webcam, basically this will turn the phone into a IP camera for use in security situations. Download and install.
For my settings I have set:
Resolution: 1280 x 720 (max)
Photo Resolution 2592x1952 (max)
Quality: 50
Orientation: Upside Down (Because of how I have it set up)
Port: 8081
Prevent going to sleep: √
Everything else on default.
Now fire up by pressing Start Server at the bottom.
Through the crack you can just about see http://192.168.28.69:8081, here is where I am gonna go to access the stream. On the page I several options one being "URL for full-resolution photo capture", that take me to http://192.168.28.69:8081/photo.jpg.
Taking Photos
I am going to build a small python application to take photos in intervals, for a set amount of photos and then stitch them together into a movie or gif.
First function is to take a URL and save it to location with a filename
import urllib import os, errno def getImage(url, filename): cwd = os.getcwd() default_dir = os.path.join(cwd, 'captured') try: os.makedirs(default_dir) except OSError as e: if e.errno != errno.EEXIST: raise file = os.path.join(default_dir, filename) urllib.urlretrieve(url, file) getImage(url='http://192.168.28.69:8081/photo.jpg', filename='test2.jpg')
Next is to have a function to empty the folder, run a loop of taking images and incrementing the filename. But first some maths. I am gonna have my finished time lapse at 30 frames a seconds, so if I want to create a 10 second clip I will need 300 images. Now if I have 1 image every 30 seconds it will take 2.5 hours to record. So this is my formula.
((clip_length(sec) * 30) * interval_length(sec)) / 3600 = capture_time(hrs)
So I am going to use the clip and interval length for my input variables.
def takeImages(url, clip_length, interval_length): images = [] imageCount = clip_length * 30 for count, image in enumerate(range(imageCount)): filename = '%04d.jpg' % count imageFile = getImage(url=url, filename=filename) images.append(imageFile) time.sleep(interval_length) return imagestakeImages(url='http://192.168.28.69:8081/photo.jpg', clip_length=2, interval_length=10)
Cool, now next I need to collect them all into clip. First I attempted a gif, what I found was at full resolution didn't work. So I added another module to scale the image using PIL. I then used imageio to stream the images into a gif.
def resizeImage(imageFile): maxsize = (600, 600) img = Image.open(imageFile) img.thumbnail(maxsize, Image.ANTIALIAS) img.save(imageFile) return True def makeGif(filelist): gifFile = os.path.join(default_dir, 'timelapse.gif') with imageio.get_writer(gifFile, mode='I') as writer: for filename in filelist: file = os.path.join(default_dir, filename) resizeImage(file) image = imageio.imread(file) writer.append_data(image)
Next I wanted to create a video from the images. Here I used ffmpeg to stream the files to a file. I download from http://www.ffmpegmac.net/ and ran it from the script as if I was doing so from the terminal. With this I just get all of the files from looking in the folder and not sending the list to the function.
Finally I just call the functions as I need them. The Android app url at a clip length of 10 secs at an interval of 5secs ended up as so:
A right hefty file. Sorry for the time to load.
def makeVideo(): os.system('./ffmpeg -f image2 -r 30 -i ./captured/%04d.jpg -y ./captured/timelapse.mp4')
Finally I just call the functions as I need them. The Android app url at a clip length of 10 secs at an interval of 5secs ended up as so:
A right hefty file. Sorry for the time to load.
Where from here
If you are wondering, 'why the fuck didn't you just use an app', that's a good question. Well I tend to find myself with some IP camera and thought it would be an interesting way to get timelapse footage. Also there is a site that has IP cameras that haven't been secured, take a peak over at insecam.org. I also wanted to get some timelapse footage from some random cameras from around the world.
import urllib
import os, errno
import time
import imageio
from PIL import Image
# Get the current working directory and check for/create a folder capture
cwd = os.getcwd()
default_dir = os.path.join(cwd, 'captured')
try:
os.makedirs(default_dir)
except OSError as e:
if e.errno != errno.EEXIST:
raise
# Function to save an image from a URL to file
# Inputs:
# url (str): Full URL to parse
# filename (str): name the file to be saved
# Outputs:
# file (string): Return file as a string
def getImage(url, filename):
# Build file location, request url and save there
file = os.path.join(default_dir, filename)
urllib.urlretrieve(url, file)
return file
# Function to take several images
# Inputs:
# url (str): Full URL to parse
# clip_length (int): How long the time lapse clip will be in secs
# interval_length (int): The real time interval between taking images in secs
#
# Outputs:
# images (list): Return all images as a list of files
def takeImages(url, clip_length, interval_length):
images = []
imageCount = clip_length * 30
for count, image in enumerate(range(imageCount)):
filename = '%04d.jpg' % count
imageFile = getImage(url=url, filename=filename)
images.append(imageFile)
time.sleep(interval_length)
return images
# Function to resize an image to a maximum of either 600px high or wide
# Input:
# imagefile (size): Absolute location of image
def resizeImage(imageFile):
maxsize = (600, 600)
img = Image.open(imageFile)
img.thumbnail(maxsize, Image.ANTIALIAS)
img.save(imageFile)
return True
# Take a list of images and create a gif
# Inputs:
# filelist (list): list of files from a folder of images
def makeGif(filelist):
gifFile = os.path.join(default_dir, 'timelapse.gif')
with imageio.get_writer(gifFile, mode='I') as writer:
for filename in filelist:
file = os.path.join(default_dir, filename)
# Send image to be resized
resizeImage(file)
image = imageio.imread(file)
writer.append_data(image)
# Look in the captured folder and
def makeVideo():
os.system('./ffmpeg -f image2 -r 30 -i ./captured/%04d.jpg -y ./captured/timelapse.mp4')
images = takeImages(url='http://184.7.223.152/jpg/image.jpg', clip_length=30, interval_length=5)
makeVideo()
makeGif(images)
import os, errno
import time
import imageio
from PIL import Image
# Get the current working directory and check for/create a folder capture
cwd = os.getcwd()
default_dir = os.path.join(cwd, 'captured')
try:
os.makedirs(default_dir)
except OSError as e:
if e.errno != errno.EEXIST:
raise
# Function to save an image from a URL to file
# Inputs:
# url (str): Full URL to parse
# filename (str): name the file to be saved
# Outputs:
# file (string): Return file as a string
def getImage(url, filename):
# Build file location, request url and save there
file = os.path.join(default_dir, filename)
urllib.urlretrieve(url, file)
return file
# Function to take several images
# Inputs:
# url (str): Full URL to parse
# clip_length (int): How long the time lapse clip will be in secs
# interval_length (int): The real time interval between taking images in secs
#
# Outputs:
# images (list): Return all images as a list of files
def takeImages(url, clip_length, interval_length):
images = []
imageCount = clip_length * 30
for count, image in enumerate(range(imageCount)):
filename = '%04d.jpg' % count
imageFile = getImage(url=url, filename=filename)
images.append(imageFile)
time.sleep(interval_length)
return images
# Function to resize an image to a maximum of either 600px high or wide
# Input:
# imagefile (size): Absolute location of image
def resizeImage(imageFile):
maxsize = (600, 600)
img = Image.open(imageFile)
img.thumbnail(maxsize, Image.ANTIALIAS)
img.save(imageFile)
return True
# Take a list of images and create a gif
# Inputs:
# filelist (list): list of files from a folder of images
def makeGif(filelist):
gifFile = os.path.join(default_dir, 'timelapse.gif')
with imageio.get_writer(gifFile, mode='I') as writer:
for filename in filelist:
file = os.path.join(default_dir, filename)
# Send image to be resized
resizeImage(file)
image = imageio.imread(file)
writer.append_data(image)
# Look in the captured folder and
def makeVideo():
os.system('./ffmpeg -f image2 -r 30 -i ./captured/%04d.jpg -y ./captured/timelapse.mp4')
images = takeImages(url='http://184.7.223.152/jpg/image.jpg', clip_length=30, interval_length=5)
makeVideo()
makeGif(images)
Comments
Post a Comment