DEV Community

Cover image for shirt color = desktop background in 10 lines of code
Aaradhya Vaze
Aaradhya Vaze

Posted on • Edited on

shirt color = desktop background in 10 lines of code

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

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
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 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)

Enter fullscreen mode Exit fullscreen mode

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, 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
Enter fullscreen mode Exit fullscreen mode

now anytime you want to use this script, go in the terminal and type:

./directoryName/script.py
Enter fullscreen mode Exit fullscreen mode

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'

Enter fullscreen mode Exit fullscreen mode

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

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

Top comments (2)

Collapse
 
michaeltharrington profile image
Michael Tharrington

Cool! This is a fun idea. 😀

Collapse
 
vez profile image
Aaradhya Vaze

thank you!