Skip to main content

Cheapo Time Lapse

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)

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.

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)



Comments

Popular posts from this blog

Adventures in Pillow Part 2

From my last post where I made a slideshow promo video, I realised how powerful Pillow is. I still have a fair bit of automation to do, so another thing I do a lot of is motivational quotes for Twitter (I am aware they are fucking stupid, but they share well)



The breakdown of the components are a background with a filter, the quote, who said it and our logo.
Background and Filter To start off I am going to create a folder called quote and add in an image and just name it background.jpg (sourced from Pixabay). Next I import PIL and open the file.
from PIL import Image import os, errno cwd = os.getcwd() image_dir = os.path.join(cwd, 'quote') def filterImage(imageFile): im = Image.open(imageFile) im.show() filterImage(os.path.join(image_dir, 'background.jpg'))



Next I need to crop the image. I am going to take the centre portion out of the image to make square. Like so:
So I start off with getting the dimensions of the image with:
im.size
I get a tuple of (1920, 1…

Adventures with Pillow Part 1

I am in the middle of building an app and need to put together several promo videos for Twitter and Instagram, and man it is boring. So I thought 'how can I automate this process?', so welcome to this post.

What I am going for is a selection of images, greyscaled flipping through with our logo on the front. So my approach was to use python, pillow and ffmpeg to build something. This could be disastrous.

Images
To start a few pre-flight checks, a variable for the test image and to check for/create a processed folder for the final images to go.

import os, errnofrom PIL import Image, ImageFont, ImageDraw testImage = 'test.png'cwd = os.getcwd()image_dir = os.path.join(cwd, 'images')default_dir = os.path.join(cwd, 'processed')try: os.makedirs(default_dir)except OSError as e: if e.errno != errno.EEXIST: raise
I am going to build a function that will do all of the processing, but first going to run on one image before looping through all of the …

Raspberry Pi Download Machine Part 1

Yet Another Raspberry Pi Project Kodi builds, weird fucking robots and classic gaming always seems to be the theme of RPi projects. But a stat I would like to know is how many are just sat in a drawer somewhere. Anyway I am part of that number, until now. I manage to find a 4TB drive and managed to blag a caddy, so with this triangle of 'crap hanging around' I thought I'd build a downloader.

Open Directories So I first had the idea from the sub-reddit open directories, here storage devices are opened up to the internet without a morsel of authentication. Google comes along and indexes them and you can go and find them. Decent ones find themselves on this sub of which I assume stays up until the user realises that there broadband is getting absolutely raped.
So I wanted to be able to get a URL from a server and just throw it in a WebUI and get it to auto download and ping me when all is finished. 

First Steps So to start off I downloaded Raspbian Jessie Lite from 2017-07-0…