RasPi.TV

Raspberry Pi, Electronics & Making
  • Home
  • Site Map
  • Shop
  • Downloads
  • I²C
  • raspberry pi
  • Linux usage
  • Python prog.
  • Input & Output

Overlaying Text and Graphics on a Photo and Tweeting it – pt 5 Twitter App series

 python programming, raspberry pi, Raspberry Pi Camera  Add comments
Feb 162014
 

Today we’re going to take a photo, overlay some text and graphics on it and then tweet it. In this series, we’ve been building a Raspberry Pi Twitter app and we’re adding more to it. This is a great way to develop software. Add things one step at a time and don’t move on to the next part until it works well, and you understand it.

Why Would You Want To Do This?

Let me backtrack and explain why I wanted to do this in the first place. I have a weather station running on a Raspberry Pi. It logs the following data to Xively…

  • Inside temperature
  • Outside temperature
  • Inside light level
  • Outside light level
  • Barometric pressure

When away from the house, I like to monitor what’s happening. I have security cameras for this, but last summer I used a Pi camera as well.

So, I thought it would be cool if I could grab the weather station data from Xively and overlay that on a photo of the garden, along with time and date, and then tweet the photo. It sounds hard, but it didn’t take long to find out how to do it.

And then I thought “What about overlaying a logo as well?” That didn’t take too long to work out either.

Final result. Tweeted photo of garden with weather data and logos overlaid.

Tweeted photo of garden with weather data and logos overlaid. Click to enlarge.

What I’m Not Covering


I’m not going to cover the specifics of how I get the data from Xively because…

  1. I’m using the obsolete COSM pachube interface (it still works, but it’s not the way forward).
  2. Whatever text you want to overlay, may come from a totally different place, so it wouldn’t be helpful for you

But I am going to cover the mechanics of doing the text and graphics overlay. So how do we do the overlays?

It’s Magic

Screen Shot 2014-02-10 at 13.38.32
I had no idea how to overlay text on a photo, but I headed over to the Raspberry Pi forums and did a search. It didn’t take long to find a helpful thread.

It can all be done with an excellent package called ImageMagick. So let’s install it…

sudo apt-get update (update package list)
sudo apt-get install imagemagick (install program)

Overlaying Text

From the command line, this is how it works…
convert your_photo.jpg -pointsize 36 -fill white -annotate +40+728 'your overlay text' your_output_photo.jpg

There are a couple of traps though because, from within a program, it’s better to specify the full path to files and programs. So it becomes…

/usr/bin/convert /path/to/your_photo.jpg -pointsize 36 -fill white -annotate +40+728 'your overlay text' /path/to/your_output_photo.jpg

So What Does This Do?

It takes the photo your_photo.jpg and overlays the text your overlay text 40 pixels in from the left-hand edge and 728 pixels from the top edge. The text will be 36 points high and white. The resulting file is saved as your_output_photo.jpg, but you can use the same filename and path as the input file to overwrite the original.

This is incredibly powerful and – once you’ve got your head round it – not very hard. So the program does this step for each piece of data it wants to overlay. There is a way to change the font, but I had trouble with it, so stayed with the default font.

But I want logos too. :)

Overlaying Graphics

We use the same program as before, but different command arguments and parameters…
/usr/bin/convert /path/to/your_photo.jpg /home/pi/overlay.png -geometry +1+1 -composite path/to/your_modified_photo.jpg

This uses ‘convert’ to take your_photo.jpg and overlay the file overlay.png 1 pixel from the left-hand edge and 1 pixel down from the top edge. It puts the output in the file your_modified_photo.jpg

So, in my program, I ran this command twice. Once for each logo. It’s a good idea to make sure your logos are a suitable size. If they’re not, you can scale them, but if you’re doing the same thing over and over again, it’s more efficient to do that processing once and in advance.

So What About the Code Then?

Here is a slightly modified version of the code I used at the Cambridge Raspberry Jam last weekend to tweet photos of people who visited the HDMIPi stand.

#!/usr/bin/env python2.7
# tweetpic6BLOG.py by Alex Eames https://raspi.tv/?p=6004
# take a photo with the Pi camera, overlay some text
# then overlay a small logo and tweet the final image
import tweepy
from time import sleep
from subprocess import call
from datetime import datetime
import sys

if len(sys.argv) >= 2:
    tweet_text = sys.argv[1]

else:
    tweet_text = "Photo from insert your location here"

if len(tweet_text) > 110:
    print "tweet not sent. Too long. 110 chars Max. Try again."
    sys.exit()

