<jupyter_start><jupyter_text>Mosaic ArtWe would like to use images as mosaic pieces to build a bigger image.Data originally comes from [here](https://www.kaggle.com/thedownhill/art-images-drawings-painting-sculpture-engraving).<jupyter_code>from os import listdir
from os.path import isfile, join

import numpy as np
import pandas as pd
from PIL import Image

from lets_plot import *
LetsPlot.setup_html()
def get_grayscale_img(filepath):
    if not isfile(filepath):
        return None
    img = Image.open(filepath)
    if not img.mode in ['RGB', 'L']:
        return None
    return img.convert('L')
WIDTH, HEIGHT = 20, 20
IMAGES_PATH = 'images/sculpture'
data = []
for f in listdir(IMAGES_PATH):
    img = get_grayscale_img(join(IMAGES_PATH, f))
    img = img.resize((WIDTH, HEIGHT))
    image_data = np.asarray(img).reshape(WIDTH * HEIGHT)
    image_agg_data = np.array([np.round(image_data.mean()), np.round(image_data.std())])
    data.append(np.concatenate((image_agg_data, image_data), axis=0).astype(int))
df = pd.DataFrame(data)
df = df.rename(columns={0: 'color', 1: 'std'})
df = df.sort_values(by=['color', 'std']).reset_index(drop=True)
ggplot() + \
    geom_bar(aes(x='color', fill='color'), data=df, sampling=sampling_pick(n=256)) + \
    scale_fill_gradient(low='black', high='white') + \
    ggtitle('Gray Color Distribution')
for missing_color in set(range(256)) - set(df.color.unique()):
    df = df.append([dict(color=missing_color)])
df = df.sort_values(by='color').reset_index(drop=True)
df = df.fillna(method='pad').fillna(method='backfill')
img = get_grayscale_img(join(IMAGES_PATH, 'i - 663.jpeg'))
img = img.resize((80, 80))
rows = ()
for row in np.asarray(img):
    cols = ()
    for color in row:
        subimg = df[df.color == color].iloc[0, 2:].to_numpy().reshape(WIDTH, HEIGHT)
        cols = cols + (subimg,)
    rows = rows + (np.hstack(cols),)
image_data = np.vstack(rows)
ggplot() + \
    geom_image(image_data=image_data) + \
    ggsize(800, 800) + \
    ggtitle('Mosaic Image') + \
    theme_classic() + theme(axis='blank')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15957955088389872, 'fraction_numerical': 0.013377926421404682, 'mean_word_length': 4.554376657824934, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '331459', 'license': 'MIT', 'n_tokens_mistral': 804, 'n_tokens_neox': 763, 'n_words': 157, 'path': 'source/examples/demo/mosaic_image.ipynb', 'repo_name': 'JetBrains/lets-plot-docs', 'size': '2093'}