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 images takeImages( 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)







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)





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.