# Twitter Bits. Consumer keys and access tokens, used for OAuth
consumer_key = 'copy your consumer key here'
consumer_secret = 'copy your consumer secret here'
access_token = 'copy your access token here'
access_token_secret = 'copy your access token secret here'

# OAuth process, using the keys and tokens
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
 
# Creation of the actual interface, using authentication
api = tweepy.API(auth)

def photo_tweet():
    i = datetime.now()
    now = i.strftime('%Y%m%d-%H%M%S')
    tweettime = i.strftime('%Y/%m/%d %H:%M:%S')
    photo_name = now + '.jpg'
    cmd = 'raspistill -t 500 -w 1024 -h 768 -o /home/pi/' + photo_name    
    print 'cmd ' +cmd
    print "about to take photo"
    call ([cmd], shell=True)
    print "photo taken"
    photo_path = '/home/pi/' + photo_name
    status = tweet_text + ' #optionalhashtag ' + tweettime 

# Add text overlay of data on the photo we just took
    print "about to set overlay_text variable"
    overlay_text = "/usr/bin/convert "+ photo_path + "  -pointsize 36 -fill white -annotate +40+728 '" + tweettime + "' "
    overlay_text += " -pointsize 36 -fill white -annotate +40+630 'Your Text annotation here ' " + photo_path

    print "overlaying text"
    call ([overlay_text], shell=True)

    print "adding your logo" # you'll need a file called overlay.png in /home/pi
    overlay_text = '/usr/bin/convert '+ photo_path + ' /home/pi/overlay.png -geometry +1+1 -composite ' + photo_path
    call ([overlay_text], shell=True)
    print "added logo 1"

    print "tweeting photo"
    api.update_with_media(photo_path, status=status)    
    print "photo tweeted, deleting .jpg"
    cmd = 'rm ' + photo_path 
    call ([cmd], shell=True)

print 'start of program' 

photo_tweet()

There is one major caveat. The spaces at the ends of lines 49 (“‘ “), 50 (‘ “) and 56 (composite ‘) are essential or the imagemagick convert command will fail.

A minor caveat is that I use the same path/filename for the input and output of all overlays, which means that the original photo is overwritten at each step.

Code Walkthrough

Here’s an explanation of what the code does…
1 shebang line enables this script to be executed directly (if permissions correct)
2-4 and comments
5-9 import required libraries
11-15 use command line input as tweet text, or default set in 15
17-19 ensure tweet text is not too long
21-32 set up twitter interface
34-63 main function defined
35-38 deal with time stamping and photo file name
39-43 take the photo
44 set full photo file path
45 assemble the full tweet text
48-53 build and execute the ‘convert’ text overlay command
55-58 build and execute the ‘convert’ graphic overlay command
60-61 tweet the overlaid photo
62-64 delete the photo (comment out 64 if you want to keep it)
68 call the main function photo_tweet()

What Does the Output Look Like?

And here’s an embedded tweet from last weekend’s Cambridge Jam, where I used a very similar script to tweet photos from the event. This is myself and Ben Nuttall (although the weather data was still from my home-based weather station)…

Photo from #CamJam 8th Feb 2014 #CamJam 2014/02/08 16:11:08 pic.twitter.com/Pkm5mvoCzL

— RasP.iO (@RasPiO1) February 8, 2014

Improvements?

At the Cambridge Jam, I realised it would be nice to be able to view the photo afterwards on the HDMIPi screen that was attached to the Pi.

