<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Blog CS</title>
<subtitle>A Repository of Things</subtitle>
<link href="http://oldblog.cubittsmith.co.uk/feed.php" rel="self" />
<id>http://oldblog.cubittsmith.co.uk/feed.php</id>
<updated>2015-04-08T16:21:06+00:00</updated>
<entry>
<title type="html">Scraping Weather Data</title>
<content type="html">&lt;p&gt;We recently had a requirement for UK weather data. A little digging around revealed that hourly weather observation data is available, free of charge from the UK met office, via the &lt;a href=&quot;http://data.gov.uk/metoffice-data-archive&quot;&gt;uk gov open data site&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;However, this link above only gives one hour or results at a time, which is a little restrictive...&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://oldblog.cubittsmith.co.uk/content/public/upload/weatherform_0_o.png&quot; alt=&quot;undefined&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Then I took a look at the met office&#039;s own API (Datapoint), which is &lt;a href=&quot;http://www.metoffice.gov.uk/datapoint/product/uk-hourly-site-specific-observations/detailed-documentation&quot;&gt;supposed to provide data for a given datetime for it&#039;s weather stations&lt;/a&gt;.Unfortunately, although I could get xml/json data feeds from the api, every time I polled for data before today, it returned &#039;no matching records&#039;.&lt;/p&gt;
&lt;p&gt;In the end I decided to write the following python script to loop through every day and hour I was interested in on the data gov site, and pull back the csvs into one folder so I could get the full dataset. &lt;/p&gt;
&lt;p&gt;Click &lt;a href=&quot;https://gist.github.com/willycs40/10e5f3627e28fb3a21d8&quot;&gt;here to see the code in gist&lt;/a&gt; or else click permalink below, where I have included the code.&lt;/p&gt;
&lt;p&gt;&lt;!-- pagebreak --&gt;&lt;/p&gt;
&lt;p&gt;
&lt;script src=&quot;https://gist.github.com/willycs40/10e5f3627e28fb3a21d8.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;</content>
<link href="http://oldblog.cubittsmith.co.uk/index.php?controller=post&amp;amp;action=view&amp;amp;id_post=46" />
<id>http://oldblog.cubittsmith.co.uk/index.php?controller=post&amp;amp;action=view&amp;amp;id_post=46</id>
<updated>2015-04-08T16:21:06+00:00</updated>
<category term="General"/>
</entry>
<entry>
<title type="html">SonArtPi (Part II: The Application)</title>
<content type="html">&lt;p&gt;&lt;a href=&quot;/index.php?controller=post&amp;amp;action=view&amp;amp;id_post=43&quot;&gt;Sonart is my project to control Sonos / Spotify directly via a camera and album covers.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I got the application up and running last night, and it works a charm. I have just pushed the initial code to github, and you can find it here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/willycs40/sonart/tree/master&quot;&gt;https://github.com/willycs40/sonart/tree/master&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I plan to make some updates to clean up the code, and also add some scripts for viewing and updating the record library. But for now, it works a charm, and I put on a playlist this morning using it!&lt;/p&gt;</content>
<link href="http://oldblog.cubittsmith.co.uk/index.php?controller=post&amp;amp;action=view&amp;amp;id_post=45" />
<id>http://oldblog.cubittsmith.co.uk/index.php?controller=post&amp;amp;action=view&amp;amp;id_post=45</id>
<updated>2015-04-07T10:46:42+00:00</updated>
<category term="General"/>
</entry>
<entry>
<title type="html">SonArtPi (Part I: The Setup)</title>
<content type="html">&lt;p&gt;&lt;a href=&quot;/index.php?controller=post&amp;amp;action=view&amp;amp;id_post=43&quot;&gt;Sonart is my project to control Sonos / Spotify directly via a camera and album covers.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Since building the POC (see my last post above), I wanted to make this a permanent capability for my Sonos set up. I decided to build a &#039;production&#039; version, on top of Raspberry Pi hardware. This post is about how I got the pi fully set up for computer vision.&lt;/p&gt;
&lt;p&gt;I chose a Raspberry Pi 2 (as I&#039;ll need as much processing power as possible to process the images quickly), and also bought the official Pi Camera, and a case that could hold the whole thing. After having assembled the Pi, camera and case, and plugging in all the relevant cables, I powered it up and installed Raspbian through Noobs, making sure to enable the camera module in raspi-config.&lt;/p&gt;
&lt;p&gt;From there I started to follow various guides to &lt;a href=&quot;http://www.raspberrypi.org/help/camera-module-setup/&quot;&gt;install and &lt;/a&gt;&lt;a href=&quot;http://www.raspberrypi.org/help/camera-module-setup/&quot;&gt;test the camera&lt;/a&gt;, &lt;a href=&quot;http://simplecv.readthedocs.org/en/latest/HOWTO-Install%20on%20RaspberryPi.html?highlight=opencv&quot;&gt;get SimpleCV installed&lt;/a&gt; and deploy my Sonart application. I&#039;d like to say things worked perfectly, but unsurprisingly I came up against a number of issues! In this post I&#039;ve detailed those issues, and how I managed to fix them. I&#039;ve also included the happy-path code for anyone who wants to avoid the problems!&lt;/p&gt;
&lt;p&gt;Click permalink below to see the rest!&lt;/p&gt;
&lt;p&gt;&lt;!-- pagebreak --&gt;&lt;/p&gt;
&lt;p&gt;Installation Issues&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The first time I tried to use the camera on the pi, it didn&#039;t work. I tried to take a simple still from the command line by running:&lt;br /&gt;
&lt;pre&gt;&lt;code data-language=&quot;generic&quot;&gt;raspistill -n -t 300 -o test.jpg&lt;/code&gt;&lt;/pre&gt;
Breaking this down:&lt;br /&gt; * Take a still (raspistill)&lt;br /&gt; * Don&#039;t show a preview window because I haven&#039;t loaded the GUI (-n)&lt;br /&gt; * Don&#039;t wait the default 5 seconds before taking the photo, just wait 300 ms to let the camera start (-t 300)&lt;br /&gt; * Write the image to this directory and call it test.jpg (-o test.jpg)&lt;br /&gt;&lt;br /&gt;Unfortunately, it didn&#039;t work and I got a weird error instead. It turns out I had forgotten to upgrade my raspbian installation, and the version that had come shipped with my pi wasn&#039;t new enough to know about the camera. Nothing a quick &#039;sudo apt-get upgrade&#039; won&#039;t fix, I thought. Unfortunately however, the upgrade process got about half way through before spewing out the message &#039;segmentation fault&#039;. At this point my raspbian installation was ruined, and wouldn&#039;t respond or reboot.&lt;br /&gt;&lt;br /&gt;Fortunately, the solution was fairly quick: Hold shift as you restart the pi, taking you back to the noobs recovery image. From there I reinstalled a fresh raspbian, and on loading that, I ran &#039;sudo apt-get update&#039;, then &#039;sudo apt-get upgrade&#039; as the first two commands, which worked this time. After that I tested the camera with &#039;raspistill&#039; and it worked perfectly! I was impressed by the image quality.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Later in the process, I followed the guide to install simpleCV and ipython, but also supplemented that by installing ipython-notebook, as I knew this would allow me to see images from the pi directly (even though I wasn&#039;t using the GUI), through the notebook web interface. &lt;br /&gt;&lt;br /&gt;After installing notebook, I opened server, telling it to allow me to connect from anywhere on the network, and supressing the default behaviour to open a browser on the pi:&lt;br /&gt;ip
&lt;pre&gt;&lt;code data-language=&quot;generic&quot;&gt;ipython-notebook --ip=&#039;*&#039; --no-browser&lt;/code&gt;&lt;/pre&gt;
Then I tried the boilerplate code to read in the test.jpg image I made with the camera, and display it in the notebook:&lt;br /&gt;
&lt;pre&gt;&lt;code data-language=&quot;python&quot;&gt;from SimpleCV import *
disp = Display(displaytype=&#039;notebook&#039;)

img = Image(&#039;test.jpg&#039;)
img.save(disp)&lt;/code&gt;&lt;/pre&gt;
Unfortunately, the code errored on the &#039;disp = Display&#039; line, with the error that it was &#039;unable to open a console terminal&#039;, from line 163 of Display.py in the SimpleCV module. I decided to take a look at the offending code, so went to find the SimpleCV module files on the system:&lt;br /&gt;
&lt;pre&gt;&lt;code data-language=&quot;generic&quot;&gt;cd /usr/local/lib/python2.7/dist-packages/SimpleCV
sudo nano Display.py&lt;/code&gt;&lt;/pre&gt;
I navigated to line 163, and could see that it seemed to be trying to set a display icon, which seemed pretty redundant - so I tried the simplest possible solution of commenting it out.&lt;br /&gt;&lt;br /&gt;Having reloaded the module in python, I ran the SimpleCV code again, and hey presto, my image appeared.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;This was the hardest one. After checking that SimpleCV was working, and that I could load and display an image, I next tested SimpleCV&#039;s findKeypoints() function, by trying to open an image, draw on it&#039;s keypoints, and then show it in the notebook:&lt;br /&gt;
&lt;pre&gt;&lt;code data-language=&quot;python&quot;&gt;from SimpleCV import *&lt;br /&gt;disp = Display(displaytype=&#039;notebook&#039;)&lt;br /&gt;
img = Image(&#039;test.jpg&#039;)
kp = img.findKeypoints()
kp.draw()
img.save(disp)&lt;/code&gt;&lt;/pre&gt;
Disaster. I got another Seg Fault, this one originating from pygame. A bit of googling had me try moving to the develop branch of SimpleCV (no luck), and then deciding I needed to upgrade my opencv installation.&lt;br /&gt;&lt;br /&gt;I had installed opencv with a simple &#039;sudo apt-get install python-opencv&#039;. I checked the version by running the following in python:&lt;br /&gt;
&lt;pre&gt;&lt;code data-language=&quot;generic&quot;&gt;import cv2
cv2.__version__&lt;/code&gt;&lt;/pre&gt;
It returned version 2.4.1. The posts I read were indicated that moving to version 2.4.4 would fix this bug - however this meant building from source. First I ran &#039;sudo apt-get remove python-opencv&#039; to get rid of the old version. Then I followed OpenCV&#039;s build process (you can see the code below in the happy-path).&lt;br /&gt;&lt;br /&gt;Alas, the first time I ran the build, it failed, having run out of space at 42%... I ran &#039;build clean&#039; to remove the progress, and noted that I had tried to do the build with about 500mb space free. I then removed some other files from the Pi, so that there was 2.4Gb free, and ran the build again. &lt;br /&gt;&lt;br /&gt;After several hours, I re-ran the __version__ code above, and following that re-ran the keypoint code. What happened!?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, finally, here is my happy-path code to get a fresh raspbian install on a Pi 2 ready for some computer vision:&lt;/p&gt;
&lt;pre&gt;&lt;code data-language=&quot;python&quot;&gt;# upgrade the distro so that the pi camera module works
sudo apt-get update
sudo apt-get upgrade

# install all the python basics (Relative to the &#039;official&#039; instructions, I&#039;ve added ipython-notebook to this list, and taken away python-opencv)
sudo apt-get install ipython ipython-notebook python-scipy python-numpy python-setuptools python-pip

# install the latest develop branch simplecv
mkdir ~/simplecv_code
cd ~/simplecv_code
git clone git://github.com/sightmachine/SimpleCV.git
cd SimpleCV
sudo pip install -r requirements.txt
sudo python setup.py develop

# build and install the latest stable opencv release
mkdir ~/opencv_code
cd ~/opencv_code
wget http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/2.4.10/opencv-2.4.10.zip/download
unzip download
cd opencv-2.4.10
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_NEW_PYTHON_SUPPORT=ON -D BUILD_EXAMPLES=ON ..
screen
make
sudo make install
sudo sh -c &#039;echo &quot;/usr/local/lib&quot; &amp;gt; /etc/ld.so.conf.d/opencv.conf&#039;
sudo ldconfig

# test that it&#039;s all working by opening up ipython notebook&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note the &#039;screen&#039; command above. I realised the make was going to take a *long* time, when it was at 2% after 10 minutes. I also knew that I was accessing my pi via ssh, and that the connection wasn&#039;t great and had already flaked out a few times. Because I wanted to leave the &#039;make&#039; command to do it&#039;s thing, I quick installed &#039;&lt;a href=&quot;https://www.howtoforge.com/linux_screen&quot;&gt;screen&lt;/a&gt;&#039; (sudo apt-get install screen), and then loaded a session before calling make. This allows me to disconnect from the terminal session, but still leave it running. If I lost connection, it meant I could ssh back in, and then re-attach to the screen session I&#039;d left running. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&#039;screen&#039;, followed by spacebar, opens a new screen.&lt;/li&gt;
&lt;li&gt;ctrl + a, followed by d, detaches the screen&lt;/li&gt;
&lt;li&gt;&#039;screen -r&#039; reattaches to the screen&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;/p&gt;</content>
<link href="http://oldblog.cubittsmith.co.uk/index.php?controller=post&amp;amp;action=view&amp;amp;id_post=44" />
<id>http://oldblog.cubittsmith.co.uk/index.php?controller=post&amp;amp;action=view&amp;amp;id_post=44</id>
<updated>2015-04-03T22:41:49+00:00</updated>
<category term="General"/>
</entry>
<entry>
<title type="html">Sonart (controlling Sonos and Spotify using album art)</title>
<content type="html">&lt;p&gt;I have &lt;a href=&quot;http://www.sonos.com/en-gb/system&quot;&gt;Sonos&lt;/a&gt; speakers in my flat. In combination with &lt;a href=&quot;https://www.spotify.com/uk/&quot;&gt;Spotify&lt;/a&gt;, this allows me to play just about whatever music I want, in whichever rooms of the flat, simply by opening the Sonos app on my phone and searching for the artist. The biggest challenge is deciding what to listen to.&lt;/p&gt;
&lt;p&gt;I also have a record player in my flat, and a number of vinyl records, in nice sleeves with nice cover art. Even though putting on a record is much less convenient than opening Sonos on my phone, I still get a lot from having them around - primarily the ability to wonder over and flick through a big pile of album art to help decide what I want to listen to: something which is lost by music streaming services.&lt;/p&gt;
&lt;p&gt;I had an idea for how I could combine the two; keep the convenience and low cost of music streaming, but also retain a physical presence for my music collection (in my case a pile of records).&lt;/p&gt;
&lt;p&gt;The solution is built using a webcam and some Python code (using SimpleCV, SoCo libraries) - take a look at it in action:&lt;/p&gt;
&lt;p&gt;&lt;iframe src=&quot;http://www.youtube.com/embed/nQ_vmYI_xAY&quot; width=&quot;425&quot; height=&quot;350&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt;Click permalink below to get to the code...&lt;/p&gt;
&lt;p&gt;&lt;!-- pagebreak --&gt;&lt;/p&gt;
&lt;p&gt;As you&#039;ll see below, the code is fairly concise. The basic premise is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Load in a configuration file. This lists the name, album cover and Spotify track/album reference for each record cover.&lt;/li&gt;
&lt;li&gt;Pull images from a camera (in my case I&#039;m using an old iPhone running ipCam. (When I visit &#039;http://192.168.1.65/image.jpg&#039; on my network, it returns an image from the camera.)&lt;/li&gt;
&lt;li&gt;Using the SimpleCV/OpenCV keypoint matching functionality, test the retrieved image to see if there is a match to one of the cover art images.&lt;/li&gt;
&lt;li&gt;If there is a match, use the SoCo library to play the corresponding referenced track or album.&lt;/li&gt;
&lt;li&gt;Wait half a second, and try again.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&#039;s the code:&lt;/p&gt;
&lt;pre&gt;&lt;code data-language=&quot;python&quot;&gt;# In[1]:

from SimpleCV import *
import soco
import json
disp = Display(displaytype=&#039;notebook&#039;)
sonos = soco.SoCo(&#039;192.168.1.82&#039;)


# In[15]:

import warnings
warnings.filterwarnings(&quot;ignore&quot;)


# In[13]:

file_location = r&#039;C:\Users\will\Documents\Projects\Sonart&#039;
camera_location = r&#039;http://192.168.1.65/image.jpg&#039;
timer_duration = 0.5


# In[3]:

# open the config file and read in the images

with open(file_location + r&quot;\config.json&quot;, &#039;r+&#039;) as f:
    config = json.load(f) 
    
for artist in config:
    image_location = os.path.join(file_location, &#039;Covers&#039;, artist[&#039;cover&#039;])
    artist[&#039;img&#039;] = Image(str(image_location))


# In[18]:

from IPython.display import clear_output
while True:
    
    try:
        img = Image(camera_location)
    except:
        print(&quot;Cannot acquire image. Quitting&quot;)
        break
    
    for artist in config:
        match = img.findKeypointMatch(artist[&#039;img&#039;], minDist=0.15)

        if match is not None:
            clear_output()
            print(&#039;Recognised {0}&#039;.format(artist[&#039;artist&#039;]))
            sonos.play_uri(artist[&#039;metadata&#039;][&#039;uri&#039;], artist[&#039;metadata&#039;][&#039;metadata&#039;], artist[&#039;metadata&#039;][&#039;title&#039;])
    
    time.sleep(timer_duration)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I intend to get this cleaned up into a repo soon, including functions to help build the config file. For now though, if you want to try it out, I suggest you start by pulling the sightmachine/simpleCV docker image, and running the code from there.&lt;/p&gt;
&lt;p&gt;The configuration file which is loaded includes three attributes for each config item: the name, the name of the cover art file on disk, and a stored reference to the Sonos/Spotify track metadata. I got the reference by putting on the right track using the normal Sonos controller, and then calling &#039;sonos.get_current_track_info()&#039; and saving it to the config file.&lt;/p&gt;</content>
<link href="http://oldblog.cubittsmith.co.uk/index.php?controller=post&amp;amp;action=view&amp;amp;id_post=43" />
<id>http://oldblog.cubittsmith.co.uk/index.php?controller=post&amp;amp;action=view&amp;amp;id_post=43</id>
<updated>2015-03-29T23:19:31+00:00</updated>
<category term="Data Science"/>
</entry>
</feed>