Recently, my kid wanted to make a coloring page from a favorite cartoon. My first thought was to use one of the open source programs on Linux that manipulate images, but then I remembered I have no idea how to use any of them. Luckily, I know how to use Jupyter and Python.
How hard can it be, I figured, to use Jupyter for that?
To follow along, you need to have a modern version of Python (if you're a macOS user, you can follow this guide), then install and open Jupyter Labs, which you can learn more about here, and Pillow, a friendly fork of the Python Imaging Library (PIL), with:
$ python -V Python 3.8.5 $ pip install jupyterlab pillow # Installation process ommitted $ jupyter lab
Imagine you want to make a coloring page with an image of a deer. The first step is probably to download a picture of a deer and save it locally. Beware of images with dubious copyright status; it's best to use something with a Creative Commons or other open access license. For this example, I used an openly licensed image from Unsplash and named it
Once you're in Jupyter Lab, start by importing
from PIL import Image
With these preliminaries out of the way, open the image then look at the image size:
pic = Image.open("deer.jpg")
Wow, this is a bit of sticker shock—high-resolution pictures are fine if you want to make a delightful book about deer, but this is probably too big for a homemade coloring book page. Scale it waaaaaaay down. (This kindness is important so that this article loads fast in your browser, too!)
x, y = pic.size x //= 10 y //= 10 smaller = pic.resize((x, y))
This reduced the scale of the image by 10. See what that looks like:
Beautiful! Majestic and remote, this deer should be a breeze for an edge-detection algorithm. Speaking of which, yes, that's the next step. You want to clean up the image so coloring will be is a breeze, and thankfully there's an algorithm for that. Do some edge detection:
from PIL import ImageFilter edges = smaller.filter(ImageFilter.FIND_EDGES)
This is probably the most important step. It removes all the extraneous details and leaves clear lines. The color is a little weird, but this is not a hard problem to solve. Split the image into its color bands, and choose the one where the lines are crispest:
bands = edges.split()
The lines are clear now, but this is not a good image to print because your printer will run out of ink, and your kid will not be happy coloring on black. So invert the colors. While you're at it, snap the colors to max-black or max-white to make the lines even crisper by using a lambda function call:
outline = bands.point(lambda x: 255 if x<100 else 0)
The original image had a lot of nature that I mercilessly cleared. Now there's a lot of empty space, so crop the picture to the essentials:
outline.crop((10, 200, 300, 400))
All that's left is to save the picture as something easy to print, like a PDF:
I'll let you figure out how to print from Linux.
Have fun making homemade coloring books for your kids!
Comments are closed.