So I’ve implemented that for next week’s Oxford Jam (watch for the hashtag #OxJam on 18th Feb in the evening).

I think our work here with twitter and Python tweepy may be nearly done. I may discover more we can add, but for the time being I may well take a break. We’ll see how it goes. I hope you’ve enjoyed the series. Let us know how you get on and if you make a twitter app of your own.

I’ve created an index page of all the twitter app on the Raspberry Pi series here https://raspi.tv/raspitweets ‎

And you can download the full set of Python scripts from my Github repo here

or, from Pi command line, use…

git clone https://github.com/raspitv/raspitweets

 Posted by alex at 5:01 am  Tagged with: python twitter app on raspberry pi, tweepy upload photo, using python to control twitter on raspberry pi

  12 Responses to “Overlaying Text and Graphics on a Photo and Tweeting it – pt 5 Twitter App series”

  1. Chorlton says:
    February 16, 2014 at 11:53 pm

    Or you could use the Image.Draw function within Python Image Library (PIL) to add text, then its nicely contained within the Python ecosystem.

    Reply
    • alex says:
      February 17, 2014 at 8:58 am

      I’ll have to have a look at that. I’m perfectly happy using imagemagick, but always looking for new ways (to me) of doing things.

      Reply
  2. AndrewS says:
    February 21, 2014 at 12:51 pm

    Couple of minor points:

    Depending on the background of your image, plain-white-text may not always be easily readable. http://www.imagemagick.org/Usage/annotating/#anno_on suggests a number of techniques for dealing with that.

    Rather than getting confused about where spaces and quote marks are supposed to start and stop, you may find string formatting more useful? i.e. you can replace:
    overlay_text = "/usr/bin/convert "+ photo_path + " -pointsize 36 -fill white -annotate +40+728 '" + tweettime + "' "
    overlay_text += " -pointsize 36 -fill white -annotate +40+630 'Your Text annotation here ' " + photo_path

    with:
    overlay_text = "/usr/bin/convert %s -pointsize 36 -fill white -annotate +40+728 '%s' -pointsize 36 -fill white -annotate +40+630 '%s' %s" % (photo_path, tweettime, "Your Text annotation here", photo_path)
    which (depending on your preference) you may or may not find easier to read ;-)
    (I haven’t checked, but maybe the duplicate -pointsize and -fill flags are redundant?)

    The text on the images on http://www.interrose.co.uk/flowers/14_happy_roses.shtml was added with ImageMagick in exactly the same way too ;-) (except I was calling /usr/bin/convert from Perl, instead of from Python, and I wasn’t doing it on a Raspberry Pi)

    Reply
    • alex says:
      February 22, 2014 at 9:08 am

      Thanks Andrew.

      Your minor points are always interesting. I use string formatting in print statements, but it never occurred to me to use it here. That’s a good idea. Bit less ‘clunky’ :)

      Imagemagick is awesome. Was talking to Dave Akerman on Tuesday at the Oxford Jam. He said that’s what he uses on his balloon flights to process the photos.

      Reply
      • AndrewS says:
        February 22, 2014 at 3:02 pm

        Yeah, ImageMagick has lots and lots of options – it’s almost like a CLI version of GIMP ;-)

        Reply
  3. Vic says:
    February 28, 2014 at 9:36 pm

    Great job and thank you for the post!

    I am attempting to do something similar but could sure use some help.

    I have image files in a folder with each file using a naming convention which utilizes the date and time the image was taken:
    YYYYMMDD-HourRMinuteSeconds.jpg
    example “20140227-134726.jpg” -Taken Feb 27 2014 at 01:47:26 PM

    I also have several .csv files which contain data I wish to overlay onto all the images I have taken.

    For example, “Humidity.csv” contains:

    STAMP,VALUE
    2014-02-27 13:36:41.312,45.3
    2014-02-27 13:39:11.908,44.5
    2014-02-27 13:41:42.07,43.7
    —snip—

    “Temperature.csv” contains:

    STAMP,VALUE
    2014-02-27 14:44:27.952,22.4
    2014-02-27 14:46:58.964,22.7
    2014-02-27 14:49:29.863,23.1
    —SNIP—

    Anybody have any clue how I could import the data from the CSV, match THAT to the closest timestamp of the image, then overlay the corresponding value onto an image?

    I know it sounds easy, but for a non-programmer, it isn’t. ANY help would be appreciated.

    -Vic

    Reply
    • AndrewS says:
      March 8, 2014 at 10:18 am

      As always in software development, the solution is to break it down into smaller sub-steps… :-)

      Reading data from a CSV file: http://docs.python.org/2/library/csv.html

      Reading filenames in a directory: http://docs.python.org/2/library/os.html#os.listdir

      Converting a date in text format to a datetime object: http://docs.python.org/2/library/datetime.html#datetime.datetime.strptime

      Subtracting one datetime object from another, to get a timedelta object: http://docs.python.org/2/library/datetime.html#datetime-objects

      Comparing timedelta objects: http://docs.python.org/2/library/datetime.html#timedelta-objects

      So to get the ‘closest’ timestamp, you simply need to find the two timestamps where the abs(datetime1 – datetime2) gives the smallest value.

      And then you can just follow Alex’s instructions above to overlay the data onto your image :)

      Reply
  4. Tweets from a Dragon says:
    August 13, 2014 at 11:52 am

    […] setup allowed me to merge  example code from Raspi.tv and example code from picamera to take a picture once every 5 minutes and uploaded it to […]

  5. picfish81 says:
    November 14, 2014 at 1:47 pm

    Python 3 support would be nice :)

    Reply
    • alex says:
      November 14, 2014 at 3:01 pm

      I’m probably going to switch to Python 3 at some point within the next few months, but in order to do that, I will first have to learn the differences. I’m not sure if tweepy operates in Python 3, but I’ve heard that twython does.

      Reply
  6. Sean says:
    April 5, 2016 at 4:13 pm

    I am using your script and it is running just fine, except at the end it takes a second photo.

    Reply
  7. Ian Barton says:
    April 8, 2016 at 6:35 am

    Here is a quick way of adding the text using PIL. Note I think PIL itself is no longer maintained, so use pillow instead:

    pip install pillow

    from PIL import Image, ImageDraw, ImageFont

    image = Image.open(photo_path)
    draw = ImageDraw.Draw(image)
    font = ImageFont.truetype(“DejaVuSansMono.ttf”, 20, encoding=”unic”)
    draw.text( (40,728), tweettime, fill=”white”, font=font)
    image.save(photo_path)

    Reply

