Skip to content

Instantly share code, notes, and snippets.

@razimantv
Created November 8, 2025 20:52
Show Gist options
  • Select an option

  • Save razimantv/2c63165a397010b698b385df406e4da4 to your computer and use it in GitHub Desktop.

Select an option

Save razimantv/2c63165a397010b698b385df406e4da4 to your computer and use it in GitHub Desktop.
Poor man's attempt at pointilism with python
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "cf91c81c-03c4-4357-ae7f-ba969c859c14",
"metadata": {},
"outputs": [],
"source": [
"from PIL import Image\n",
"import numpy as np\n",
"from matplotlib import pyplot as plt\n",
"from tqdm.notebook import tqdm\n",
"import requests"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "38b28cd8-00ea-4e42-a0c4-e57853ce7866",
"metadata": {},
"outputs": [],
"source": [
"rng = np.random.default_rng()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "94e20b00-867c-4bdf-8b15-d07c949088f7",
"metadata": {},
"outputs": [],
"source": [
"def smudge(img, img_new, x, y, radius, rng):\n",
" Nx, Ny = img.shape[:2]\n",
" idx_x, idx_y = np.array([\n",
" [x + dx, y + dy]\n",
" for dx in range(max(-radius, -x), min(radius + 1, Nx - x))\n",
" for dy in range(max(-radius, -y), min(radius + 1, Ny - y))\n",
" if ((dx ** 2 + dy ** 2) / (radius ** 2)) ** 2 <= rng.random()\n",
" ]).T\n",
" for layer in range(img.shape[2]):\n",
" idx_l = [layer] * len(idx_x)\n",
" mean = np.mean(img[idx_x, idx_y, idx_l])\n",
" std = np.std(img[idx_x, idx_y, idx_l]) / 5\n",
" img_new[idx_x, idx_y, idx_l] = np.clip(\n",
" rng.normal(mean - std + rng.random() * 2 * std, std, len(idx_l)), 0, 1\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "c5155ba4-08ed-4997-980e-50a7328d4a34",
"metadata": {},
"outputs": [],
"source": [
"filename = '/tmp/Coral_Tree_Monsoon_Mallalli_Falls_Hassan_Jun24_A7CR_01575.jpg'\n",
"\n",
"# Source: Wikimedia Commons (https://commons.wikimedia.org/wiki/File:Coral_Tree_Monsoon_Mallalli_Falls_Hassan_Jun24_A7CR_01575.jpg)\n",
"# Author: Timothy A. Gonsalves (https://commons.wikimedia.org/wiki/User:Tagooty)\n",
"# License: Creative Commons Attribution-Share Alike 4.0 International "
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "b416730e-d7f7-476c-b71d-ce739af88611",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "80266f73fc1d48d5b236b5a3012d435c",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
" 0%| | 0/100000 [00:00<?, ?it/s]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"img = np.array(Image.open(filename)) / 255.\n",
"img_new = img * 1\n",
"\n",
"for i in tqdm(range(100000)):\n",
" x, y = [rng.integers(N) for N in img.shape[:2]]\n",
" if (img[x][y] != img_new[x][y]).all():\n",
" continue\n",
" radius = rng.integers(12, 20)\n",
" smudge(img, img_new, x, y, radius, rng)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "f4a8fca7-0db6-40f9-bd8b-0f768ecde033",
"metadata": {},
"outputs": [
{
"data": {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment