{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Mosaic Art\n", "\n", "We would like to use images as mosaic pieces to build a bigger image.\n", "\n", "Data originally comes from [here](https://www.kaggle.com/thedownhill/art-images-drawings-painting-sculpture-engraving)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2024-04-17T07:38:47.101204Z", "iopub.status.busy": "2024-04-17T07:38:47.101000Z", "iopub.status.idle": "2024-04-17T07:38:47.415427Z", "shell.execute_reply": "2024-04-17T07:38:47.415108Z" } }, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "\n", "from lets_plot import *" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2024-04-17T07:38:47.417119Z", "iopub.status.busy": "2024-04-17T07:38:47.416982Z", "iopub.status.idle": "2024-04-17T07:38:47.419198Z", "shell.execute_reply": "2024-04-17T07:38:47.419021Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", " \n", " " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "LetsPlot.setup_html()" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2024-04-17T07:38:47.432396Z", "iopub.status.busy": "2024-04-17T07:38:47.432297Z", "iopub.status.idle": "2024-04-17T07:38:47.434623Z", "shell.execute_reply": "2024-04-17T07:38:47.434444Z" } }, "outputs": [], "source": [ "def get_img_or_none_by_index(i):\n", " import io\n", " from os.path import isfile, join\n", " import requests\n", " from PIL import Image\n", "\n", " TIMEOUT = 5\n", " IMAGES_PATH = \"images/sculpture\"\n", " IMAGES_URL = \"https://github.com/JetBrains/lets-plot-docs/raw/master/source/examples/demo/images/sculpture\"\n", "\n", " filepath = join(IMAGES_PATH, \"{0}.jpg\".format(i))\n", " if isfile(filepath):\n", " return Image.open(filepath)\n", " filepath = join(IMAGES_PATH, \"{0}.jpeg\".format(i))\n", " if isfile(filepath):\n", " return Image.open(filepath)\n", " r = requests.get(\"{0}/{1}.jpg\".format(IMAGES_URL, i), timeout=TIMEOUT)\n", " if r.status_code == requests.codes.ok:\n", " return Image.open(io.BytesIO(r.content))\n", " r = requests.get(\"{0}/{1}.jpeg\".format(IMAGES_URL, i), timeout=TIMEOUT)\n", " if r.status_code == requests.codes.ok:\n", " return Image.open(io.BytesIO(r.content))\n", " return None" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2024-04-17T07:38:47.435643Z", "iopub.status.busy": "2024-04-17T07:38:47.435498Z", "iopub.status.idle": "2024-04-17T07:38:47.436995Z", "shell.execute_reply": "2024-04-17T07:38:47.436819Z" } }, "outputs": [], "source": [ "def get_grayscale_img_or_none(img):\n", " if img is None:\n", " return None\n", " if img.mode not in ['RGB', 'L']:\n", " return None\n", " return img.convert('L')" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2024-04-17T07:38:47.437848Z", "iopub.status.busy": "2024-04-17T07:38:47.437773Z", "iopub.status.idle": "2024-04-17T07:38:47.439116Z", "shell.execute_reply": "2024-04-17T07:38:47.438943Z" } }, "outputs": [], "source": [ "WIDTH, HEIGHT = 20, 20\n", "IMAGES_COUNT = 1_732\n", "TARGET_IMAGE = 1_086" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2024-04-17T07:38:47.439960Z", "iopub.status.busy": "2024-04-17T07:38:47.439881Z", "iopub.status.idle": "2024-04-17T07:38:52.196355Z", "shell.execute_reply": "2024-04-17T07:38:52.195995Z" } }, "outputs": [], "source": [ "data = []\n", "for i in range(IMAGES_COUNT):\n", " img = get_grayscale_img_or_none(get_img_or_none_by_index(i))\n", " if img is None:\n", " continue\n", " img = img.resize((WIDTH, HEIGHT))\n", " image_data = np.asarray(img).reshape(WIDTH * HEIGHT)\n", " image_agg_data = np.array([np.round(image_data.mean()), np.round(image_data.std())])\n", " data.append(np.concatenate((image_agg_data, image_data), axis=0).astype(int))" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2024-04-17T07:38:52.197757Z", "iopub.status.busy": "2024-04-17T07:38:52.197665Z", "iopub.status.idle": "2024-04-17T07:38:52.618680Z", "shell.execute_reply": "2024-04-17T07:38:52.618428Z" } }, "outputs": [], "source": [ "df = pd.DataFrame(data)\n", "df = df.rename(columns={0: 'color', 1: 'std'})\n", "df = df.sort_values(by=['color', 'std']).reset_index(drop=True)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2024-04-17T07:38:52.619986Z", "iopub.status.busy": "2024-04-17T07:38:52.619817Z", "iopub.status.idle": "2024-04-17T07:38:52.993096Z", "shell.execute_reply": "2024-04-17T07:38:52.992788Z" } }, "outputs": [ { "data": { "text/html": [ " \n", " " ], "text/plain": [ "