[PYTHON] Make your photos pictorial with Pillow's Mode Filter

Now that I know how to use pillow's ʻImageFilter.ModeFilter` effectively, I'll use it to create a painting-like filter. I don't use numpy etc., only pillow.

The original image

mono.jpg

After conversion

ダウンロード (1).png

This is the only source.

from PIL import Image, ImageChops, ImageOps, ImageFilter

img = Image.open("test.jpeg ")
qant_img = img.quantize(8, kmeans=True).convert("RGB")

t = qant_img
t = t.filter(ImageFilter.ModeFilter(12))
t = t.filter(ImageFilter.GaussianBlur(5))
t = t.filter(ImageFilter.ModeFilter(12))
t = t.filter(ImageFilter.GaussianBlur(1))
color_img = t.convert("RGB")

gray = img.convert("L")
gray2 = gray.filter(ImageFilter.MaxFilter(5))
line_inv = ImageChops.difference(gray, gray2)
line_img = ImageOps.invert(line_inv).convert("RGB")

ImageChops.multiply(color_img, line_img)
2017/02/24 There was an error in the source, so I fixed it

Commentary

Color reduction

First of all, if the number of colors is large, it will be difficult to make a painting-like color, so the color will be reduced. Use ʻImage.quantize` for color reduction. The number of colors can be any number, but the smaller the number of colors, the solider the color. Here, the kmeans method is used to reduce the colors to eight. For images with a large number of colors, it may be better to use 16 to 32 colors.

qant_img = img.quantize(8, kmeans=True).convert("RGB")

ダウンロード.png

Make a fill image

ʻImageFilter.ModeFilter` has not been used until now, but when applied, the color becomes monotonous. Since the convolution operation that selects the mode in the kernel window is performed, the color area expands.

t = qant_img.filter(ImageFilter.ModeFilter(12))

ダウンロード (1).png

It's becoming more like a painting.

Alternating Gaussian blur and monotonization

This time, I want to express "bleeding", so I will add Gaussian blur to make it monotonous again. If you repeat "monotonization → Gaussian blur", the image will bleed more and more. Finally, lightly apply Gaussian blur to make it look a little blurry.

t = t.filter(ImageFilter.GaussianBlur(5))
t = t.filter(ModeFilter(12))
t = t.filter(ImageFilter.GaussianBlur(1))

ダウンロード (2).png

If you want to get more bleeding, repeat "monotonic → Gaussian blur" more, but this time it should be about this.

Make a line art

Finally, create a line art from the original image, the algorithm is based on here. Although this method is simple, it is recommended because it can generate very beautiful line art.

gray = img.convert("L")
gray2 = gray.filter(ImageFilter.MaxFilter(5))
line_inv = ImageChops.difference(gray, gray2)
line_img = ImageOps.invert(line_inv).convert("RGB")

ダウンロード (3).png

Combine fill image and line art

Finally, combine these two to complete.

ImageChops.multiply(color_img, line_img)

ダウンロード (4).png

Summary

If you adjust the parameters a little more, you may be able to express it more beautifully. The combination of ʻImageFilter.ModeFilter` and Gaussian blur causes "bleeding", so I think it can be used for something.

After all, parameter adjustment is necessary, and if the value of ʻImageFilter.ModeFilter` is set to about 5," bleeding "will be softened.

ダウンロード (8).png

Recommended Posts

Make your photos pictorial with Pillow's Mode Filter
Make a filter with a django template
Try to make your own AWS-SDK with bash
Make your own module quickly with setuptools (python)
Make your own music player with Bottle0.13 + jPlayer2.5!
Make your Python environment "easy" with VS Code