Using Python, OpenCV2, take an image and pixel-ize it without Photoshop (with apologies to Calvin and Hobbes – Transmogrifier).
I challenged myself to do something creative, something that might look interesting, without using the obvious tools.
I decided I wanted to pixelize images, without making them any smaller, with a command line tool.
Like any good developer, I looked for prior art and as often happens, landed on a Stack Overflow article where someone had done all the heaving lifting already.
In the tradition of Good artists borrow, Great artists steal, let’s use that, review it and polish it up.
The following are assumptions and dependencies:
- MacOS, 12.6 (Monterey)
- Python3, 3.10.6
- OpenCV, 4.6.0
MacOS will be used in the instructions, but any OS should work.
Install Python 3, OpenCV
Installing Python 3 is out of scope of this document, but either download the installer from:
Or use brew:
brew install python3
To confirm it is installed correctly run:
python3 -V Python 3.10.6
brew install opencv
Grab the script here:
Let’s go through it and see what it does.
Imports and argparse
#!/usr/local/bin/python3 import argparse from typing import List import cv2 parser = argparse.ArgumentParser(description='Take an image and pixel-ize it.') parser.add_argument('-i', type=str, required=False, default='input.jpg', help='input image file') parser.add_argument('-o', type=str, required=False, default='output.jpg', help='output jpg filename, defaults to "output.svg"') # TODO: Add image height and width dimension arguements args = parser.parse_args() print('Input filename: ', args.i) print('Output filename: ', args.o)
Typical imports, the important ones are argparse and cv2.
Using argparse will allow us to parse the command line arguements and set some sensible defaults.
The cv2 import, imports the OpenCV2 library, which will manage the processing of the input image.
# Input image input = cv2.imread(args.i) # Get input size height, width = input.shape[:2] # Desired "pixelated" size w, h = (64, 64) # Resize input to "pixelated" size temp = cv2.resize(input, (w, h), interpolation=cv2.INTER_LINEAR) # Initialize output image output = cv2.resize(temp, (width, height), interpolation=cv2.INTER_NEAREST) # Write to file cv2.imwrite(args.o, output) cv2.imshow('Input', input) cv2.imshow('Output', output) cv2.waitKey(0)
Next, the input image argument is parsed and the size of the image is parsed. The desired ‘pixelated’ size is hard coded.
The next steps use the OpenCV2 linear interpolation to down sample the input image (basically pixelize it) and then blow it back up to the original size. The resizing down and backup results in the input image being pixelized.
The last steps are using OpenCV2 to write the output file.
The Mona Lisa is a good test image, well recognized even when pixelated:
Mona Lisa (Wikipedia)
pixelmogrifier.py script into a working directory, create two folders
input-images and output-images in that directory
Copy the input file into
input-images and run the script:
./pixelify.py -i ./input-images/mona-lisa.jpg -o ./output-images/mona-lisa.jpg
I also ran some paintings by Van Gough and Monet through, but the impressionists don’t look as interesting (because they are sort of ‘pixelated’ already?)
Here is the result, it a large version of the Pixel Mona Lisa:
Mona Lisa Pixelized (3 MB)
Bit of a long write up for what is a very simple script, but these sort of building blocks can be coupled together to create more interesting projects.