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.
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)
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")
ʻ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))
It's becoming more like a painting.
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))
If you want to get more bleeding, repeat "monotonic → Gaussian blur" more, but this time it should be about this.
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")
Finally, combine these two to complete.
ImageChops.multiply(color_img, line_img)
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.
Recommended Posts