Leave a Reply to picfish81 Cancel reply

  Tweeted Photos on a Pi from the Cambridge Jam   Jamboree Raspberry Pi Second Birthday
RasPi.TV Site Map - click here

Follow Me

RSS Twitter YouTube

NEW Product

NEW RasPiO® Breadboard Pi Bridge New RasPiO Breadboard Pi Bridge

Pi Ports to Breadboard in Numerical Order

Products Designed by Alex

RasPiO® Night Light - great gift idea! New RasPiO Night Light RasPiO® Analog Zero - Read sensors, make a weather station, thermometer or voltmeter RasPiO Analog Zero

Recent Posts

  • Back up your Garmin activity data on a Raspberry Pi
  • How much power does the Pi4B use? Power Measurements
  • Raspberry Pi 4 launches with BCM2711 quad-core Cortex-A72 64-bit SoC running at 1.5GHz with dual 4K display capability
  • Development of a new product – RasPiO Breadboard Pi Bridge (BBPi)
  • Making a fairly simple bike dashcam with Raspberry Pi – “Live project blog” pt5 Road Testing

Recent Comments

  • Dirk Broer on New Raspberry Pi Family Photo including Pi3A+ plus Zero WH
  • Dirk Broer on New Raspberry Pi Family Photo including Pi3A+ plus Zero WH
  • Peter Capon on Ethernet On Pi Zero – How To Put An Ethernet Port On Your Pi
  • Giles on How to drive a 7 segment display directly on Raspberry Pi in Python
  • Ben on Review of ISO-TECH IDM99III Digital Multimeter
Tweets by @RasPiTV

Categories

  • Electronics
  • Gertboard
  • get_iplayer
  • Input and Output
  • interfacing
  • Laser Cutting
  • Linux usage
  • Mailbag
  • Making
  • Product Launch
  • python programming
  • raspberry pi
  • Raspberry Pi Camera
  • Raspberry Pi Hardware
  • raspberry pihardware
  • RasPiO Duino
  • Review
  • software installation
  • Uncategorized
  • Wemos

Blogroll

  • Makersify
  • Oxford Raspberry Jam
  • Raspberry Pi Foundation
  • Raspberry Pi Spy
  • Raspberry PiPod
  • Robotics and Add-ons
  • See – Adafruit Industries

Archives

  • July 2020
  • June 2019
  • March 2019
  • December 2018
  • July 2018
  • June 2018
  • May 2018
  • March 2018
  • February 2018
  • January 2018
  • November 2017
  • October 2017
  • September 2017
  • July 2017
  • June 2017
  • May 2017
  • March 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
  • October 2016
  • September 2016
  • August 2016
  • July 2016
  • June 2016
  • May 2016
  • April 2016
  • March 2016
  • February 2016
  • January 2016
  • December 2015
  • November 2015
  • October 2015
  • September 2015
  • August 2015
  • July 2015
  • June 2015
  • May 2015
  • April 2015
  • March 2015
  • February 2015
  • January 2015
  • December 2014
  • November 2014
  • October 2014
  • September 2014
  • August 2014
  • July 2014
  • June 2014
  • May 2014
  • April 2014
  • March 2014
  • February 2014
  • January 2014
  • December 2013
  • November 2013
  • October 2013
  • September 2013
  • August 2013
  • July 2013
  • June 2013
  • May 2013
  • April 2013
  • March 2013
  • February 2013
  • January 2013
  • December 2012
  • November 2012
  • October 2012
  • September 2012
  • August 2012
  • July 2012
  • June 2012

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Stats since June 2012

blog posts: 305
word count: 210,404
© 2012-19 RasPi.TV Site Map | Reviews Policy Suffusion theme by Sayontan Sinha