ImageCartoonizer¶

Cartoonizes an image using opencv and python

Uses : OpenCVJupyter NotebookPythonMatplotlibNumPy

All photos are sourced from Wikipedia Commons

In [96]:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
origionalImage = cv.imread("data/Hummingbird.jpg")

#Display Code
plt.imshow(origionalImage)
plt.yticks([])
_ = plt.xticks([])

Color Flattening¶

To start with we'll reduce the number of colors the image uses, to simulate a color palet that would be used by an artist. We'll first blur the image to take out the extra detail, such as those small lines in the feathers. Next, we'll use open cv's kmeans function, this will take all the colors of all pixels in the image, and group them into 16 colors. The rest of the code is for transforming the image into and out of the format this function needs.

In [97]:
numColors = 16
blurredImage = cv.medianBlur(origionalImage,5)

flattenedImage = np.float32(blurredImage).reshape((-1,3))
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 20, 1.0)
_, labels, centers = cv.kmeans(flattenedImage,numColors,None,criteria,10, cv.KMEANS_RANDOM_CENTERS)
centers = np.uint8(centers)
flattenedImage = centers[labels.flatten()]
flattenedImage = flattenedImage.reshape(origionalImage.shape)

#Display Code
plt.imshow(flattenedImage)
plt.yticks([])
_ = plt.xticks([])

Edge Drawing¶

Now we need to simulate drawn edges. First we'll convert the image to grayscale and blur it to remove minor details we don't want drawn. Then we'll use opencv's canny edge detection function. Finally we'll widen the edges.

In [98]:
grayscale = cv.cvtColor(origionalImage,cv.COLOR_BGR2GRAY)
blurred = cv.medianBlur(grayscale,15)
edges = cv.Canny(blurred,50,70)
thin = cv.bitwise_not(edges)
edges = cv.dilate(edges,np.ones((3,3)),iterations=1)
edges = cv.bitwise_not(edges)

#Display Code
fig, axes = plt.subplots(2,2)
fig.set_figheight(10)
fig.set_figwidth(12)
axes[0][0].imshow(grayscale, cmap="gray")
axes[0][0].set_yticks([])
axes[0][0].set_xticks([])
axes[0][0].set_title("Grayscale")
axes[0][1].imshow(blurred, cmap="gray")
axes[0][1].set_yticks([])
axes[0][1].set_xticks([])
axes[0][1].set_title("Blurred")
axes[1][0].imshow(thin, cmap="gray")
axes[1][0].set_yticks([])
axes[1][0].set_xticks([])
axes[1][0].set_title("Canny Edges")
axes[1][1].imshow(edges, cmap="gray")
axes[1][1].set_yticks([])
axes[1][1].set_xticks([])
_ = axes[1][1].set_title("Thickened Edges")

Combination and Final Result¶

In [99]:
#combines the flattened and edges
final = cv.bitwise_and(flattenedImage,flattenedImage,mask= edges)

#Display code
fig, axes = plt.subplots(1,2)
fig.set_figheight(10)
fig.set_figwidth(20)
axes[0].imshow(origionalImage)
axes[0].set_yticks([])
axes[0].set_xticks([])
axes[0].set_title("Origional Image")
axes[1].imshow(final)
axes[1].set_yticks([])
axes[1].set_xticks([])
_ = axes[1].set_title("Result")