shirt color = desktop background in 10 lines of code
Tags: linux, python
Published: 2020-07-14 12:03:50


here's a shower-thought:

imagine firing up your laptop, and the background changes to your dress color! and it actually ended up being doable in Ubuntu (18.04) but this should hopefully work fine in any Linux distribution. 

And boy, does it put a smile on my face 

{% vimeo 437604553 %}


**the idea is straightforward : make the webcam click a picture, crop to where a shirt generally is (in a picture), find the dominant color in it and set it to the background.**

**Step 1**: Make the webcam click a picture
i use mplayer for this, and i've found vlc and ffmpeg to work fine as well. Here's the one liner for mplayer that clicks three pictures:
`mplayer tv:// -tv driver=v4l2:device=/dev/video0:width=100:height=100 -frames 3 -vo jpeg:outdir=/home/vaze/vez`

This puts three images, by the name 00000001.jpg, 00000002.jpg, 00000003.jpg in the specified **outdir** directory. Sweet!
(Replace the `/home/vaze/vez` with your directory name)

-frames is set to 3 because it gives the camera enough time to start and not mess up the lighting. Experiment with the width and height as well; i set it to a hundred but i think the final image still had a size of 176x144, so that's probably a limit or something

**Step 2**: Crop to where the shirt is
i've done this in Python, using a library called Pillow. Here's the [Installation guide](https://pillow.readthedocs.io/en/stable/installation.html)
It makes handling images super easy. Let's leave this step here for now, we'll come back to it in a moment

**Step 3**: Find the dominant color in the image

This is the interesting bit! there are so many ways you could approach this, depending on what kind of result you want.
i resized the cropped image (which consisted only the shirt color) just to *one* pixel (again, using Pillow), and that method approximated the true color real quick. More ideas from [this](https://stackoverflow.com/questions/3241929/python-find-dominant-most-common-color-in-an-image) nice StackOverflow answer.

**Step 4**: Setting an image to the the background

this command takes the file name(the three '///' is important) as input and sets it to the background. I use gnome, so that's the name of my desktop background. If you use, say Mint, replace the 'gnome' with 'cinnamon' and so on.

`gsettings set org.gnome.desktop.background picture-uri file:///home/vaze/vez/back.jpg`

Cool, we have the pieces ready. Let's put them together in a script:
```
#!/usr/bin/python3
from PIL import Image;
import subprocess as s

com = 'mplayer tv:// -tv driver=v4l2:device=/dev/video0:width=100:height=100 -frames 3 -vo jpeg:outdir=/home/vaze/vez'
comb = 'gsettings set org.gnome.desktop.background picture-uri file:///home/vaze/vez/back.jpg'
path = '/home/vaze/vez/00000001.jpg'
save = '/home/vaze/vez/back.jpg'

s.call(com, shell=True)
im = Image.open(path)
w, h = im.size
im = im.crop((50, h - 10, w-50, h)).resize((1, 1), resample=0)
im.save(save)
s.call(comb, shell=True)

```
let's go over this line by line:
`#!/usr/bin/python3`
this is important as we're soon going to be making this file *executable*. The kernel needs to know what language to execute the script in (python3 in this case, the she-bang is some kind of a 'hey look! the language to read this in is : ')

`import subprocess as s`
the subprocess module can be used to call terminal commands right from python, using `subprocess.call("command goes here")`.

`s.call(com, shell=True)`

first we're calling the command 'com' (i assigned it to the mplayer-fire-the-webcam thingy)
Also commands didn't work without the `shell=True` bit and i'm not quite sure why yet.


`im = Image.open(path)`

On this next line, i import the image that was just clicked (i can do that because i know what name it will be saved with. neat!)

`w, h = im.size`

sets the width of the image to the variable w and height to h

`im = im.crop((50, h - 10, w-50, h)).resize((1, 1), resample=0)`

we crop it with the tuple `(50, h-10, w-50, h)` which corresponds to top left corner and bottom right corner of whatever region you're cropping in pixels. This seemed to work in the location i sit it,for my shirt is generally in that region, but if you're a fan of hats and want the background to be your hat color, crop to the top bit :)

next we chain it with the resize method, and make it one single pixel, using the nearest neighbour filter (resample = 0 sets it to this (that is because it accepts a whole bunch of [filters](https://kite.com/python/docs/PIL.Image.Image.resize), feel free to experiment!)).

`im.save(save)`

save this image to wherever you want to, i saved it in the same directory as this script

`s.call(comb, shell=True)`

finally, we call the background-setter code! (see that the 'comb' variable is set to the same location as the 'save')

now all that's left to do is to make this executable. First save it as some file (say script.py) and go into the terminal and type:
```
cd directory_where_the_script_is_saved
chmod +x script.py
```
now anytime you want to use this script, go in the terminal and type:
```
./directoryName/script.py
```

i made a handy alias for this (as seen in the video) called color, and you can make this by going into the `.bash_aliases` file and adding this line: (note the dot)

```
nano .bash_aliases
(text editor opens up, go to the last line and type: )
alias color='./directoryName/script.py'

```

you can make this script run automatically on boot very easily in Ubuntu:

Go to Startup Applications (just type it out in the app drawer) and put our `./directoryName/script.py` in the section for adding commands.(i'm not sure why but inserting the alias wasn't working)
like so:

![startup script](https://dev-to-uploads.s3.amazonaws.com/i/w97fvlkxzbb5adp8ybo5.png)


There we have it! on boot-up your webcam should wink with a little flash and dress itself like you :)