├── .gitignore
├── Computer-Graphics
├── 2DTransformation_Matrix.ipynb
├── 2DTransformation_Matrix_viz.ipynb
├── 3DTransformation_Matrix.ipynb
├── 3DTransformation_Matrix_viz.ipynb
├── README.md
├── output
│ ├── 2DTransform_rotate.gif
│ ├── 2DTransform_scale.gif
│ ├── 2DTransform_shear.gif
│ ├── 2DTransform_translate.gif
│ ├── 3DTransform_rotate.gif
│ ├── 3DTransform_scale.gif
│ ├── 3DTransform_shear.gif
│ └── 3DTransform_translate.gif
├── ray-intersection_sphere.ipynb
├── ray-intersection_triangle.ipynb
└── sourceimages
│ ├── ray-intersection_sphere_01.jpg
│ ├── ray-intersection_sphere_02.jpg
│ ├── ray-intersection_sphere_03.jpg
│ ├── ray-intersection_sphere_04.jpg
│ ├── ray-intersection_sphere_05.jpg
│ ├── ray-intersection_sphere_06.jpg
│ ├── ray-intersection_sphere_07.jpg
│ ├── ray-intersection_sphere_08.jpg
│ ├── ray-intersection_triangle_01.jpg
│ ├── ray-intersection_triangle_02.jpg
│ ├── ray-intersection_triangle_03.jpg
│ ├── ray-intersection_triangle_04.jpg
│ ├── ray-intersection_triangle_05.jpg
│ ├── ray-intersection_triangle_06.jpg
│ ├── ray-intersection_triangle_07.jpg
│ └── ray-intersection_triangle_08.jpg
├── Generative
├── README.md
├── _utils.py
├── ascii-generator.ipynb
├── imgFX_pseudoHalftone.ipynb
├── imgFX_scatterCircles.ipynb
├── imgFX_scatterSquares.ipynb
├── imgFX_segments.ipynb
├── imgFX_strings.ipynb
├── imgFX_tracing.ipynb
├── imgFX_voronoi.ipynb
├── svg-gargantua.ipynb
├── svg-quadtree.ipynb
└── wall-of-letters.ipynb
├── LICENSE.md
├── ML-and-AI
├── README.md
├── image_approximation_deepNN.ipynb
├── pixel-art-depixelization-deepNN.ipynb
└── text-generation_markov-chain.ipynb
├── README.md
├── Simulation
├── README.md
├── cellularAutomaton1D.ipynb
├── cellularAutomaton2D.ipynb
├── mandelbrot-set.ipynb
├── output
│ ├── NLDC_cellularAutomaton1D_anim.gif
│ ├── NLDC_cellularAutomaton2D_anim.gif
│ ├── NLDC_cellularAutomaton2D_animA.gif
│ ├── NLDC_cellularAutomaton2D_animB.gif
│ ├── NLDC_cellularAutomaton2D_animC.gif
│ └── NLDC_reactionDiffusion.gif
└── reactionDiffusion.ipynb
├── Sound-Design
├── README.md
├── _utils.py
├── musical-notes-physics.ipynb
├── waveform_noise.ipynb
├── waveform_non-sinusoidal.ipynb
└── waveform_sinusoidal.ipynb
├── Tips-and-Tricks
├── README.md
├── _utils.py
├── audio_libraries.ipynb
├── basics_Numba.ipynb
├── connect_openai_api.ipynb
├── image_libraries.ipynb
├── matplotlib_animation.ipynb
├── output
│ ├── matplotlib_animation_BPF.mp4
│ ├── matplotlib_animation_colorShift.0000.png
│ ├── matplotlib_animation_colorShift.0001.png
│ ├── matplotlib_animation_colorShift.0002.png
│ ├── matplotlib_animation_colorShift.0003.png
│ └── matplotlib_animation_reactionDiffusion.gif
└── web-scraping.ipynb
├── _data
├── A4_cello-pizzicato.aiff
├── A4_cello01.wav
├── A4_cello02.wav
├── A4_flute-bad-richness.wav
├── A4_flute-vibrato.wav
├── A4_flute01.wav
├── A4_oboe01.wav
├── A4_piano01.wav
├── A4_sax-alto.wav
├── A4_sax-soprano.wav
├── A4_sax-tenor.wav
├── Additive_Synthesis_Harmonic.ogg
├── Additive_Synthesis_Inharmonic.ogg
├── Additive_synthesis_bell.ogg
├── aerial01.png
├── aerial02.png
├── aerial03.png
├── babuino.png
├── cameraman.png
├── earth.png
├── f16.png
├── fruits.png
├── pimentos.png
├── pixel-art-gitlab.png
├── pixel-art-mario.png
├── pixel-art-sonic.png
├── pixel-art-yoshi.png
├── sailboat.png
├── ship.png
├── sphere_16bits.tiff
├── sphere_32bits.tiff
├── sphere_8bits.tiff
├── tomography.png
├── woman01.png
├── woman02.png
└── woman03.png
└── docs
├── assets
├── icons
│ ├── go_python_notebooks.svg
│ ├── join_discussion.svg
│ ├── support_this_project.svg
│ └── visit_cookbook.svg
└── images
│ └── social-preview.png
├── index.html
└── style.css
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Python ###
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | ### Jupyter Notebook ###
7 | .ipynb_checkpoints
8 |
9 | ###################
10 | ### Page Assets ###
11 | ###################
12 |
13 | ### NodeJS ###
14 | node_modules/
15 | package-lock.json
16 |
17 | # live sass compiler
18 | *.css.map
19 |
20 | ######################
21 | ### Tests and Temp ###
22 | ######################
23 |
24 | ### Development files ###
25 | .env
26 |
27 | ### Image files ###
28 | _temp*.png
29 | _temp*.jpg
30 | _temp*.jpeg
31 |
--------------------------------------------------------------------------------
/Computer-Graphics/2DTransformation_Matrix.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# 2D Transformation Matrices\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [2DTransformation_Matrix.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Computer-Graphics/2DTransformation_Matrix.ipynb)\n",
12 | "---\n",
13 | "Overview and application of bi-dimensional transformation matrices."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib\n",
24 | "import matplotlib.pyplot as plt\n",
25 | "import numpy as np"
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": null,
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "plt.rcParams['figure.figsize'] = (16, 4)"
35 | ]
36 | },
37 | {
38 | "cell_type": "code",
39 | "execution_count": null,
40 | "metadata": {},
41 | "outputs": [],
42 | "source": [
43 | "X, Y = np.mgrid[0:1:5j, 0:1:5j]\n",
44 | "x, y = X.ravel(), Y.ravel()"
45 | ]
46 | },
47 | {
48 | "cell_type": "markdown",
49 | "metadata": {},
50 | "source": [
51 | "## Translation\n",
52 | "---\n",
53 | "$$\n",
54 | "\\large x'=x + t_x \\\\\n",
55 | "\\large y'=y + t_y\n",
56 | "$$\n",
57 | "using homogeneous matrix\n",
58 | "$$ \\large\n",
59 | "\\begin{bmatrix} x' \\\\ y' \\\\ 1 \\end{bmatrix} = \\begin{bmatrix} 1 & 0 & t_x \\\\ 0 & 1 & t_y \\\\ 0 & 0 & 1 \\end{bmatrix}\\begin{bmatrix} x \\\\ y \\\\ 1 \\end{bmatrix}\n",
60 | "$$"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": null,
66 | "metadata": {},
67 | "outputs": [],
68 | "source": [
69 | "def trans_translate(x, y, tx, ty):\n",
70 | " T = [[1, 0, tx],\n",
71 | " [0, 1, ty],\n",
72 | " [0, 0, 1 ]]\n",
73 | " T = np.array(T)\n",
74 | " P = np.array([x, y, [1]*x.size])\n",
75 | " return np.dot(T, P)\n",
76 | "\n",
77 | "fig, ax = plt.subplots(1, 4)\n",
78 | "\n",
79 | "T_ = [[0, 0], [2.3, 0], [0, 1.7], [2, 2]]\n",
80 | "\n",
81 | "for i in range(4):\n",
82 | " tx, ty = T_[i]\n",
83 | " x_, y_, _ = trans_translate(x, y, tx, ty)\n",
84 | " ax[i].scatter(x_, y_)\n",
85 | " ax[i].set_title(r'$t_x={0:.2f}$ , $t_y={1:.2f}$'.format(tx, ty))\n",
86 | " \n",
87 | " ax[i].set_xlim([-0.5, 4])\n",
88 | " ax[i].set_ylim([-0.5, 4])\n",
89 | " ax[i].grid(alpha=0.5)\n",
90 | " ax[i].axhline(y=0, color='k')\n",
91 | " ax[i].axvline(x=0, color='k')\n",
92 | "\n",
93 | "plt.show()"
94 | ]
95 | },
96 | {
97 | "cell_type": "markdown",
98 | "metadata": {},
99 | "source": [
100 | ""
101 | ]
102 | },
103 | {
104 | "cell_type": "markdown",
105 | "metadata": {},
106 | "source": [
107 | "## Scaling\n",
108 | "---\n",
109 | "Relative to the point $(p_x, p_y)$\n",
110 | "$$\n",
111 | "\\large x'=s_x(x - p_x) + p_x = s_x x + p_x(1 - s_x)\\\\\n",
112 | "\\large y'=s_y(y - p_y) + p_y = s_y y + p_y(1 - s_y)\n",
113 | "$$\n",
114 | "using homogeneous matrix\n",
115 | "$$ \\large\n",
116 | "\\begin{bmatrix} x' \\\\ y' \\\\ 1 \\end{bmatrix} = \\begin{bmatrix} s_x & 0 & p_x(1 - s_x) \\\\ 0 & s_y & p_y(1 - s_y) \\\\ 0 & 0 & 1 \\end{bmatrix}\\begin{bmatrix} x \\\\ y \\\\ 1 \\end{bmatrix}\n",
117 | "$$"
118 | ]
119 | },
120 | {
121 | "cell_type": "code",
122 | "execution_count": null,
123 | "metadata": {},
124 | "outputs": [],
125 | "source": [
126 | "def trans_scale(x, y, px, py, sx, sy):\n",
127 | " T = [[sx, 0 , px*(1 - sx)],\n",
128 | " [0 , sy, py*(1 - sy)],\n",
129 | " [0 , 0 , 1 ]]\n",
130 | " T = np.array(T)\n",
131 | " P = np.array([x, y, [1]*x.size])\n",
132 | " return np.dot(T, P)\n",
133 | "\n",
134 | "fig, ax = plt.subplots(1, 4)\n",
135 | "\n",
136 | "S_ = [[1, 1], [1.8, 1], [1, 1.7], [2, 2]]\n",
137 | "P_ = [[0, 0], [0, 0], [0.45, 0.45], [1.1, 1.1]]\n",
138 | "\n",
139 | "for i in range(4):\n",
140 | " sx, sy = S_[i]; px, py = P_[i]\n",
141 | " x_, y_, _ = trans_scale(x, y, px, py, sx, sy)\n",
142 | " ax[i].scatter(x_, y_)\n",
143 | " ax[i].scatter(px, py)\n",
144 | " ax[i].set_title(r'$p_x={0:.2f}$ , $p_y={1:.2f}$'.format(px, py) + '\\n'\n",
145 | " r'$s_x={0:.2f}$ , $s_y={1:.2f}$'.format(sx, sy))\n",
146 | " \n",
147 | " ax[i].set_xlim([-2, 2])\n",
148 | " ax[i].set_ylim([-2, 2])\n",
149 | " ax[i].grid(alpha=0.5)\n",
150 | " ax[i].axhline(y=0, color='k')\n",
151 | " ax[i].axvline(x=0, color='k')\n",
152 | "\n",
153 | "plt.show()"
154 | ]
155 | },
156 | {
157 | "cell_type": "markdown",
158 | "metadata": {},
159 | "source": [
160 | ""
161 | ]
162 | },
163 | {
164 | "cell_type": "markdown",
165 | "metadata": {},
166 | "source": [
167 | "## Rotation\n",
168 | "---\n",
169 | "Relative to the point $(p_x, p_y)$\n",
170 | "$$\n",
171 | "\\large x'=(x - p_x)\\cos\\beta-(y - p_y)\\sin \\beta + p_x = x \\cos \\beta - y \\sin \\beta + p_x(1 - \\cos \\beta) + p_y \\sin \\beta \\\\\n",
172 | "\\large y'=(x - p_x)\\sin\\beta+(y - p_y)\\cos \\beta + p_y = x \\sin \\beta + y \\cos \\beta + p_y(1 - \\cos \\beta) - p_x \\sin \\beta\n",
173 | "$$\n",
174 | "using homogeneous matrix\n",
175 | "$$ \\large\n",
176 | "\\begin{bmatrix} x' \\\\ y' \\\\ 1 \\end{bmatrix} = \\begin{bmatrix} \\cos\\beta & -\\sin\\beta & p_x(1 - \\cos \\beta) + p_y \\sin \\beta \\\\ \\sin\\beta & \\cos\\beta & p_y(1 - \\cos \\beta) - p_x \\sin \\beta \\\\ 0 & 0 & 1 \\end{bmatrix}\\begin{bmatrix} x \\\\ y \\\\ 1 \\end{bmatrix}\n",
177 | "$$"
178 | ]
179 | },
180 | {
181 | "cell_type": "code",
182 | "execution_count": null,
183 | "metadata": {},
184 | "outputs": [],
185 | "source": [
186 | "def trans_rotate(x, y, px, py, beta):\n",
187 | " beta = np.deg2rad(beta)\n",
188 | " T = [[np.cos(beta), -np.sin(beta), px*(1 - np.cos(beta)) + py*np.sin(beta)],\n",
189 | " [np.sin(beta), np.cos(beta), py*(1 - np.cos(beta)) - px*np.sin(beta)],\n",
190 | " [0 , 0 , 1 ]]\n",
191 | " T = np.array(T)\n",
192 | " P = np.array([x, y, [1]*x.size])\n",
193 | " return np.dot(T, P)\n",
194 | "\n",
195 | "fig, ax = plt.subplots(1, 4)\n",
196 | "\n",
197 | "R_ = [0, 225, 40, -10]\n",
198 | "P_ = [[0, 0], [0, 0], [0.5, -0.5], [1.1, 1.1]]\n",
199 | "\n",
200 | "for i in range(4):\n",
201 | " beta = R_[i]; px, py = P_[i]\n",
202 | " x_, y_, _ = trans_rotate(x, y, px, py, beta)\n",
203 | " ax[i].scatter(x_, y_)\n",
204 | " ax[i].scatter(px, py)\n",
205 | " ax[i].set_title(r'$\\beta={0}°$ , $p_x={1:.2f}$ , $p_y={2:.2f}$'.format(beta, px, py))\n",
206 | " \n",
207 | " ax[i].set_xlim([-2, 2])\n",
208 | " ax[i].set_ylim([-2, 2])\n",
209 | " ax[i].grid(alpha=0.5)\n",
210 | " ax[i].axhline(y=0, color='k')\n",
211 | " ax[i].axvline(x=0, color='k')\n",
212 | "\n",
213 | "plt.show()"
214 | ]
215 | },
216 | {
217 | "cell_type": "markdown",
218 | "metadata": {},
219 | "source": [
220 | ""
221 | ]
222 | },
223 | {
224 | "cell_type": "markdown",
225 | "metadata": {},
226 | "source": [
227 | "## Shearing\n",
228 | "---\n",
229 | "Relative to the point $(p_x, p_y)$\n",
230 | "$$\n",
231 | "\\large x' = x + \\lambda_x(y - p_x) = x + \\lambda_x y - \\lambda_x p_x\\\\\n",
232 | "\\large y' = y + \\lambda_y(x - p_y) = y + \\lambda_y x - \\lambda_y p_y\n",
233 | "$$\n",
234 | "using homogeneous matrix\n",
235 | "$$ \\large\n",
236 | "\\begin{bmatrix} x' \\\\ y' \\\\ 1 \\end{bmatrix} = \\begin{bmatrix} 1 & \\lambda_x & -\\lambda_x p_x \\\\ \\lambda_y & 1 & -\\lambda_y p_y \\\\ 0 & 0 & 1 \\end{bmatrix}\\begin{bmatrix} x \\\\ y \\\\ 1 \\end{bmatrix}\n",
237 | "$$"
238 | ]
239 | },
240 | {
241 | "cell_type": "code",
242 | "execution_count": null,
243 | "metadata": {},
244 | "outputs": [],
245 | "source": [
246 | "def trans_shear(x, y, px, py, lambdax, lambday):\n",
247 | " T = [[1 , lambdax, -lambdax*px],\n",
248 | " [lambday, 1 , -lambday*py],\n",
249 | " [0 , 0 , 1 ]]\n",
250 | " T = np.array(T)\n",
251 | " P = np.array([x, y, [1]*x.size])\n",
252 | " return np.dot(T, P)\n",
253 | "\n",
254 | "fig, ax = plt.subplots(1, 4)\n",
255 | "\n",
256 | "L_ = [[0, 0], [2, 0], [0, -2], [-2, -2]]\n",
257 | "P_ = [[0, 0], [0, 0], [0, 1.5], [1.1, 1.1]]\n",
258 | "\n",
259 | "for i in range(4):\n",
260 | " lambdax, lambday = L_[i]; px, py = P_[i]\n",
261 | " x_, y_, _ = trans_shear(x, y, px, py, lambdax, lambday)\n",
262 | " ax[i].scatter(x_, y_)\n",
263 | " ax[i].scatter(px, py)\n",
264 | " ax[i].set_title(r'$p_x={0:.2f}$ , $p_y={1:.2f}$'.format(px, py) + '\\n'\n",
265 | " r'$\\lambda_x={0:.2f}$ , $\\lambda_y={1:.2f}$'.format(lambdax, lambday))\n",
266 | "\n",
267 | " ax[i].set_xlim([-3, 3])\n",
268 | " ax[i].set_ylim([-3, 3])\n",
269 | " ax[i].grid(alpha=0.5)\n",
270 | " ax[i].axhline(y=0, color='k')\n",
271 | " ax[i].axvline(x=0, color='k')\n",
272 | "\n",
273 | "plt.show()"
274 | ]
275 | },
276 | {
277 | "cell_type": "markdown",
278 | "metadata": {},
279 | "source": [
280 | ""
281 | ]
282 | }
283 | ],
284 | "metadata": {
285 | "kernelspec": {
286 | "display_name": "Python 3",
287 | "language": "python",
288 | "name": "python3"
289 | },
290 | "language_info": {
291 | "codemirror_mode": {
292 | "name": "ipython",
293 | "version": 3
294 | },
295 | "file_extension": ".py",
296 | "mimetype": "text/x-python",
297 | "name": "python",
298 | "nbconvert_exporter": "python",
299 | "pygments_lexer": "ipython3",
300 | "version": "3.7.7"
301 | }
302 | },
303 | "nbformat": 4,
304 | "nbformat_minor": 2
305 | }
306 |
--------------------------------------------------------------------------------
/Computer-Graphics/2DTransformation_Matrix_viz.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# 2D Transformation Matrix [Viz]\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)"
11 | ]
12 | },
13 | {
14 | "cell_type": "code",
15 | "execution_count": null,
16 | "metadata": {},
17 | "outputs": [],
18 | "source": [
19 | "%matplotlib inline\n",
20 | "import matplotlib\n",
21 | "import matplotlib.pyplot as plt\n",
22 | "import matplotlib.animation as manim\n",
23 | "import numpy as np"
24 | ]
25 | },
26 | {
27 | "cell_type": "code",
28 | "execution_count": null,
29 | "metadata": {},
30 | "outputs": [],
31 | "source": [
32 | "plt.rcParams['figure.figsize'] = (16, 4)"
33 | ]
34 | },
35 | {
36 | "cell_type": "code",
37 | "execution_count": null,
38 | "metadata": {},
39 | "outputs": [],
40 | "source": [
41 | "X, Y = np.mgrid[0:1:5j, 0:1:5j]\n",
42 | "x, y = X.ravel(), Y.ravel()"
43 | ]
44 | },
45 | {
46 | "cell_type": "markdown",
47 | "metadata": {},
48 | "source": [
49 | "## 1. Translation\n",
50 | "---"
51 | ]
52 | },
53 | {
54 | "cell_type": "code",
55 | "execution_count": null,
56 | "metadata": {},
57 | "outputs": [],
58 | "source": [
59 | "def trans_translate(x, y, tx, ty):\n",
60 | " T = [[1, 0, tx],\n",
61 | " [0, 1, ty],\n",
62 | " [0, 0, 1 ]]\n",
63 | " T = np.array(T)\n",
64 | " P = np.array([x, y, [1]*x.size])\n",
65 | " return np.dot(T, P)\n",
66 | "\n",
67 | "fig, ax = plt.subplots(1, 4)\n",
68 | "\n",
69 | "NFRAMES = 20\n",
70 | "\n",
71 | "T_ = [[0, 0], [2.3, 0], [0, 1.7], [2, 2]]\n",
72 | "\n",
73 | "def animation(frame):\n",
74 | " for i in range(4):\n",
75 | " ax[i].cla()\n",
76 | " tx, ty = T_[i][0]*frame/NFRAMES, T_[i][1]*frame/NFRAMES\n",
77 | " x_, y_, _ = trans_translate(x, y, tx, ty)\n",
78 | " ax[i].scatter(x_, y_)\n",
79 | "\n",
80 | " ax[i].set_xlim([-0.5, 4])\n",
81 | " ax[i].set_ylim([-0.5, 4])\n",
82 | " ax[i].grid(alpha=0.5)\n",
83 | " ax[i].axhline(y=0, color='k')\n",
84 | " ax[i].axvline(x=0, color='k')\n",
85 | " plt.tight_layout()\n",
86 | " return ax\n",
87 | "\n",
88 | "anim = manim.FuncAnimation(fig, animation, frames=NFRAMES, interval=100)\n",
89 | "anim.save('output/2DTransform_translate.gif', writer=\"imagemagick\", extra_args=\"convert\")\n",
90 | "\n",
91 | "plt.close()\n",
92 | "\n",
93 | "# Solve repetition problem\n",
94 | "! magick convert _output/2DTransform_translate.gif -loop 0 _output/2DTransform_translate.gif\n",
95 | "! echo GIF exported and reconverted. Disregard the message above."
96 | ]
97 | },
98 | {
99 | "cell_type": "markdown",
100 | "metadata": {},
101 | "source": [
102 | "## 2. Scaling\n",
103 | "---"
104 | ]
105 | },
106 | {
107 | "cell_type": "code",
108 | "execution_count": null,
109 | "metadata": {},
110 | "outputs": [],
111 | "source": [
112 | "def trans_scale(x, y, px, py, sx, sy):\n",
113 | " T = [[sx, 0 , px*(1 - sx)],\n",
114 | " [0 , sy, py*(1 - sy)],\n",
115 | " [0 , 0 , 1 ]]\n",
116 | " T = np.array(T)\n",
117 | " P = np.array([x, y, [1]*x.size])\n",
118 | " return np.dot(T, P)\n",
119 | "\n",
120 | "fig, ax = plt.subplots(1, 4)\n",
121 | "\n",
122 | "NFRAMES = 20\n",
123 | "\n",
124 | "S_ = [[1, 1], [1.8, 1], [1, 1.7], [2, 2]]\n",
125 | "P_ = [[0, 0], [0, 0], [0.45, 0.45], [1.1, 1.1]]\n",
126 | "\n",
127 | "def animation(frame):\n",
128 | " for i in range(4):\n",
129 | " ax[i].cla(); px, py = P_[i]\n",
130 | " sx, sy = 1 + (S_[i][0]-1)*frame/NFRAMES, 1 + (S_[i][1]-1)*frame/NFRAMES\n",
131 | " x_, y_, _ = trans_scale(x, y, px, py, sx, sy)\n",
132 | " ax[i].scatter(x_, y_)\n",
133 | " ax[i].scatter(px, py)\n",
134 | "\n",
135 | " ax[i].set_xlim([-2, 2])\n",
136 | " ax[i].set_ylim([-2, 2])\n",
137 | " ax[i].grid(alpha=0.5)\n",
138 | " ax[i].axhline(y=0, color='k')\n",
139 | " ax[i].axvline(x=0, color='k')\n",
140 | " plt.tight_layout()\n",
141 | " return ax\n",
142 | "\n",
143 | "anim = manim.FuncAnimation(fig, animation, frames=NFRAMES, interval=100)\n",
144 | "anim.save('output/2DTransform_scale.gif', writer=\"imagemagick\", extra_args=\"convert\")\n",
145 | "\n",
146 | "plt.close()\n",
147 | "\n",
148 | "# Solve repetition problem\n",
149 | "! magick convert _output/2DTransform_scale.gif -loop 0 _output/2DTransform_scale.gif\n",
150 | "! echo GIF exported and reconverted. Disregard the message above."
151 | ]
152 | },
153 | {
154 | "cell_type": "markdown",
155 | "metadata": {},
156 | "source": [
157 | "## 3. Rotation\n",
158 | "---"
159 | ]
160 | },
161 | {
162 | "cell_type": "code",
163 | "execution_count": null,
164 | "metadata": {},
165 | "outputs": [],
166 | "source": [
167 | "def trans_rotate(x, y, px, py, beta):\n",
168 | " beta = np.deg2rad(beta)\n",
169 | " T = [[np.cos(beta), -np.sin(beta), px*(1 - np.cos(beta)) + py*np.sin(beta)],\n",
170 | " [np.sin(beta), np.cos(beta), py*(1 - np.cos(beta)) - px*np.sin(beta)],\n",
171 | " [0 , 0 , 1 ]]\n",
172 | " T = np.array(T)\n",
173 | " P = np.array([x, y, [1]*x.size])\n",
174 | " return np.dot(T, P)\n",
175 | "\n",
176 | "fig, ax = plt.subplots(1, 4)\n",
177 | "\n",
178 | "NFRAMES = 20\n",
179 | "\n",
180 | "R_ = [0, 225, 40, -10]\n",
181 | "P_ = [[0, 0], [0, 0], [0.5, -0.5], [1.1, 1.1]]\n",
182 | "\n",
183 | "def animation(frame):\n",
184 | " for i in range(4):\n",
185 | " ax[i].cla(); px, py = P_[i]\n",
186 | " beta = 0 if i == 0 else R_[i] + 360*frame/NFRAMES\n",
187 | " x_, y_, _ = trans_rotate(x, y, px, py, beta)\n",
188 | " ax[i].scatter(x_, y_)\n",
189 | " ax[i].scatter(px, py)\n",
190 | "\n",
191 | " ax[i].set_xlim([-2, 2])\n",
192 | " ax[i].set_ylim([-2, 2])\n",
193 | " ax[i].grid(alpha=0.5)\n",
194 | " ax[i].axhline(y=0, color='k')\n",
195 | " ax[i].axvline(x=0, color='k')\n",
196 | " plt.tight_layout()\n",
197 | " return ax\n",
198 | "\n",
199 | "anim = manim.FuncAnimation(fig, animation, frames=NFRAMES, interval=100)\n",
200 | "anim.save('output/2DTransform_rotate.gif', writer=\"imagemagick\", extra_args=\"convert\")\n",
201 | "\n",
202 | "plt.close()\n",
203 | "\n",
204 | "# Solve repetition problem\n",
205 | "! magick convert _output/2DTransform_rotate.gif -loop 0 _output/2DTransform_rotate.gif\n",
206 | "! echo GIF exported and reconverted. Disregard the message above."
207 | ]
208 | },
209 | {
210 | "cell_type": "markdown",
211 | "metadata": {},
212 | "source": [
213 | "## 4. Shearing\n",
214 | "---"
215 | ]
216 | },
217 | {
218 | "cell_type": "code",
219 | "execution_count": null,
220 | "metadata": {},
221 | "outputs": [],
222 | "source": [
223 | "def trans_shear(x, y, px, py, lambdax, lambday):\n",
224 | " T = [[1 , lambdax, -lambdax*px],\n",
225 | " [lambday, 1 , -lambday*py],\n",
226 | " [0 , 0 , 1 ]]\n",
227 | " T = np.array(T)\n",
228 | " P = np.array([x, y, [1]*x.size])\n",
229 | " return np.dot(T, P)\n",
230 | "\n",
231 | "fig, ax = plt.subplots(1, 4)\n",
232 | "\n",
233 | "NFRAMES = 20\n",
234 | "\n",
235 | "L_ = [[0, 0], [2, 0], [0, -2], [-2, -2]]\n",
236 | "P_ = [[0, 0], [0, 0], [0, 1.5], [1.1, 1.1]]\n",
237 | "\n",
238 | "def animation(frame):\n",
239 | " for i in range(4):\n",
240 | " ax[i].cla(); px, py = P_[i]\n",
241 | " lambdax, lambday = L_[i][0]*frame/NFRAMES, L_[i][1]*frame/NFRAMES\n",
242 | " x_, y_, _ = trans_shear(x, y, px, py, lambdax, lambday)\n",
243 | " ax[i].scatter(x_, y_)\n",
244 | " ax[i].scatter(px, py)\n",
245 | "\n",
246 | " ax[i].set_xlim([-3, 3])\n",
247 | " ax[i].set_ylim([-3, 3])\n",
248 | " ax[i].grid(alpha=0.5)\n",
249 | " ax[i].axhline(y=0, color='k')\n",
250 | " ax[i].axvline(x=0, color='k')\n",
251 | " plt.tight_layout()\n",
252 | " return ax\n",
253 | "\n",
254 | "anim = manim.FuncAnimation(fig, animation, frames=NFRAMES, interval=100)\n",
255 | "anim.save('output/2DTransform_shear.gif', writer=\"imagemagick\", extra_args=\"convert\")\n",
256 | "\n",
257 | "plt.close()\n",
258 | "\n",
259 | "# Solve repetition problem\n",
260 | "! magick convert _output/2DTransform_shear.gif -loop 0 _output/2DTransform_shear.gif\n",
261 | "! echo GIF exported and reconverted. Disregard the message above."
262 | ]
263 | }
264 | ],
265 | "metadata": {
266 | "kernelspec": {
267 | "display_name": "Python 3",
268 | "language": "python",
269 | "name": "python3"
270 | },
271 | "language_info": {
272 | "codemirror_mode": {
273 | "name": "ipython",
274 | "version": 3
275 | },
276 | "file_extension": ".py",
277 | "mimetype": "text/x-python",
278 | "name": "python",
279 | "nbconvert_exporter": "python",
280 | "pygments_lexer": "ipython3",
281 | "version": "3.7.10"
282 | }
283 | },
284 | "nbformat": 4,
285 | "nbformat_minor": 2
286 | }
287 |
--------------------------------------------------------------------------------
/Computer-Graphics/README.md:
--------------------------------------------------------------------------------
1 | # Computer Graphics
2 |
3 | Demonstrations and studies involving some quite important topics about **computer graphics**.
--------------------------------------------------------------------------------
/Computer-Graphics/output/2DTransform_rotate.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/output/2DTransform_rotate.gif
--------------------------------------------------------------------------------
/Computer-Graphics/output/2DTransform_scale.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/output/2DTransform_scale.gif
--------------------------------------------------------------------------------
/Computer-Graphics/output/2DTransform_shear.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/output/2DTransform_shear.gif
--------------------------------------------------------------------------------
/Computer-Graphics/output/2DTransform_translate.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/output/2DTransform_translate.gif
--------------------------------------------------------------------------------
/Computer-Graphics/output/3DTransform_rotate.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/output/3DTransform_rotate.gif
--------------------------------------------------------------------------------
/Computer-Graphics/output/3DTransform_scale.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/output/3DTransform_scale.gif
--------------------------------------------------------------------------------
/Computer-Graphics/output/3DTransform_shear.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/output/3DTransform_shear.gif
--------------------------------------------------------------------------------
/Computer-Graphics/output/3DTransform_translate.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/output/3DTransform_translate.gif
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_sphere_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_sphere_01.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_sphere_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_sphere_02.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_sphere_03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_sphere_03.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_sphere_04.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_sphere_04.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_sphere_05.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_sphere_05.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_sphere_06.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_sphere_06.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_sphere_07.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_sphere_07.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_sphere_08.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_sphere_08.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_triangle_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_triangle_01.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_triangle_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_triangle_02.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_triangle_03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_triangle_03.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_triangle_04.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_triangle_04.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_triangle_05.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_triangle_05.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_triangle_06.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_triangle_06.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_triangle_07.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_triangle_07.jpg
--------------------------------------------------------------------------------
/Computer-Graphics/sourceimages/ray-intersection_triangle_08.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Computer-Graphics/sourceimages/ray-intersection_triangle_08.jpg
--------------------------------------------------------------------------------
/Generative/README.md:
--------------------------------------------------------------------------------
1 | # Generative
2 |
3 | Procedural generation, algorithmic design, graphics programming, creative imaging ..
4 |
--------------------------------------------------------------------------------
/Generative/_utils.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import matplotlib.gridspec as gridspec
3 | import numpy as np
4 |
5 | def panel(images, gspec, **kargs):
6 | M, N = gspec
7 |
8 | x, y = (1024, 512) if 'dims' not in kargs else kargs['dims']
9 | dpi = 72 if 'dpi' not in kargs else kargs['dpi']
10 | texts = [] if 'texts' not in kargs else kargs['texts']
11 | tx, ty = (10, 10) if 'text_pos' not in kargs else kargs['text_pos']
12 | tc = 'white' if 'text_color' not in kargs else kargs['text_color']
13 | ts = 12 if 'text_size' not in kargs else kargs['text_size']
14 | interval = [0, 255] if 'interval' not in kargs else kargs['interval']
15 |
16 | fig = plt.figure(figsize=(x/dpi, y/dpi))
17 | gs = gridspec.GridSpec(N, M)
18 | gs.update( left=0, right=1,
19 | bottom=0, top=1,
20 | wspace=0, hspace=0)
21 | images = (images - interval[0])/(interval[1] - interval[0])
22 | images[images < 0] = 0
23 | images[images > 1] = 1
24 | for n in range(N):
25 | for m in range(M):
26 | ax = plt.subplot(gs[n, m])
27 | ax.axis('off')
28 | try:
29 | image = images[n*M + m]
30 | except:
31 | image = images[0]*0
32 | if image.ndim == 2:
33 | ax.imshow(image, cmap='gray')
34 | else:
35 | ax.imshow(image)
36 | try:
37 | texto = texts[n*M + m]
38 | except:
39 | texto = ''
40 | ax.text( tx, ty, texto,
41 | color=tc, size=ts,
42 | horizontalalignment='left',
43 | verticalalignment='top')
44 | plt.show()
--------------------------------------------------------------------------------
/Generative/ascii-generator.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Image to ASCII Generator\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [ascii-generator.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Generative/ascii-generator.ipynb)\n",
12 | "---\n",
13 | "Implementation of a simple image to ASCII generator."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "from PIL import (\n",
23 | " Image, \n",
24 | " ImageOps, \n",
25 | " ImageFont, \n",
26 | " ImageDraw\n",
27 | ")\n",
28 | "\n",
29 | "import numpy as np\n",
30 | "\n",
31 | "from IPython.display import HTML, display"
32 | ]
33 | },
34 | {
35 | "cell_type": "markdown",
36 | "metadata": {},
37 | "source": [
38 | "## Symbols\n",
39 | "---"
40 | ]
41 | },
42 | {
43 | "cell_type": "code",
44 | "execution_count": null,
45 | "metadata": {},
46 | "outputs": [],
47 | "source": [
48 | "# Define symbol set\n",
49 | "symbols = list(\"!@#%¨&*()-_=+{}[]<>^~,.:;?|\")\n",
50 | "symbols += [chr(e) for e in range(ord(\"a\"), ord(\"z\") + 1)]\n",
51 | "symbols += [chr(e) for e in range(ord(\"A\"), ord(\"Z\") + 1)]\n",
52 | "symbols += list(\"0123456789\")\n",
53 | "N = len(symbols)"
54 | ]
55 | },
56 | {
57 | "cell_type": "code",
58 | "execution_count": null,
59 | "metadata": {},
60 | "outputs": [],
61 | "source": [
62 | "# Download font\n",
63 | "import requests\n",
64 | "URL = \"https://github.com/googlefonts/roboto/blob/master/src/hinted/Roboto-Regular.ttf?raw=true\"\n",
65 | "response = requests.get(URL)\n",
66 | "open(\"Roboto-Regular.ttf\", \"wb\").write(response.content)"
67 | ]
68 | },
69 | {
70 | "cell_type": "code",
71 | "execution_count": null,
72 | "metadata": {},
73 | "outputs": [],
74 | "source": [
75 | "# Raster symbol set parameters\n",
76 | "S, T = 32, 32 # raster sizes\n",
77 | "\n",
78 | "# Create raster symbol set\n",
79 | "SYMBOLS = np.zeros((N, T, S))\n",
80 | "for i, e in enumerate(symbols):\n",
81 | " image = Image.fromarray(np.zeros((S, S)))\n",
82 | " draw = ImageDraw.Draw(image)\n",
83 | " font = ImageFont.truetype(\"Roboto-Regular.ttf\", S)\n",
84 | " draw.text((S/2, S/2), e, anchor=\"mm\", font=font)\n",
85 | " SYMBOLS[i] = np.asarray(image)"
86 | ]
87 | },
88 | {
89 | "cell_type": "markdown",
90 | "metadata": {},
91 | "source": [
92 | "## Input B&W\n",
93 | "---"
94 | ]
95 | },
96 | {
97 | "cell_type": "code",
98 | "execution_count": null,
99 | "metadata": {},
100 | "outputs": [],
101 | "source": [
102 | "# Read input B&W image\n",
103 | "IMAGE_BW = Image.open(\"../_data/cameraman.png\")\n",
104 | "\n",
105 | "# Histogram equalization\n",
106 | "IMAGE_BW = ImageOps.equalize(IMAGE_BW)\n",
107 | "\n",
108 | "# Show image\n",
109 | "IMAGE_BW"
110 | ]
111 | },
112 | {
113 | "cell_type": "code",
114 | "execution_count": null,
115 | "metadata": {},
116 | "outputs": [],
117 | "source": [
118 | "# Ascii symbols parameters\n",
119 | "m, n = 160, 80 # number of ascii symbols per axis\n",
120 | "\n",
121 | "# Resize input image based on inputs\n",
122 | "IMAGE_ = IMAGE_BW.resize((m*S, n*T))\n",
123 | "IMAGE_ = np.asarray(IMAGE_)/255\n",
124 | "\n",
125 | "# Build ascii conversions\n",
126 | "OUTPUT = [[\"\" for _ in range(m)] for _ in range(n)]\n",
127 | "for j, ROW in enumerate(OUTPUT):\n",
128 | " for i, e in enumerate(ROW):\n",
129 | " image = IMAGE_[j*S:(j+1)*S, i*S:(i+1)*S]\n",
130 | " diff = np.power(SYMBOLS - image, 2).reshape((N, -1))\n",
131 | " OUTPUT[j][i] = symbols[np.argmin(diff.sum(axis=1))]"
132 | ]
133 | },
134 | {
135 | "cell_type": "code",
136 | "execution_count": null,
137 | "metadata": {},
138 | "outputs": [],
139 | "source": [
140 | "STYLE = \"\"\"\n",
141 | "\n",
162 | "\"\"\"\n",
163 | "\n",
164 | "# Build HTML\n",
165 | "DIV = f'
'\n",
166 | "\n",
167 | "DIV += f'
'\n",
168 | "OUTPUT_ROWS = [\"\".join(e) for e in OUTPUT]\n",
169 | "DIV += \"\".join([f'
{row}
' for row in OUTPUT_ROWS])\n",
170 | "DIV += \"
\"\n",
171 | "\n",
172 | "DIV += \"
\"\n",
173 | "\n",
174 | "# Display ascii art\n",
175 | "display(HTML(STYLE + DIV))"
176 | ]
177 | },
178 | {
179 | "cell_type": "code",
180 | "execution_count": null,
181 | "metadata": {},
182 | "outputs": [],
183 | "source": [
184 | "# Print HTML div\n",
185 | "# print(STYLE + DIV)"
186 | ]
187 | },
188 | {
189 | "cell_type": "markdown",
190 | "metadata": {},
191 | "source": [
192 | "## Input RGB\n",
193 | "---"
194 | ]
195 | },
196 | {
197 | "cell_type": "code",
198 | "execution_count": null,
199 | "metadata": {},
200 | "outputs": [],
201 | "source": [
202 | "# Read input RGB image\n",
203 | "IMAGE_RGB = Image.open(\"../_data/woman03.png\")\n",
204 | "\n",
205 | "# Histogram equalization\n",
206 | "IMAGE_RGB = ImageOps.equalize(IMAGE_RGB)\n",
207 | "\n",
208 | "# Convert to HSV\n",
209 | "IMAGE_HSV = IMAGE_RGB.convert(\"HSV\")\n",
210 | "\n",
211 | "# Show image\n",
212 | "IMAGE_RGB"
213 | ]
214 | },
215 | {
216 | "cell_type": "code",
217 | "execution_count": null,
218 | "metadata": {},
219 | "outputs": [],
220 | "source": [
221 | "# Ascii symbols parameters\n",
222 | "m, n = 80, 40 # number of ascii symbols per axis\n",
223 | "\n",
224 | "# Resize input image based on inputs\n",
225 | "IMAGE_ = IMAGE_HSV.resize((m*S, n*T))\n",
226 | "IMAGE_ = np.asarray(IMAGE_)/255\n",
227 | "\n",
228 | "# Build ascii conversions\n",
229 | "OUTPUT = [[{\"chr\": \"\", \"hue\": \"\"} for _ in range(m)] for _ in range(n)]\n",
230 | "for j, ROW in enumerate(OUTPUT):\n",
231 | " for i, e in enumerate(ROW):\n",
232 | " image = IMAGE_[j*S:(j+1)*S, i*S:(i+1)*S, 2]\n",
233 | " diff = np.power(SYMBOLS - image, 2).reshape((N, -1))\n",
234 | " OUTPUT[j][i][\"chr\"] = symbols[np.argmin(diff.sum(axis=1))]\n",
235 | " block_hue = int(np.median(IMAGE_[j*S:(j+1)*S, i*S:(i+1)*S, 0])*360)\n",
236 | " block_sat = int(np.median(IMAGE_[j*S:(j+1)*S, i*S:(i+1)*S, 1])*100)\n",
237 | " block_val = int(np.median(IMAGE_[j*S:(j+1)*S, i*S:(i+1)*S, 2])*100)\n",
238 | " OUTPUT[j][i][\"color\"] = f'hsl({block_hue}, {block_sat}%, {block_val}%)'"
239 | ]
240 | },
241 | {
242 | "cell_type": "code",
243 | "execution_count": null,
244 | "metadata": {},
245 | "outputs": [],
246 | "source": [
247 | "STYLE = \"\"\"\n",
248 | "\n",
268 | "\"\"\"\n",
269 | "\n",
270 | "# Build HTML\n",
271 | "DIV = f''\n",
272 | "\n",
273 | "DIV += f'
'\n",
274 | "OUTPUT_ROWS = [\"\".join(\n",
275 | " [f'
{e[\"chr\"]}' for e in row]\n",
276 | ") for row in OUTPUT]\n",
277 | "DIV += \"\".join([f'
{row}
' for row in OUTPUT_ROWS])\n",
278 | "DIV += \"
\"\n",
279 | "\n",
280 | "DIV += \"
\"\n",
281 | "\n",
282 | "# Display ascii art\n",
283 | "display(HTML(STYLE + DIV))"
284 | ]
285 | },
286 | {
287 | "cell_type": "code",
288 | "execution_count": null,
289 | "metadata": {},
290 | "outputs": [],
291 | "source": [
292 | "# Print HTML div\n",
293 | "# print(STYLE + DIV)"
294 | ]
295 | }
296 | ],
297 | "metadata": {
298 | "kernelspec": {
299 | "display_name": "Python [conda env:imaging]",
300 | "language": "python",
301 | "name": "conda-env-imaging-py"
302 | },
303 | "language_info": {
304 | "codemirror_mode": {
305 | "name": "ipython",
306 | "version": 3
307 | },
308 | "file_extension": ".py",
309 | "mimetype": "text/x-python",
310 | "name": "python",
311 | "nbconvert_exporter": "python",
312 | "pygments_lexer": "ipython3",
313 | "version": "3.7.13"
314 | }
315 | },
316 | "nbformat": 4,
317 | "nbformat_minor": 4
318 | }
319 |
--------------------------------------------------------------------------------
/Generative/imgFX_pseudoHalftone.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Pseudo-Halftone\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [imgFX_pseudoHalftone.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Generative/imgFX_pseudoHalftone.ipynb)\n",
12 | "---\n",
13 | "Image effect algorithm that mimics the appearance of the halftone technique."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib.pyplot as plt\n",
24 | "import numpy as np\n",
25 | "import random, math, time\n",
26 | "from PIL import Image as image\n",
27 | "\n",
28 | "from _utils import *"
29 | ]
30 | },
31 | {
32 | "cell_type": "code",
33 | "execution_count": null,
34 | "metadata": {},
35 | "outputs": [],
36 | "source": [
37 | "def setRange(value, smin, smax, dmin, dmax):\n",
38 | " '''\n",
39 | " Linear interpolation\n",
40 | " '''\n",
41 | " value = float(value)\n",
42 | " smin, smax = float(smin), float(smax)\n",
43 | " dmin, dmax = float(dmin), float(dmax)\n",
44 | " out = dmin + ((value - smin)/(smax - smin))*(dmax - dmin)\n",
45 | " return int(out)"
46 | ]
47 | },
48 | {
49 | "cell_type": "markdown",
50 | "metadata": {},
51 | "source": [
52 | "## Additive mode\n",
53 | "---"
54 | ]
55 | },
56 | {
57 | "cell_type": "code",
58 | "execution_count": null,
59 | "metadata": {},
60 | "outputs": [],
61 | "source": [
62 | "class PointAdd:\n",
63 | " def __init__(self, tx, ty, cd):\n",
64 | " self.tx = tx\n",
65 | " self.ty = ty\n",
66 | " self.cd = cd\n",
67 | " \n",
68 | " def setRad(self, ioc):\n",
69 | " '''\n",
70 | " Radius definition\n",
71 | " '''\n",
72 | " self.rad = setRange(self.cd[ioc], 0, 255, minSize, maxSize)\n",
73 | " \n",
74 | " def circle(self, ioc):\n",
75 | " '''\n",
76 | " Draw a circle\n",
77 | " '''\n",
78 | " r1 = self.rad\n",
79 | " r2 = self.rad + antAlsg\n",
80 | " disp = (sb*0.5 - self.rad)*dispMult\n",
81 | " dispx = int(random.uniform(- disp, disp))\n",
82 | " dispy = int(random.uniform(- disp, disp))\n",
83 | " tx = self.tx + dispx\n",
84 | " ty = self.ty + dispy\n",
85 | " for y in range(ty - r2, ty + r2):\n",
86 | " for x in range(tx - r2, tx + r2):\n",
87 | " try:\n",
88 | " dx = math.pow(tx - x, 2.0)\n",
89 | " dy = math.pow(ty - y, 2.0)\n",
90 | " r = math.sqrt(dx + dy)\n",
91 | " if r <= r1:\n",
92 | " ca = 1\n",
93 | " elif r > r2:\n",
94 | " ca = 0\n",
95 | " else:\n",
96 | " ca = (r2 - r)/(r2 - r1)\n",
97 | " cdt = imgOut.getpixel((x, y))\n",
98 | " if(cnorm == True):\n",
99 | " cc = int(255*ca + cdt[ioc])\n",
100 | " else:\n",
101 | " cc = int(self.cd[ioc]*ca + cdt[ioc])\n",
102 | " if(ioc == 0):\n",
103 | " imgOut.putpixel((x, y), (cc, cdt[1], cdt[2]))\n",
104 | " elif(ioc == 1):\n",
105 | " imgOut.putpixel((x, y), (cdt[0], cc, cdt[2]))\n",
106 | " else:\n",
107 | " imgOut.putpixel((x, y), (cdt[0], cdt[1], cc))\n",
108 | " except:\n",
109 | " continue"
110 | ]
111 | },
112 | {
113 | "cell_type": "code",
114 | "execution_count": null,
115 | "metadata": {},
116 | "outputs": [],
117 | "source": [
118 | "%%time\n",
119 | "# parameters\n",
120 | "sb = 12 # space between the center of the points\n",
121 | "minSize = 2 # minimum size\n",
122 | "maxSize = 6 # maximum size\n",
123 | "dispMult = 1.0 # channel dispersion\n",
124 | "cnorm = False # switch for color normalization\n",
125 | "antAlsg = 1 # circle antialiasing\n",
126 | "BG = (10, 15, 20) # background color\n",
127 | "\n",
128 | "# init\n",
129 | "img = image.open('../_data/woman03.png')\n",
130 | "imx = img.size[0]\n",
131 | "imy = img.size[1]\n",
132 | "imgIn = image.new('RGB', img.size)\n",
133 | "imgIn.paste(img)\n",
134 | "imgOut = image.new('RGB', img.size, BG)\n",
135 | "\n",
136 | "# execução\n",
137 | "lpt = []\n",
138 | "y, i = 0, 0\n",
139 | "while(y < imy):\n",
140 | " x = int(sb*0.5)*(i % 2) # shifting points in the even lines\n",
141 | " while(x < imx):\n",
142 | " cd = imgIn.getpixel((x, y))\n",
143 | " temp = PointAdd(x, y, cd)\n",
144 | " lpt.append(temp)\n",
145 | " x += sb\n",
146 | " i += 1\n",
147 | " y += sb\n",
148 | "for channel in range(3):\n",
149 | " for point in lpt:\n",
150 | " point.setRad(channel)\n",
151 | " point.circle(channel)\n",
152 | "\n",
153 | "output = np.array([np.asarray(imgIn),\n",
154 | " np.asarray(imgOut)])\n",
155 | "panel(output, (2, 1))"
156 | ]
157 | },
158 | {
159 | "cell_type": "markdown",
160 | "metadata": {},
161 | "source": [
162 | "## Subtractive mode\n",
163 | "---"
164 | ]
165 | },
166 | {
167 | "cell_type": "code",
168 | "execution_count": null,
169 | "metadata": {},
170 | "outputs": [],
171 | "source": [
172 | "class PointSub:\n",
173 | " def __init__(self, tx, ty, cd):\n",
174 | " self.tx = tx\n",
175 | " self.ty = ty\n",
176 | " self.cd = cd\n",
177 | " \n",
178 | " def setRad(self, ioc):\n",
179 | " '''\n",
180 | " Radius definition\n",
181 | " '''\n",
182 | " self.rad = setRange(self.cd[ioc], 0, 255, maxSize, minSize)\n",
183 | " \n",
184 | " def circle(self, ioc):\n",
185 | " '''\n",
186 | " Draw circle\n",
187 | " '''\n",
188 | " r1 = self.rad\n",
189 | " r2 = self.rad + antAlsg\n",
190 | " disp = (sb*0.5 - self.rad)*dispMult\n",
191 | " dispx = int(random.uniform(- disp, disp))\n",
192 | " dispy = int(random.uniform(- disp, disp))\n",
193 | " tx = self.tx + dispx\n",
194 | " ty = self.ty + dispy\n",
195 | " for y in range(ty - r2, ty + r2):\n",
196 | " for x in range(tx - r2, tx + r2):\n",
197 | " try:\n",
198 | " dx = math.pow(tx - x, 2.0)\n",
199 | " dy = math.pow(ty - y, 2.0)\n",
200 | " r = math.sqrt(dx + dy)\n",
201 | " if r <= r1:\n",
202 | " ca = 1\n",
203 | " elif r > r2:\n",
204 | " ca = 0\n",
205 | " else:\n",
206 | " ca = (r2 - r)/(r2 - r1)\n",
207 | " cdt = imgOut.getpixel((x, y))\n",
208 | " if(cnorm == True):\n",
209 | " cc = int(cdt[ioc] - 255*ca)\n",
210 | " else:\n",
211 | " cc = int(cdt[ioc] - self.cd[ioc]*ca)\n",
212 | " if(ioc == 0):\n",
213 | " imgOut.putpixel((x, y), (cc, cdt[1], cdt[2]))\n",
214 | " elif(ioc == 1):\n",
215 | " imgOut.putpixel((x, y), (cdt[0], cc, cdt[2]))\n",
216 | " else:\n",
217 | " imgOut.putpixel((x, y), (cdt[0], cdt[1], cc))\n",
218 | " except:\n",
219 | " continue"
220 | ]
221 | },
222 | {
223 | "cell_type": "code",
224 | "execution_count": null,
225 | "metadata": {},
226 | "outputs": [],
227 | "source": [
228 | "%%time\n",
229 | "# parameters\n",
230 | "sb = 12 # space between the center of points\n",
231 | "minSize = 2 # minimum size\n",
232 | "maxSize = 6 # maximum size\n",
233 | "dispMult = 0.75 # channel dispersion\n",
234 | "cnorm = True # switch for color normalization\n",
235 | "antAlsg = 1 # circle antialiasing\n",
236 | "BG = (220, 220, 220) # background color\n",
237 | "\n",
238 | "# init\n",
239 | "img = image.open('../_data/pimentos.png')\n",
240 | "imx = img.size[0]\n",
241 | "imy = img.size[1]\n",
242 | "imgIn = image.new('RGB', img.size)\n",
243 | "imgIn.paste(img)\n",
244 | "imgOut = image.new('RGB', img.size, BG)\n",
245 | "\n",
246 | "# execution\n",
247 | "lpt = []\n",
248 | "y, i = 0, 0\n",
249 | "while(y < imy):\n",
250 | " x = int(sb*0.5)*(i % 2) # shifting points in the even lines\n",
251 | " while(x < imx):\n",
252 | " cd = imgIn.getpixel((x, y))\n",
253 | " temp = PointSub(x, y, cd)\n",
254 | " lpt.append(temp)\n",
255 | " x += sb\n",
256 | " i += 1\n",
257 | " y += sb\n",
258 | "for channel in range(3):\n",
259 | " for point in lpt:\n",
260 | " point.setRad(channel)\n",
261 | " point.circle(channel)\n",
262 | "\n",
263 | "output = np.array([np.asarray(imgIn),\n",
264 | " np.asarray(imgOut)])\n",
265 | "panel(output, (2, 1))"
266 | ]
267 | }
268 | ],
269 | "metadata": {
270 | "kernelspec": {
271 | "display_name": "Python 3",
272 | "language": "python",
273 | "name": "python3"
274 | },
275 | "language_info": {
276 | "codemirror_mode": {
277 | "name": "ipython",
278 | "version": 3
279 | },
280 | "file_extension": ".py",
281 | "mimetype": "text/x-python",
282 | "name": "python",
283 | "nbconvert_exporter": "python",
284 | "pygments_lexer": "ipython3",
285 | "version": "3.7.7"
286 | }
287 | },
288 | "nbformat": 4,
289 | "nbformat_minor": 2
290 | }
291 |
--------------------------------------------------------------------------------
/Generative/imgFX_scatterCircles.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Circle Scatter Diagram\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [imgFX_scatterCircles.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Generative/imgFX_scatterCircles.ipynb)\n",
12 | "---\n",
13 | "Image effect algorithm that scatters raster circles (with anti-aliasing)."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib.pyplot as plt\n",
24 | "import numpy as np\n",
25 | "import random, math, time\n",
26 | "from PIL import Image as image\n",
27 | "\n",
28 | "from _utils import *"
29 | ]
30 | },
31 | {
32 | "cell_type": "code",
33 | "execution_count": null,
34 | "metadata": {},
35 | "outputs": [],
36 | "source": [
37 | "def average(vec3):\n",
38 | " '''\n",
39 | " Returns the mean value between axes\n",
40 | " '''\n",
41 | " avr = int((vec3[0] + vec3[1] + vec3[2])/3.0)\n",
42 | " return avr\n",
43 | "\n",
44 | "def midHigh(img):\n",
45 | " '''\n",
46 | " Returns the median and the maximum value of the input image\n",
47 | " '''\n",
48 | " mid = [0.0, 0.0, 0.0]\n",
49 | " high = [0.0, 0.0, 0.0]\n",
50 | " for y in range(imy):\n",
51 | " for x in range(imx):\n",
52 | " pix = img.getpixel((x, y))\n",
53 | " mid[0] += pix[0]\n",
54 | " mid[1] += pix[1]\n",
55 | " mid[2] += pix[2]\n",
56 | " if average(pix) > average(high): high = pix\n",
57 | " else: continue\n",
58 | " mid[0] = int(mid[0]/(imx*imy))\n",
59 | " mid[1] = int(mid[1]/(imx*imy))\n",
60 | " mid[2] = int(mid[2]/(imx*imy))\n",
61 | " return (tuple(mid), tuple(high))\n",
62 | "\n",
63 | "def setRange(value, smin, smax, dmin, dmax):\n",
64 | " '''\n",
65 | " Linear interpolation\n",
66 | " '''\n",
67 | " value = float(value)\n",
68 | " smin, smax = float(smin), float(smax)\n",
69 | " dmin, dmax = float(dmin), float(dmax)\n",
70 | " out = dmin + ((value - smin)/(smax - smin))*(dmax - dmin)\n",
71 | " return int(out)\n",
72 | "\n",
73 | "class Point:\n",
74 | " def __init__(self, tx, ty, cd, lvl):\n",
75 | " self.tx = tx\n",
76 | " self.ty = ty\n",
77 | " self.cd = tuple(cd)\n",
78 | " rad = setRange(lvl, lod - 1, 0, minSize, maxSize)\n",
79 | " self.rad = int(random.uniform(rad - rad*varSize, rad + rad*varSize))\n",
80 | " \n",
81 | " def circle(self):\n",
82 | " '''\n",
83 | " Draw a circle\n",
84 | " '''\n",
85 | " r1 = self.rad\n",
86 | " r2 = self.rad + antAlsg\n",
87 | " for y in range(self.ty - r2, self.ty + r2):\n",
88 | " for x in range(self.tx - r2, self.tx + r2):\n",
89 | " try:\n",
90 | " dx = math.pow(self.tx - x, 2.0)\n",
91 | " dy = math.pow(self.ty - y, 2.0)\n",
92 | " r = math.sqrt(dx + dy)\n",
93 | " if r <= r1:\n",
94 | " imgOut.putpixel((x, y), self.cd)\n",
95 | " elif r > r2:\n",
96 | " cdt = imgOut.getpixel((x, y))\n",
97 | " imgOut.putpixel((x, y), cdt)\n",
98 | " else:\n",
99 | " cdt = imgOut.getpixel((x, y))\n",
100 | " ca = (r2 - r)/(r2 - r1)\n",
101 | " cr = int(self.cd[0]*ca + cdt[0]*(1 - ca))\n",
102 | " cg = int(self.cd[1]*ca + cdt[1]*(1 - ca))\n",
103 | " cb = int(self.cd[2]*ca + cdt[2]*(1 - ca))\n",
104 | " imgOut.putpixel((x, y), (cr, cg, cb))\n",
105 | " except:\n",
106 | " continue"
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "execution_count": null,
112 | "metadata": {},
113 | "outputs": [],
114 | "source": [
115 | "%%time\n",
116 | "# parameters\n",
117 | "lod = 8 # level of detail\n",
118 | "minSamp = 0.001 # minimum probability\n",
119 | "maxSamp = 0.01 # maximum probability\n",
120 | "\n",
121 | "minSize = 8 # minimum size\n",
122 | "maxSize = 32 # maximum size\n",
123 | "varSize = 0.5 # size deviation\n",
124 | "antAlsg = 1 # circle antialising level\n",
125 | "\n",
126 | "# init\n",
127 | "img = image.open('../_data/fruits.png')\n",
128 | "imx = img.size[0]\n",
129 | "imy = img.size[1]\n",
130 | "imgIn = image.new('RGB', img.size)\n",
131 | "imgIn.paste(img)\n",
132 | "midPix, highPix = midHigh(imgIn)\n",
133 | "highPixMax = max(highPix)\n",
134 | "imgOut = image.new('RGB', img.size, midPix)\n",
135 | "\n",
136 | "# execution\n",
137 | "imgArr = np.asarray(imgIn)\n",
138 | "imgArrM = imgArr.max(axis=2)\n",
139 | "lpt = []\n",
140 | "for lvl in range(lod):\n",
141 | " mmin = int(lvl*highPixMax/lod)\n",
142 | " mmax = int((lvl + 1)*highPixMax/lod)\n",
143 | " sel = np.argwhere(np.logical_and(imgArrM > mmin,\n",
144 | " imgArrM <= mmax))\n",
145 | " sel = np.argwhere(imgArrM > mmin)\n",
146 | " np.random.shuffle(sel)\n",
147 | " lim = np.linspace(minSamp, maxSamp, lod)[lvl]\n",
148 | " lim = int(lim*len(sel))\n",
149 | " for py, px in sel[:lim]:\n",
150 | " cd = imgArr[py, px]\n",
151 | " lpt.append(Point(px, py, cd, lvl))\n",
152 | " \n",
153 | "for point in lpt:\n",
154 | " point.circle()\n",
155 | "\n",
156 | "output = np.array([np.asarray(imgIn),\n",
157 | " np.asarray(imgOut)])\n",
158 | "panel(output, (2, 1))"
159 | ]
160 | }
161 | ],
162 | "metadata": {
163 | "kernelspec": {
164 | "display_name": "Python 3",
165 | "language": "python",
166 | "name": "python3"
167 | },
168 | "language_info": {
169 | "codemirror_mode": {
170 | "name": "ipython",
171 | "version": 3
172 | },
173 | "file_extension": ".py",
174 | "mimetype": "text/x-python",
175 | "name": "python",
176 | "nbconvert_exporter": "python",
177 | "pygments_lexer": "ipython3",
178 | "version": "3.7.7"
179 | }
180 | },
181 | "nbformat": 4,
182 | "nbformat_minor": 2
183 | }
184 |
--------------------------------------------------------------------------------
/Generative/imgFX_scatterSquares.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Square Scatter Diagram\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [imgFX_scatterSquares.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Generative/imgFX_scatterSquares.ipynb)\n",
12 | "---\n",
13 | "Image effect algorithm that scatters raster squares."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib.pyplot as plt\n",
24 | "import numpy as np\n",
25 | "import random, math, time\n",
26 | "from PIL import Image as image\n",
27 | "\n",
28 | "from _utils import *"
29 | ]
30 | },
31 | {
32 | "cell_type": "code",
33 | "execution_count": null,
34 | "metadata": {},
35 | "outputs": [],
36 | "source": [
37 | "def average(vec3):\n",
38 | " '''\n",
39 | " Returns the mean value between axes\n",
40 | " '''\n",
41 | " avr = int((vec3[0] + vec3[1] + vec3[2])/3.0)\n",
42 | " return avr\n",
43 | "\n",
44 | "def midHigh(img):\n",
45 | " '''\n",
46 | " Returns the median and the maximum value of the input image\n",
47 | " '''\n",
48 | " mid = [0.0, 0.0, 0.0]\n",
49 | " high = [0.0, 0.0, 0.0]\n",
50 | " for y in range(imy):\n",
51 | " for x in range(imx):\n",
52 | " pix = img.getpixel((x, y))\n",
53 | " mid[0] += pix[0]\n",
54 | " mid[1] += pix[1]\n",
55 | " mid[2] += pix[2]\n",
56 | " if average(pix) > average(high): high = pix\n",
57 | " else: continue\n",
58 | " mid[0] = int(mid[0]/(imx*imy))\n",
59 | " mid[1] = int(mid[1]/(imx*imy))\n",
60 | " mid[2] = int(mid[2]/(imx*imy))\n",
61 | " return (tuple(mid), tuple(high))\n",
62 | "\n",
63 | "def setRange(value, smin, smax, dmin, dmax):\n",
64 | " '''\n",
65 | " Linear interpolation\n",
66 | " '''\n",
67 | " value = float(value)\n",
68 | " smin, smax = float(smin), float(smax)\n",
69 | " dmin, dmax = float(dmin), float(dmax)\n",
70 | " out = dmin + ((value - smin)/(smax - smin))*(dmax - dmin)\n",
71 | " return int(out)\n",
72 | "\n",
73 | "class Point:\n",
74 | " def __init__(self, tx, ty, cd, lvl):\n",
75 | " self.tx = tx\n",
76 | " self.ty = ty\n",
77 | " self.cd = tuple(cd)\n",
78 | " rad = setRange(lvl, lod - 1, 0, minSize, maxSize)\n",
79 | " self.rad = int(random.uniform(rad - rad*varSize, rad + rad*varSize))\n",
80 | " \n",
81 | " def square(self):\n",
82 | " '''\n",
83 | " Draw a square\n",
84 | " '''\n",
85 | " for y in range(self.ty - self.rad, self.ty + self.rad):\n",
86 | " for x in range(self.tx - self.rad, self.tx + self.rad):\n",
87 | " try:\n",
88 | " imgOut.putpixel((x, y), self.cd)\n",
89 | " except:\n",
90 | " continue"
91 | ]
92 | },
93 | {
94 | "cell_type": "code",
95 | "execution_count": null,
96 | "metadata": {},
97 | "outputs": [],
98 | "source": [
99 | "%%time\n",
100 | "# parameters\n",
101 | "lod = 8 # level of detail\n",
102 | "minSamp = 0.001 # minimum probability\n",
103 | "maxSamp = 0.05 # maximum probability\n",
104 | "\n",
105 | "minSize = 8 # minimum size\n",
106 | "maxSize = 32 # maximum size\n",
107 | "varSize = 0.5 # size deviation\n",
108 | "\n",
109 | "# inicialização\n",
110 | "img = image.open('../_data/pimentos.png')\n",
111 | "imx = img.size[0]\n",
112 | "imy = img.size[1]\n",
113 | "imgIn = image.new('RGB', img.size)\n",
114 | "imgIn.paste(img)\n",
115 | "midPix, highPix = midHigh(imgIn)\n",
116 | "highPixMax = max(highPix)\n",
117 | "imgOut = image.new('RGB', img.size, midPix)\n",
118 | "\n",
119 | "# execução\n",
120 | "imgArr = np.asarray(imgIn)\n",
121 | "imgArrM = imgArr.max(axis=2)\n",
122 | "lpt = []\n",
123 | "for lvl in range(lod):\n",
124 | " mmin = int(lvl*highPixMax/lod)\n",
125 | " mmax = int((lvl + 1)*highPixMax/lod)\n",
126 | " sel = np.argwhere(np.logical_and(imgArrM > mmin,\n",
127 | " imgArrM <= mmax))\n",
128 | " sel = np.argwhere(imgArrM > mmin)\n",
129 | " np.random.shuffle(sel)\n",
130 | " lim = np.linspace(minSamp, maxSamp, lod)[lvl]\n",
131 | " lim = int(lim*len(sel))\n",
132 | " for py, px in sel[:lim]:\n",
133 | " cd = imgArr[py, px]\n",
134 | " lpt.append(Point(px, py, cd, lvl))\n",
135 | " \n",
136 | "for point in lpt:\n",
137 | " point.square()\n",
138 | "\n",
139 | "output = np.array([np.asarray(imgIn),\n",
140 | " np.asarray(imgOut)])\n",
141 | "panel(output, (2, 1))"
142 | ]
143 | }
144 | ],
145 | "metadata": {
146 | "kernelspec": {
147 | "display_name": "Python 3",
148 | "language": "python",
149 | "name": "python3"
150 | },
151 | "language_info": {
152 | "codemirror_mode": {
153 | "name": "ipython",
154 | "version": 3
155 | },
156 | "file_extension": ".py",
157 | "mimetype": "text/x-python",
158 | "name": "python",
159 | "nbconvert_exporter": "python",
160 | "pygments_lexer": "ipython3",
161 | "version": "3.7.7"
162 | }
163 | },
164 | "nbformat": 4,
165 | "nbformat_minor": 2
166 | }
167 |
--------------------------------------------------------------------------------
/Generative/imgFX_segments.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Segments\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [imgFX_segments.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Generative/imgFX_segments.ipynb)\n",
12 | "---\n",
13 | "Image effect algorithm that simulates small filaments inspired by old watch LCDs."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib.pyplot as plt\n",
24 | "import numpy as np\n",
25 | "import random, math, time\n",
26 | "from PIL import Image as image\n",
27 | "\n",
28 | "from _utils import *"
29 | ]
30 | },
31 | {
32 | "cell_type": "code",
33 | "execution_count": null,
34 | "metadata": {},
35 | "outputs": [],
36 | "source": [
37 | "class Segment:\n",
38 | " def __init__(self, tx, ty, width, offset, orient):\n",
39 | " self.tx = tx + int(size*0.5)\n",
40 | " self.ty = ty + int(size*0.5)\n",
41 | " self.width = int(size*width)\n",
42 | " self.offset = int(size*offset) - int(size*0.5)\n",
43 | " self.orient = orient\n",
44 | " \n",
45 | " def kernel(self):\n",
46 | " '''\n",
47 | " Kernel definition\n",
48 | " '''\n",
49 | " self.xmin = self.tx - int(size*0.5)\n",
50 | " self.xmax = self.tx + int(size*0.5)\n",
51 | " self.ymin = self.ty - int(size*0.5)\n",
52 | " self.ymax = self.ty + int(size*0.5)\n",
53 | " \n",
54 | " def getColor(self):\n",
55 | " '''\n",
56 | " Segment color\n",
57 | " '''\n",
58 | " cr, cg, cb = 0, 0, 0\n",
59 | " count = 0\n",
60 | " for y in range(self.ymin, self.ymax):\n",
61 | " for x in range(self.xmin, self.xmax):\n",
62 | " try:\n",
63 | " c = imgIn.getpixel((x, y))\n",
64 | " cr += c[0]\n",
65 | " cg += c[1]\n",
66 | " cb += c[2]\n",
67 | " count += 1\n",
68 | " except:\n",
69 | " continue\n",
70 | " cr = int(cr/count)\n",
71 | " cg = int(cg/count)\n",
72 | " cb = int(cb/count)\n",
73 | " self.cd = (cr, cg, cb)\n",
74 | " \n",
75 | " def draw(self):\n",
76 | " '''\n",
77 | " Draw a segment\n",
78 | " '''\n",
79 | " for y in range(self.ymin, self.ymax):\n",
80 | " for x in range(self.xmin, self.xmax):\n",
81 | " try:\n",
82 | " lim = max(self.xmax + self.ymin + self.offset, self.xmin + self.ymax + self.offset)\n",
83 | " if ((x + y) >= lim - self.width) & ((x + y) < lim + self.width - 1):\n",
84 | " if self.orient == 0:\n",
85 | " imgOut.putpixel((x, y), self.cd)\n",
86 | " else:\n",
87 | " imgOut.putpixel(((self.xmax + self.xmin - x - 1), y), self.cd)\n",
88 | " else:\n",
89 | " continue\n",
90 | " except:\n",
91 | " continue"
92 | ]
93 | },
94 | {
95 | "cell_type": "code",
96 | "execution_count": null,
97 | "metadata": {},
98 | "outputs": [],
99 | "source": [
100 | "%%time\n",
101 | "# parameters\n",
102 | "size = 16 # kernel size\n",
103 | "BG = (50, 50, 50) # background color\n",
104 | "\n",
105 | "# init\n",
106 | "lista_img = ['woman02.png', 'cameraman.png', 'sailboat.png']\n",
107 | "for imagem in lista_img:\n",
108 | " img = image.open('../_data/' + imagem)\n",
109 | " imx = img.size[0]\n",
110 | " imy = img.size[1]\n",
111 | " imgIn = image.new('RGB', img.size)\n",
112 | " imgIn.paste(img)\n",
113 | " imgOut = image.new('RGB', img.size, BG)\n",
114 | "\n",
115 | " # execution\n",
116 | " los = []\n",
117 | "\n",
118 | " ty = 0\n",
119 | " while ty < imy:\n",
120 | " tx = 0\n",
121 | " while tx < imx:\n",
122 | " width = random.uniform(0.2, 0.4)\n",
123 | " offset = random.uniform(0.25, 0.75)\n",
124 | " orient = int(random.uniform(0, 2))\n",
125 | " temp = Segment(tx, ty, width, offset, orient)\n",
126 | " los.append(temp)\n",
127 | " tx += size\n",
128 | " ty += size\n",
129 | "\n",
130 | " for segm in los:\n",
131 | " segm.kernel()\n",
132 | " segm.getColor()\n",
133 | " segm.draw()\n",
134 | "\n",
135 | " output = np.array([np.asarray(imgIn),\n",
136 | " np.asarray(imgOut)])\n",
137 | " panel(output, (2, 1))"
138 | ]
139 | }
140 | ],
141 | "metadata": {
142 | "kernelspec": {
143 | "display_name": "Python 3",
144 | "language": "python",
145 | "name": "python3"
146 | },
147 | "language_info": {
148 | "codemirror_mode": {
149 | "name": "ipython",
150 | "version": 3
151 | },
152 | "file_extension": ".py",
153 | "mimetype": "text/x-python",
154 | "name": "python",
155 | "nbconvert_exporter": "python",
156 | "pygments_lexer": "ipython3",
157 | "version": "3.7.7"
158 | }
159 | },
160 | "nbformat": 4,
161 | "nbformat_minor": 2
162 | }
163 |
--------------------------------------------------------------------------------
/Generative/imgFX_strings.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Strings\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [imgFX_strings.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Generative/imgFX_strings.ipynb)\n",
12 | "---\n",
13 | "Image effect algorithm that traces lines with radius variation."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib.pyplot as plt\n",
24 | "import numpy as np\n",
25 | "import random, math, time\n",
26 | "from PIL import Image as image\n",
27 | "\n",
28 | "from _utils import *"
29 | ]
30 | },
31 | {
32 | "cell_type": "code",
33 | "execution_count": null,
34 | "metadata": {},
35 | "outputs": [],
36 | "source": [
37 | "def averColor(color):\n",
38 | " '''\n",
39 | " Returns the mean value between channels\n",
40 | " '''\n",
41 | " cr = float(color[0])\n",
42 | " cg = float(color[1])\n",
43 | " cb = float(color[2])\n",
44 | " cd = (cr + cg + cb)/3\n",
45 | " return cd\n",
46 | "\n",
47 | "def setRange(value, smin, smax, dmin, dmax):\n",
48 | " '''\n",
49 | " Linear interpolation\n",
50 | " '''\n",
51 | " value = float(value)\n",
52 | " smin, smax = float(smin), float(smax)\n",
53 | " dmin, dmax = float(dmin), float(dmax)\n",
54 | " out = dmin + ((value - smin)/(smax - smin))*(dmax - dmin)\n",
55 | " return int(out)\n",
56 | "\n",
57 | "class Point:\n",
58 | " def __init__(self, tx, ty):\n",
59 | " self.tx = tx\n",
60 | " self.ty = ty\n",
61 | " \n",
62 | " def setColor(self):\n",
63 | " '''\n",
64 | " Color defining\n",
65 | " '''\n",
66 | " self.cd = imgIn.getpixel((self.tx, self.ty))\n",
67 | " \n",
68 | " def setRad(self):\n",
69 | " '''\n",
70 | " Radius defining\n",
71 | " '''\n",
72 | " try:\n",
73 | " apix = averColor(self.cd)\n",
74 | " self.rad = setRange(apix, 0, 255, minSize, maxSize)\n",
75 | " except:\n",
76 | " self.rad = minSize\n",
77 | " \n",
78 | " def circle(self):\n",
79 | " '''\n",
80 | " Draw circle\n",
81 | " '''\n",
82 | " r1 = self.rad\n",
83 | " r2 = self.rad + antAlsg\n",
84 | " for y in range(self.ty - r2, self.ty + r2):\n",
85 | " for x in range(self.tx - r2, self.tx + r2):\n",
86 | " try:\n",
87 | " dx = math.pow(self.tx - x, 2.0)\n",
88 | " dy = math.pow(self.ty - y, 2.0)\n",
89 | " r = math.sqrt(dx + dy)\n",
90 | " if r <= r1:\n",
91 | " imgOut.putpixel((x, y), self.cd)\n",
92 | " elif r > r2:\n",
93 | " cdt = imgOut.getpixel((x, y))\n",
94 | " imgOut.putpixel((x, y), cdt)\n",
95 | " else:\n",
96 | " cdt = imgOut.getpixel((x, y))\n",
97 | " ca = (r2 - r)/(r2 - r1)\n",
98 | " cr = int(self.cd[0]*ca + cdt[0]*(1 - ca))\n",
99 | " cg = int(self.cd[1]*ca + cdt[1]*(1 - ca))\n",
100 | " cb = int(self.cd[2]*ca + cdt[2]*(1 - ca))\n",
101 | " imgOut.putpixel((x, y), (cr, cg, cb))\n",
102 | " except:\n",
103 | " continue"
104 | ]
105 | },
106 | {
107 | "cell_type": "code",
108 | "execution_count": null,
109 | "metadata": {},
110 | "outputs": [],
111 | "source": [
112 | "%%time\n",
113 | "# parameters\n",
114 | "sb = 8 # space between strings\n",
115 | "minSize = 0 # minimum size\n",
116 | "maxSize = 5 # maximum size\n",
117 | "antAlsg = 1 # circle antialising level\n",
118 | "BG = (100, 0, 100) # background color\n",
119 | "\n",
120 | "# init\n",
121 | "img = image.open('../_data/earth.png')\n",
122 | "imx = img.size[0]\n",
123 | "imy = img.size[1]\n",
124 | "imgIn = image.new('RGB', img.size)\n",
125 | "imgIn.paste(img)\n",
126 | "imgOut = image.new('RGB', img.size, BG)\n",
127 | "\n",
128 | "# ececution\n",
129 | "lpt = []\n",
130 | "for x in range(0, imx - 1, sb):\n",
131 | " for y in range(imy - 1):\n",
132 | " p = Point(x, y)\n",
133 | " lpt.append(p)\n",
134 | "\n",
135 | "for point in lpt:\n",
136 | " point.setColor()\n",
137 | " point.setRad()\n",
138 | " point.circle()\n",
139 | "\n",
140 | "output = np.array([np.asarray(imgIn),\n",
141 | " np.asarray(imgOut)])\n",
142 | "panel(output, (2, 1))"
143 | ]
144 | }
145 | ],
146 | "metadata": {
147 | "kernelspec": {
148 | "display_name": "Python 3",
149 | "language": "python",
150 | "name": "python3"
151 | },
152 | "language_info": {
153 | "codemirror_mode": {
154 | "name": "ipython",
155 | "version": 3
156 | },
157 | "file_extension": ".py",
158 | "mimetype": "text/x-python",
159 | "name": "python",
160 | "nbconvert_exporter": "python",
161 | "pygments_lexer": "ipython3",
162 | "version": "3.7.7"
163 | }
164 | },
165 | "nbformat": 4,
166 | "nbformat_minor": 2
167 | }
168 |
--------------------------------------------------------------------------------
/Generative/imgFX_tracing.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Diagonal Tracing\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [imgFX_tracing.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Generative/imgFX_tracing.ipynb)\n",
12 | "---\n",
13 | "Image effect algorithm that produces stylized diagonal stripes with color conditionals."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib.pyplot as plt\n",
24 | "import numpy as np\n",
25 | "import random, math, time\n",
26 | "from PIL import Image as image\n",
27 | "\n",
28 | "from _utils import *"
29 | ]
30 | },
31 | {
32 | "cell_type": "code",
33 | "execution_count": null,
34 | "metadata": {},
35 | "outputs": [],
36 | "source": [
37 | "def clamp(value, vmin, vmax):\n",
38 | " '''\n",
39 | " Clamp function\n",
40 | " '''\n",
41 | " if(value < vmin):\n",
42 | " value = vmin\n",
43 | " if(value > vmax):\n",
44 | " value = vmax\n",
45 | " return value\n",
46 | "\n",
47 | "def searchPoints(po):\n",
48 | " '''\n",
49 | " Search points\n",
50 | " '''\n",
51 | " co = imgIn.getpixel((clamp(po[0], 0, imx - 1),\n",
52 | " clamp(po[1], 0, imy - 1)))\n",
53 | " pi, ci = po, co\n",
54 | " x, y = po[0], po[1]\n",
55 | " while((x < imx) or (y < imy)):\n",
56 | " x += 1\n",
57 | " y += 1\n",
58 | " try:\n",
59 | " pi = (x, y)\n",
60 | " ci = imgIn.getpixel(pi)\n",
61 | " if((abs(ci[0] - co[0]) > colorDisp) +\n",
62 | " (abs(ci[1] - co[1]) > colorDisp) +\n",
63 | " (abs(ci[2] - co[2]) > colorDisp)):\n",
64 | " pi = (x - 1, y - 1)\n",
65 | " ci = imgIn.getpixel(pi)\n",
66 | " break\n",
67 | " except:\n",
68 | " continue\n",
69 | " return po, pi, co, ci\n",
70 | "\n",
71 | "def drawL(tx, ty, rad, cd):\n",
72 | " '''\n",
73 | " Draw a trace\n",
74 | " '''\n",
75 | " for i in range(rad + 1):\n",
76 | " try:\n",
77 | " px = int(tx - rad/2 + i)\n",
78 | " py = int(ty + rad/2 - i)\n",
79 | " imgOut.putpixel((px, py), cd)\n",
80 | " except:\n",
81 | " continue"
82 | ]
83 | },
84 | {
85 | "cell_type": "code",
86 | "execution_count": null,
87 | "metadata": {},
88 | "outputs": [],
89 | "source": [
90 | "%%time\n",
91 | "# parameters\n",
92 | "rad = 4\n",
93 | "sb = 6\n",
94 | "colorDisp = 50 # color dispersion tolerance\n",
95 | "BG = (20, 30, 10) # background color\n",
96 | "\n",
97 | "# init\n",
98 | "lista_img = ['pimentos.png', 'babuino.png', 'aerial03.png']\n",
99 | "for imagem in lista_img:\n",
100 | " img = image.open('../_data/' + imagem)\n",
101 | " imx = img.size[0]\n",
102 | " imy = img.size[1]\n",
103 | " imgIn = image.new('RGB', img.size)\n",
104 | " imgIn.paste(img)\n",
105 | " imgOut = image.new('RGB', img.size, BG)\n",
106 | "\n",
107 | " # execution\n",
108 | " x, y = 0, 0\n",
109 | " i, j = 0, 0\n",
110 | " po = (0, 0)\n",
111 | " imyy = imy\n",
112 | " while(x < imx):\n",
113 | " while(y < imyy):\n",
114 | " i, j = po[0], po[1]\n",
115 | " while((i < imx) or (j < imy)):\n",
116 | " po, pi, co, ci = searchPoints(po)\n",
117 | "\n",
118 | " cd = co\n",
119 | " dx = (pi[0] - po[0])\n",
120 | " try:\n",
121 | " rs = (float(ci[0]) - float(co[0]))/dx\n",
122 | " gs = (float(ci[1]) - float(co[1]))/dx\n",
123 | " bs = (float(ci[2]) - float(co[2]))/dx\n",
124 | " cs = (rs, gs, bs)\n",
125 | " except:\n",
126 | " cs = (1, 1, 1)\n",
127 | "\n",
128 | " for k in range(dx):\n",
129 | " drawL(k + i, k + j, rad, cd)\n",
130 | " cd = (int(cd[0] + cs[0]), int(cd[1] + cs[1]), int(cd[2] + cs[2]))\n",
131 | "\n",
132 | " i = clamp(pi[0] + 1, 0, imx)\n",
133 | " j = clamp(pi[1] + 1, 0, imy)\n",
134 | " po = (i, j)\n",
135 | "\n",
136 | " if(x == 0):\n",
137 | " y += clamp(rad*2 + sb, 0, imy - 1)\n",
138 | " else:\n",
139 | " y = imyy\n",
140 | " po = (x, y)\n",
141 | "\n",
142 | " x += clamp(rad*2 + sb, 0, imx - 1)\n",
143 | " y = 0\n",
144 | " po = (x, y)\n",
145 | " imyy = 1\n",
146 | "\n",
147 | " output = np.array([np.asarray(imgIn),\n",
148 | " np.asarray(imgOut)])\n",
149 | " panel(output, (2, 1))"
150 | ]
151 | }
152 | ],
153 | "metadata": {
154 | "kernelspec": {
155 | "display_name": "Python 3",
156 | "language": "python",
157 | "name": "python3"
158 | },
159 | "language_info": {
160 | "codemirror_mode": {
161 | "name": "ipython",
162 | "version": 3
163 | },
164 | "file_extension": ".py",
165 | "mimetype": "text/x-python",
166 | "name": "python",
167 | "nbconvert_exporter": "python",
168 | "pygments_lexer": "ipython3",
169 | "version": "3.7.7"
170 | }
171 | },
172 | "nbformat": 4,
173 | "nbformat_minor": 2
174 | }
175 |
--------------------------------------------------------------------------------
/Generative/imgFX_voronoi.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Voronoi Diagram\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [imgFX_voronoi.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Generative/imgFX_voronoi.ipynb)\n",
12 | "---\n",
13 | "Image effect algorithm that produces different results based on different distance metrics.\n",
14 | "\n",
15 | "[Voronoi diagram](https://en.wikipedia.org/wiki/Voronoi_diagram) defined by distance between the pixel matrix $\\large m$ and the subset of the central points $\\large c$ (randomicaly defined) given your respectively index, which are them spacial coordinates $\\large x$ and $\\large y$. Different effects are made with different distance metrics."
16 | ]
17 | },
18 | {
19 | "cell_type": "code",
20 | "execution_count": null,
21 | "metadata": {},
22 | "outputs": [],
23 | "source": [
24 | "%matplotlib inline\n",
25 | "import matplotlib.pyplot as plt\n",
26 | "import numpy as np\n",
27 | "import random, math, time\n",
28 | "from PIL import Image as image\n",
29 | "\n",
30 | "from _utils import *"
31 | ]
32 | },
33 | {
34 | "cell_type": "markdown",
35 | "metadata": {},
36 | "source": [
37 | "## Euclidean distance\n",
38 | "---\n",
39 | "Diagram defined by [euclidean distance](https://en.wikipedia.org/wiki/Euclidean_distance) which term is the $L_2$ norm:\n",
40 | "$$ \\displaystyle \\large\n",
41 | "d(m,c) \\mapsto \\|m-c\\|_2 = \\left[\\sum_{i}^{n}(m_i-c_i)^2\\right]^\\frac{1}{2} = \\sqrt{\\sum_{i}^{n}(m_i-c_i)^2}\n",
42 | "$$"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": null,
48 | "metadata": {},
49 | "outputs": [],
50 | "source": [
51 | "%%time\n",
52 | "# parameters\n",
53 | "n = 2048 # number of points c\n",
54 | "sb = 4 # space between slices\n",
55 | "BG = (0, 0, 0) # background color\n",
56 | "\n",
57 | "# init\n",
58 | "img = image.open('../_data/cameraman.png')\n",
59 | "imx = img.size[0]\n",
60 | "imy = img.size[1]\n",
61 | "imgIn = image.new('RGB', img.size)\n",
62 | "imgIn.paste(img)\n",
63 | "imgOut = image.new('RGB', img.size, BG)\n",
64 | "\n",
65 | "# execution\n",
66 | "cx = np.random.randint(0, imx, n)\n",
67 | "cy = np.random.randint(0, imy, n)\n",
68 | "pop = np.array([cx, cy]).T\n",
69 | "\n",
70 | "for y in range(imy):\n",
71 | " for x in range(imx):\n",
72 | " d = np.sum(((x, y) - pop)**2, axis=1)**0.5\n",
73 | " NP = pop[np.argmin(d)]\n",
74 | " cd = imgIn.getpixel((int(NP[0]), int(NP[1])))\n",
75 | " imgOut.putpixel((x, y), cd)\n",
76 | "\n",
77 | "output = np.array([np.asarray(imgIn),\n",
78 | " np.asarray(imgOut)])\n",
79 | "panel(output, (2, 1))"
80 | ]
81 | },
82 | {
83 | "cell_type": "markdown",
84 | "metadata": {},
85 | "source": [
86 | "## Manhattan\n",
87 | "---\n",
88 | "Diagram defined by [manhattan distance](https://en.wikipedia.org/wiki/Taxicab_geometry) (or Taxicab geometry) which term is the $L_1$ norm:\n",
89 | "$$ \\displaystyle \\large\n",
90 | "d(m,c) \\mapsto \\|m-c\\|_1 = \\sum_{i}^{n}|m_i-c_i|\n",
91 | "$$"
92 | ]
93 | },
94 | {
95 | "cell_type": "code",
96 | "execution_count": null,
97 | "metadata": {},
98 | "outputs": [],
99 | "source": [
100 | "%%time\n",
101 | "# parâmetros\n",
102 | "n = 1024 # number of points c\n",
103 | "sb = 4 # space between slices\n",
104 | "BG = (0, 0, 0) # background color\n",
105 | "\n",
106 | "# init\n",
107 | "img = image.open('../_data/aerial03.png')\n",
108 | "imx = img.size[0]\n",
109 | "imy = img.size[1]\n",
110 | "imgIn = image.new('RGB', img.size)\n",
111 | "imgIn.paste(img)\n",
112 | "imgOut = image.new('RGB', img.size, BG)\n",
113 | "\n",
114 | "# execution\n",
115 | "cx = np.random.randint(0, imx, n)\n",
116 | "cy = np.random.randint(0, imy, n)\n",
117 | "pop = np.array([cx, cy]).T\n",
118 | "\n",
119 | "for y in range(imy):\n",
120 | " for x in range(imx):\n",
121 | " d = np.sum(abs((x, y) - pop), axis=1)\n",
122 | " NP = pop[np.argmin(d)]\n",
123 | " cd = imgIn.getpixel((int(NP[0]), int(NP[1])))\n",
124 | " imgOut.putpixel((x, y), cd)\n",
125 | "\n",
126 | "output = np.array([np.asarray(imgIn),\n",
127 | " np.asarray(imgOut)])\n",
128 | "panel(output, (2, 1))"
129 | ]
130 | },
131 | {
132 | "cell_type": "markdown",
133 | "metadata": {},
134 | "source": [
135 | "## Chebyshev\n",
136 | "---\n",
137 | "Diagram defined by [chebyshev distance](https://en.wikipedia.org/wiki/Chebyshev_distance) which term is the $L_\\infty$ norm:\n",
138 | "$$ \\displaystyle \\large\n",
139 | "d(m,c) \\mapsto \\|m-c\\|_\\infty = \\lim_{p\\to\\infty} \\left(\\sum_{i}^{n}|m_i-c_i|^p\\right)^\\frac{1}{p} = \\overset{n}{\\underset{i}{\\max}}|m_i-c_i|\n",
140 | "$$"
141 | ]
142 | },
143 | {
144 | "cell_type": "code",
145 | "execution_count": null,
146 | "metadata": {},
147 | "outputs": [],
148 | "source": [
149 | "%%time\n",
150 | "# parameters\n",
151 | "n = 1024 # number of points c\n",
152 | "sb = 4 # space between slices\n",
153 | "BG = (0, 0, 0) # background color\n",
154 | "\n",
155 | "# init\n",
156 | "img = image.open('../_data/aerial01.png')\n",
157 | "imx = img.size[0]\n",
158 | "imy = img.size[1]\n",
159 | "imgIn = image.new('RGB', img.size)\n",
160 | "imgIn.paste(img)\n",
161 | "imgOut = image.new('RGB', img.size, BG)\n",
162 | "\n",
163 | "# execution\n",
164 | "cx = np.random.randint(0, imx, n)\n",
165 | "cy = np.random.randint(0, imy, n)\n",
166 | "pop = np.array([cx, cy]).T\n",
167 | "\n",
168 | "for y in range(imy):\n",
169 | " for x in range(imx):\n",
170 | " d = abs((x, y) - pop).max(axis=1)\n",
171 | " NP = pop[np.argmin(d)]\n",
172 | " cd = imgIn.getpixel((int(NP[0]), int(NP[1])))\n",
173 | " imgOut.putpixel((x, y), cd)\n",
174 | "\n",
175 | "output = np.array([np.asarray(imgIn),\n",
176 | " np.asarray(imgOut)])\n",
177 | "panel(output, (2, 1))"
178 | ]
179 | },
180 | {
181 | "cell_type": "markdown",
182 | "metadata": {},
183 | "source": [
184 | "## Minkowski\n",
185 | "---\n",
186 | "Diagram defined by [minkowski distance](https://en.wikipedia.org/wiki/Minkowski_distance) which term is the $L_p$ norm and generalizes all other using the *minkowski's parameter* $p$:\n",
187 | "$$ \\displaystyle \\large\n",
188 | "d(m,c) \\mapsto \\|m-c\\|_p = \\left(\\sum_{i}^{n}|m_i-c_i|^p\\right)^\\frac{1}{p}\n",
189 | "$$"
190 | ]
191 | },
192 | {
193 | "cell_type": "code",
194 | "execution_count": null,
195 | "metadata": {},
196 | "outputs": [],
197 | "source": [
198 | "%%time\n",
199 | "# parameters\n",
200 | "n = 512 # number of points c\n",
201 | "sb = 4 # space between slices\n",
202 | "p = 0.5 # minkowski's parameter\n",
203 | "BG = (0, 0, 0) # background color\n",
204 | "\n",
205 | "# init\n",
206 | "img = image.open('../_data/babuino.png')\n",
207 | "imx = img.size[0]\n",
208 | "imy = img.size[1]\n",
209 | "imgIn = image.new('RGB', img.size)\n",
210 | "imgIn.paste(img)\n",
211 | "imgOut = image.new('RGB', img.size, BG)\n",
212 | "\n",
213 | "# execution\n",
214 | "cx = np.random.randint(0, imx, n)\n",
215 | "cy = np.random.randint(0, imy, n)\n",
216 | "pop = np.array([cx, cy]).T\n",
217 | "\n",
218 | "for y in range(imy):\n",
219 | " for x in range(imx):\n",
220 | " d = np.sum(abs((x, y) - pop)**p, axis=1)**(1/p)\n",
221 | " NP = pop[np.argmin(d)]\n",
222 | " cd = imgIn.getpixel((int(NP[0]), int(NP[1])))\n",
223 | " imgOut.putpixel((x, y), cd)\n",
224 | "\n",
225 | "output = np.array([np.asarray(imgIn),\n",
226 | " np.asarray(imgOut)])\n",
227 | "panel(output, (2, 1))"
228 | ]
229 | }
230 | ],
231 | "metadata": {
232 | "kernelspec": {
233 | "display_name": "Python 3",
234 | "language": "python",
235 | "name": "python3"
236 | },
237 | "language_info": {
238 | "codemirror_mode": {
239 | "name": "ipython",
240 | "version": 3
241 | },
242 | "file_extension": ".py",
243 | "mimetype": "text/x-python",
244 | "name": "python",
245 | "nbconvert_exporter": "python",
246 | "pygments_lexer": "ipython3",
247 | "version": "3.7.7"
248 | }
249 | },
250 | "nbformat": 4,
251 | "nbformat_minor": 2
252 | }
253 |
--------------------------------------------------------------------------------
/Generative/svg-quadtree.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Quadtree\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [svg-quadtree.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Generative/svg-quadtree.ipynb)\n",
12 | "---\n",
13 | "2D image partition using quadtrees and SVG graphics."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib as mpl\n",
24 | "import matplotlib.pyplot as plt\n",
25 | "import numpy as np\n",
26 | "import imageio"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {},
32 | "source": [
33 | "## Useful functions\n",
34 | "---"
35 | ]
36 | },
37 | {
38 | "cell_type": "code",
39 | "execution_count": null,
40 | "metadata": {},
41 | "outputs": [],
42 | "source": [
43 | "def display_svg(data):\n",
44 | " # Display SVG\n",
45 | " from IPython.display import SVG, display\n",
46 | " display(SVG(data))"
47 | ]
48 | },
49 | {
50 | "cell_type": "markdown",
51 | "metadata": {},
52 | "source": [
53 | "## Quadtree algorithm\n",
54 | "---"
55 | ]
56 | },
57 | {
58 | "cell_type": "code",
59 | "execution_count": null,
60 | "metadata": {},
61 | "outputs": [],
62 | "source": [
63 | "class Node():\n",
64 | " def __init__(self, x, y, dx, dy, mu, std):\n",
65 | " self.x = x\n",
66 | " self.y = y\n",
67 | " self.dx = dx\n",
68 | " self.dy = dy\n",
69 | " self.mu = mu\n",
70 | " self.std = std\n",
71 | " self.children = []"
72 | ]
73 | },
74 | {
75 | "cell_type": "code",
76 | "execution_count": null,
77 | "metadata": {},
78 | "outputs": [],
79 | "source": [
80 | "class QTree():\n",
81 | " def __init__(self, IMG):\n",
82 | " dy, dx, c = IMG.shape\n",
83 | " mu = np.median(IMG.reshape(-1, 3), axis=0).astype(int)\n",
84 | " std = np.std(IMG)\n",
85 | " self.root = Node(0, 0, dx, dy, mu, std)\n",
86 | " self.IMG = IMG\n",
87 | "\n",
88 | " def subdivide(self, d_max, k_std):\n",
89 | " recursive_subdivide(self.root, self.IMG, d_max, k_std)\n",
90 | "\n",
91 | " def get_leaves(self):\n",
92 | " return find_leaves(self.root)"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "metadata": {},
98 | "source": [
99 | "### Support functions\n",
100 | "---"
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "execution_count": null,
106 | "metadata": {},
107 | "outputs": [],
108 | "source": [
109 | "def divided_node(IMG, x, y, dx, dy):\n",
110 | " # Build divided node\n",
111 | " img_ = IMG[y:y+dy, x:x+dx]\n",
112 | " mu_ = np.median(img_.reshape(-1, 3), axis=0).astype(int)\n",
113 | " std_ = np.std(img_)\n",
114 | " return Node(x, y, dx, dy, mu_, std_)\n",
115 | "\n",
116 | "def recursive_subdivide(node, IMG, d_max, std_max):\n",
117 | " # Subdivide node by 4 if condition is satisfied\n",
118 | " x, y = node.x, node.y\n",
119 | " dx, dy = node.dx, node.dy\n",
120 | " mu, std = node.mu, node.std\n",
121 | "\n",
122 | " if (\n",
123 | " dx < d_max or\n",
124 | " std < std_max\n",
125 | " ): return\n",
126 | "\n",
127 | " # Node 1\n",
128 | " x_, y_ = x, y\n",
129 | " dx_, dy_ = dx//2, dy//2\n",
130 | " n1 = divided_node(IMG, x_, y_, dx_, dy_)\n",
131 | " recursive_subdivide(n1, IMG, d_max, std_max)\n",
132 | "\n",
133 | " # Node 2\n",
134 | " x_, y_ = x + dx//2, y\n",
135 | " dx_, dy_ = dx//2, dy//2\n",
136 | " n2 = divided_node(IMG, x_, y_, dx_, dy_)\n",
137 | " recursive_subdivide(n2, IMG, d_max, std_max)\n",
138 | "\n",
139 | " # Node 3\n",
140 | " x_, y_ = x, y + dy//2\n",
141 | " dx_, dy_ = dx//2, dy//2\n",
142 | " n3 = divided_node(IMG, x_, y_, dx_, dy_)\n",
143 | " recursive_subdivide(n3, IMG, d_max, std_max)\n",
144 | "\n",
145 | " # Node 4\n",
146 | " x_, y_ = x + dx//2, y + dy//2\n",
147 | " dx_, dy_ = dx//2, dy//2\n",
148 | " n4 = divided_node(IMG, x_, y_, dx_, dy_)\n",
149 | " recursive_subdivide(n4, IMG, d_max, std_max)\n",
150 | "\n",
151 | " node.children = [n1, n2, n3, n4]\n",
152 | "\n",
153 | "def find_leaves(node):\n",
154 | " # Find all leaves on the tree\n",
155 | " if not node.children:\n",
156 | " return [node]\n",
157 | " leaves = []\n",
158 | " for leaf in node.children:\n",
159 | " leaves += find_leaves(leaf)\n",
160 | " return leaves"
161 | ]
162 | },
163 | {
164 | "cell_type": "markdown",
165 | "metadata": {},
166 | "source": [
167 | "## Image partition to SVG\n",
168 | "---"
169 | ]
170 | },
171 | {
172 | "cell_type": "code",
173 | "execution_count": null,
174 | "metadata": {},
175 | "outputs": [],
176 | "source": [
177 | "# Input image\n",
178 | "IMG = imageio.imread('../_data/woman01.png')\n",
179 | "dy, dx, c = IMG.shape\n",
180 | "plt.imshow(IMG)\n",
181 | "plt.show()"
182 | ]
183 | },
184 | {
185 | "cell_type": "code",
186 | "execution_count": null,
187 | "metadata": {},
188 | "outputs": [],
189 | "source": [
190 | "# Init SVG\n",
191 | "SVG = f'''\n",
192 | "\n",
195 | "\\n'\n",
221 | "\n",
222 | "display_svg(SVG)"
223 | ]
224 | }
225 | ],
226 | "metadata": {
227 | "kernelspec": {
228 | "display_name": "Python 3",
229 | "language": "python",
230 | "name": "python3"
231 | },
232 | "language_info": {
233 | "codemirror_mode": {
234 | "name": "ipython",
235 | "version": 3
236 | },
237 | "file_extension": ".py",
238 | "mimetype": "text/x-python",
239 | "name": "python",
240 | "nbconvert_exporter": "python",
241 | "pygments_lexer": "ipython3",
242 | "version": "3.7.4"
243 | }
244 | },
245 | "nbformat": 4,
246 | "nbformat_minor": 2
247 | }
248 |
--------------------------------------------------------------------------------
/Generative/wall-of-letters.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "atlantic-typing",
6 | "metadata": {},
7 | "source": [
8 | "# Wall of Letters\n",
9 | "---\n",
10 | "- Author: Diego Inácio\n",
11 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
12 | "- Notebook: [wall-of-letters.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Generative/wall-of-letters.ipynb)\n",
13 | "---\n",
14 | "A responsive experiment with character styling and layout."
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "id": "treated-prize",
21 | "metadata": {},
22 | "outputs": [],
23 | "source": [
24 | "from IPython.display import HTML, display\n",
25 | "import random"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "id": "informative-technician",
31 | "metadata": {},
32 | "source": [
33 | "The purpose of this experiment is to reproduce nice visuals of text blocks, imitating bricks on the wall. The main idea is to use css style layout for the blocks and make them responsive by displaying the generated HTML. To make the process less verbose, *Python* will be used as the script language to produce the HTML code."
34 | ]
35 | },
36 | {
37 | "cell_type": "markdown",
38 | "id": "received-booth",
39 | "metadata": {},
40 | "source": [
41 | "## Set of letters\n",
42 | "---\n",
43 | "For this project, it will be used the following set of characters:\n",
44 | "\n",
45 | "- **Uppercase**: _ABCDEFGHIJKLMNOPQRSTUVWXYZ_\n",
46 | "- **Lowercase**: _abcdefghijklmnopqrstuvwxyz_\n",
47 | "- **Symbols**: _!#$%&*?@^~_\n",
48 | "- **Numbers**: _0123456789_\n",
49 | "\n",
50 | "This set will be used to generate random chacteres fot the blocks."
51 | ]
52 | },
53 | {
54 | "cell_type": "code",
55 | "execution_count": null,
56 | "id": "catholic-jurisdiction",
57 | "metadata": {},
58 | "outputs": [],
59 | "source": [
60 | "# Init set of characters\n",
61 | "SET = \"\"\n",
62 | "\n",
63 | "# Include uppercase\n",
64 | "SET += \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n",
65 | "# Include lowercase\n",
66 | "SET += \"abcdefghijklmnopqrstuvwxyz\"\n",
67 | "# Include symbols\n",
68 | "SET += \"!#$%&*?@^~\"\n",
69 | "# Include numbers\n",
70 | "SET += \"0123456789\"\n",
71 | "\n",
72 | "SET = list(SET)"
73 | ]
74 | },
75 | {
76 | "cell_type": "markdown",
77 | "id": "governing-tradition",
78 | "metadata": {},
79 | "source": [
80 | "## Useful functions\n",
81 | "---\n",
82 | "Here will be declared some useful functions to make it easier to generate the HTML code."
83 | ]
84 | },
85 | {
86 | "cell_type": "code",
87 | "execution_count": null,
88 | "id": "amateur-disaster",
89 | "metadata": {},
90 | "outputs": [],
91 | "source": [
92 | "def containerClass(count):\n",
93 | " \"\"\"\n",
94 | " Generate the text-container class\n",
95 | " \"\"\"\n",
96 | " return f'''\n",
97 | " .text-container {{\n",
98 | " -webkit-column-count: {count};\n",
99 | " -moz-column-count: {count};\n",
100 | " column-count: {count};\n",
101 | " }}\n",
102 | " '''\n",
103 | "\n",
104 | "def mediaQuery(maxWidth, content):\n",
105 | " \"\"\"\n",
106 | " Generate the media query for responsive design\n",
107 | " \"\"\"\n",
108 | " return f'''\n",
109 | " @media screen and (max-width: {maxWidth}px) {{{content}}}\n",
110 | " '''"
111 | ]
112 | },
113 | {
114 | "cell_type": "markdown",
115 | "id": "tropical-strengthening",
116 | "metadata": {},
117 | "source": [
118 | "## Style code\n",
119 | "---\n",
120 | "Here it will be created the style part of the HTML. Two classes will be used to model the structure of the code.\n",
121 | "\n",
122 | "- **text-container**: It is the container div which parents the blocks and it is responsible for the layout and responsiveness\n",
123 | "- **text-block**: It is the div which has the group of letters\n",
124 | "\n",
125 | "As a result, the _style_ element will be created and aggregated to the output code."
126 | ]
127 | },
128 | {
129 | "cell_type": "code",
130 | "execution_count": null,
131 | "id": "understanding-silicon",
132 | "metadata": {},
133 | "outputs": [],
134 | "source": [
135 | "STYLE = f'''\n",
136 | "\n",
153 | "'''"
154 | ]
155 | },
156 | {
157 | "cell_type": "markdown",
158 | "id": "expected-python",
159 | "metadata": {},
160 | "source": [
161 | "## Container code\n",
162 | "---\n",
163 | "Here we are going to generate the container code. This div will contain all blocks with letter and each letter will be stylized randomly by chaging color, size or any other attributes that may make the visual a little bit more appealing. "
164 | ]
165 | },
166 | {
167 | "cell_type": "code",
168 | "execution_count": null,
169 | "id": "incoming-inspiration",
170 | "metadata": {},
171 | "outputs": [],
172 | "source": [
173 | "# Parameters\n",
174 | "N_BLOCKS = 64\n",
175 | "\n",
176 | "# Deterministic random function\n",
177 | "random.seed(1234)\n",
178 | "\n",
179 | "# Build blocks\n",
180 | "BLOCKS = \"\"\n",
181 | "for _ in range(64):\n",
182 | " BG_HUE = random.randint(0, 360)\n",
183 | " N_LETTERS = random.randint(100, 500)\n",
184 | " LETTERS = \"\"\n",
185 | " for _ in range(N_LETTERS):\n",
186 | " letter_index = random.randint(0, len(SET) - 1)\n",
187 | " letter_hue = BG_HUE + random.randint(-100, 100)\n",
188 | " letter_size = random.randint(5, 20)\n",
189 | " letter_style = f'color: hsl({letter_hue},50%,50%); font-size: {letter_size}px'\n",
190 | " LETTERS += f'{SET[letter_index]}'\n",
191 | " block_style = f'background-color: hsla({BG_HUE}, 50%, 50%, 0.05)'\n",
192 | " BLOCKS += f'{LETTERS}
'\n",
193 | "\n",
194 | "CONTAINER = f'{BLOCKS}
'\n",
195 | "\n",
196 | "OUTPUT = STYLE + CONTAINER"
197 | ]
198 | },
199 | {
200 | "cell_type": "markdown",
201 | "id": "printable-collar",
202 | "metadata": {},
203 | "source": [
204 | "## Output\n",
205 | "---\n",
206 | "Display the output HTML generated code."
207 | ]
208 | },
209 | {
210 | "cell_type": "code",
211 | "execution_count": null,
212 | "id": "tropical-stretch",
213 | "metadata": {},
214 | "outputs": [],
215 | "source": [
216 | "display(HTML(OUTPUT))"
217 | ]
218 | },
219 | {
220 | "cell_type": "markdown",
221 | "id": "intensive-initial",
222 | "metadata": {},
223 | "source": [
224 | "## Wall of Emojis\n",
225 | "---\n",
226 | "As a fun experiment, let's use emojis instead of letters and see how it looks like 😅\n",
227 | "\n",
228 | "Let's first declare the set of emojis.\n",
229 | "\n",
230 | "*p.s.: The list of emojis was get from the (getemoji)[https://getemoji.com/] website*"
231 | ]
232 | },
233 | {
234 | "cell_type": "code",
235 | "execution_count": null,
236 | "id": "innocent-heater",
237 | "metadata": {},
238 | "outputs": [],
239 | "source": [
240 | "SET = \"🧳🌂☂️🧵🧶👓🕶🥽🥼🦺👔👕👖🧣🧤🧥🧦👗👘🥻🩱🩲🩳👙👚👛\"\n",
241 | "SET += \"👜👝🎒👞👟🥾🥿👠👡🩰👢👑👒🎩🎓🧢😀😃😄😁😆😅😂🤣\"\n",
242 | "\n",
243 | "SET = list(SET)"
244 | ]
245 | },
246 | {
247 | "cell_type": "markdown",
248 | "id": "political-progress",
249 | "metadata": {},
250 | "source": [
251 | "Having the emoji set, let's execute the same piece of code but discarding the random color since emoji has its own color aspect."
252 | ]
253 | },
254 | {
255 | "cell_type": "code",
256 | "execution_count": null,
257 | "id": "greatest-module",
258 | "metadata": {},
259 | "outputs": [],
260 | "source": [
261 | "# Parameters\n",
262 | "N_BLOCKS = 64\n",
263 | "\n",
264 | "# Deterministic random function\n",
265 | "random.seed(1234)\n",
266 | "\n",
267 | "# Build blocks\n",
268 | "BLOCKS = \"\"\n",
269 | "for _ in range(64):\n",
270 | " BG_HUE = random.randint(0, 360)\n",
271 | " N_LETTERS = random.randint(50, 200)\n",
272 | " LETTERS = \"\"\n",
273 | " for _ in range(N_LETTERS):\n",
274 | " letter_index = random.randint(0, len(SET) - 1)\n",
275 | " letter_hue = BG_HUE + random.randint(-100, 100)\n",
276 | " letter_size = random.randint(10, 20)\n",
277 | " letter_style = f'font-size: {letter_size}px'\n",
278 | " LETTERS += f'{SET[letter_index]}'\n",
279 | " block_style = f'background-color: hsla({BG_HUE}, 50%, 50%, 0.1)'\n",
280 | " BLOCKS += f'{LETTERS}
'\n",
281 | "\n",
282 | "CONTAINER = f'{BLOCKS}
'\n",
283 | "\n",
284 | "OUTPUT = STYLE + CONTAINER"
285 | ]
286 | },
287 | {
288 | "cell_type": "markdown",
289 | "id": "mathematical-blood",
290 | "metadata": {},
291 | "source": [
292 | "Finally, let's display the result."
293 | ]
294 | },
295 | {
296 | "cell_type": "code",
297 | "execution_count": null,
298 | "id": "challenging-university",
299 | "metadata": {},
300 | "outputs": [],
301 | "source": [
302 | "display(HTML(OUTPUT))"
303 | ]
304 | }
305 | ],
306 | "metadata": {
307 | "kernelspec": {
308 | "display_name": "Python 3",
309 | "language": "python",
310 | "name": "python3"
311 | },
312 | "language_info": {
313 | "codemirror_mode": {
314 | "name": "ipython",
315 | "version": 3
316 | },
317 | "file_extension": ".py",
318 | "mimetype": "text/x-python",
319 | "name": "python",
320 | "nbconvert_exporter": "python",
321 | "pygments_lexer": "ipython3",
322 | "version": "3.7.10"
323 | }
324 | },
325 | "nbformat": 4,
326 | "nbformat_minor": 5
327 | }
328 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2020 Diego Inácio
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/ML-and-AI/README.md:
--------------------------------------------------------------------------------
1 | # M.L. + A.I.
2 |
3 | Experiments involving machine learning, artificial intelligence and so on.
4 |
--------------------------------------------------------------------------------
/ML-and-AI/image_approximation_deepNN.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Image Approximation\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [image_approximation_deepNN.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/ML-and-AI/image_approximation_deepNN.ipynb)\n",
12 | "---\n",
13 | "Image *approximation* and *upscaling interpolation* using deep *Neural Network*."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib\n",
24 | "import matplotlib.pyplot as plt\n",
25 | "import numpy as np\n",
26 | "from PIL import Image\n",
27 | "\n",
28 | "import tensorflow as tf"
29 | ]
30 | },
31 | {
32 | "cell_type": "code",
33 | "execution_count": null,
34 | "metadata": {},
35 | "outputs": [],
36 | "source": [
37 | "plt.rcParams['figure.figsize'] = (16, 8)"
38 | ]
39 | },
40 | {
41 | "cell_type": "markdown",
42 | "metadata": {},
43 | "source": [
44 | "## Data exploration\n",
45 | "---"
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "execution_count": null,
51 | "metadata": {},
52 | "outputs": [],
53 | "source": [
54 | "n1, n2 = 128, 128\n",
55 | "# Read Image\n",
56 | "x = Image.open('../_data/woman01.png')\n",
57 | "# Rescale image to a lower resolution\n",
58 | "x = x.resize((n1, n2), Image.ANTIALIAS)\n",
59 | "x = np.asarray(x)/255\n",
60 | "n1, n2, c = x.shape\n",
61 | "\n",
62 | "### split channels ###\n",
63 | "r, g, b = x[:,:,0], x[:,:,1], x[:,:,2]"
64 | ]
65 | },
66 | {
67 | "cell_type": "code",
68 | "execution_count": null,
69 | "metadata": {},
70 | "outputs": [],
71 | "source": [
72 | "# Transform data and produce X_train\n",
73 | "Y_train = np.array([r.ravel(), g.ravel(), b.ravel()]).T\n",
74 | "t, s = np.mgrid[0:n1, 0:n2]\n",
75 | "s = (s - s.mean())/s.std()\n",
76 | "t = (t - t.mean())/t.std()\n",
77 | "# X_train is the normalized spatial coordinates\n",
78 | "X_train = np.array([s.ravel(), t.ravel()], dtype=np.float32).T"
79 | ]
80 | },
81 | {
82 | "cell_type": "code",
83 | "execution_count": null,
84 | "metadata": {},
85 | "outputs": [],
86 | "source": [
87 | "fig, [axA, axB] = plt.subplots(1, 2, figsize=(20, 10))\n",
88 | "\n",
89 | "st = np.stack([s, t, s*0], axis=2)\n",
90 | "st = (st - st.min())/(st.max() - st.min())\n",
91 | "st[:,:,2] = 0; axA.imshow(st); axA.axis('off')\n",
92 | "axA.text(5, 10, f'({s.min():.3f}, {t.min():.3f})', color='white', size=18)\n",
93 | "axA.text(86, 10, f'({s.max():.3f}, {t.min():.3f})', color='white', size=18)\n",
94 | "axA.text(5, 120, f'({s.min():.3f}, {t.max():.3f})', color='white', size=18)\n",
95 | "axA.text(86, 120, f'({s.max():.3f}, {t.max():.3f})', color='white', size=18)\n",
96 | "axA.set_title(f'$X_{{train}}$ ({n1} x {n2})', size=20)\n",
97 | "\n",
98 | "axB.imshow(x)\n",
99 | "axB.set_title(f'$Y_{{train}}$ ({n1} x {n2})', size=20)\n",
100 | "\n",
101 | "plt.show()"
102 | ]
103 | },
104 | {
105 | "cell_type": "code",
106 | "execution_count": null,
107 | "metadata": {},
108 | "outputs": [],
109 | "source": [
110 | "# Produce X_test to another scale\n",
111 | "# Upscale the image approximation\n",
112 | "N1 = N2 = 512\n",
113 | "t, s = np.mgrid[0:N1, 0:N2]\n",
114 | "s = (s - s.mean())/s.std()\n",
115 | "t = (t - t.mean())/t.std()\n",
116 | "X_test = np.array([s.ravel(), t.ravel()], dtype=np.float32).T\n",
117 | "\n",
118 | "print('X_train:', X_train.shape)\n",
119 | "print('Y_train:', Y_train.shape)\n",
120 | "print('X_test:', X_test.shape)"
121 | ]
122 | },
123 | {
124 | "cell_type": "markdown",
125 | "metadata": {},
126 | "source": [
127 | "## Deep Neural Network\n",
128 | "---"
129 | ]
130 | },
131 | {
132 | "cell_type": "code",
133 | "execution_count": null,
134 | "metadata": {},
135 | "outputs": [],
136 | "source": [
137 | "# Avoid error: \"InternalError: Blas GEMM launch failed...\" (RTX card)\n",
138 | "physical_devices = tf.config.experimental.list_physical_devices('GPU')\n",
139 | "tf.config.experimental.set_memory_growth(physical_devices[0], True)"
140 | ]
141 | },
142 | {
143 | "cell_type": "code",
144 | "execution_count": null,
145 | "metadata": {},
146 | "outputs": [],
147 | "source": [
148 | "# List of number of neurons for each hidden layer\n",
149 | "NEURONS = [2**i for i in range(5, 11)]\n",
150 | "\n",
151 | "# model \n",
152 | "# Input (2): x and y coordinates\n",
153 | "# Output (3): RGB\n",
154 | "model = tf.keras.Sequential([\n",
155 | " tf.keras.layers.Input(2),\n",
156 | " *[tf.keras.layers.Dense(n, activation='relu') for n in NEURONS],\n",
157 | " tf.keras.layers.Dense(3, activation='sigmoid')\n",
158 | "])\n",
159 | "\n",
160 | "model.summary()"
161 | ]
162 | },
163 | {
164 | "cell_type": "code",
165 | "execution_count": null,
166 | "metadata": {},
167 | "outputs": [],
168 | "source": [
169 | "model.compile(\n",
170 | " loss='mean_squared_error',\n",
171 | " optimizer='adam',\n",
172 | " metrics=['accuracy']\n",
173 | ")\n",
174 | "\n",
175 | "# Train model\n",
176 | "for i in range(5):\n",
177 | " print(f'\\nepochs: {i*100:04d} - {(i + 1)*100:04d}')\n",
178 | " model.fit(\n",
179 | " X_train, Y_train,\n",
180 | " epochs=99,\n",
181 | " verbose=0\n",
182 | " )\n",
183 | " model.fit(\n",
184 | " X_train, Y_train,\n",
185 | " epochs=1\n",
186 | " )"
187 | ]
188 | },
189 | {
190 | "cell_type": "code",
191 | "execution_count": null,
192 | "metadata": {},
193 | "outputs": [],
194 | "source": [
195 | "fig, [axA, axB] = plt.subplots(1, 2, figsize=(20, 10))\n",
196 | "\n",
197 | "axA.imshow(x)\n",
198 | "axA.set_title(f'$Y_{{train}}$ ({n1} x {n2})', size=20)\n",
199 | "# Predict using X_train (128x128x3)\n",
200 | "Y_predA = model.predict(X_train)\n",
201 | "Y_predA = Y_predA.reshape(n1, n2, c)\n",
202 | "axB.imshow(Y_predA)\n",
203 | "axB.set_title(f'$\\hat{{Y}}_{{train}}$ ({n1} x {n2})', size=20)\n",
204 | "\n",
205 | "plt.show()"
206 | ]
207 | },
208 | {
209 | "cell_type": "code",
210 | "execution_count": null,
211 | "metadata": {},
212 | "outputs": [],
213 | "source": [
214 | "fig, axA = plt.subplots(1, 1, figsize=(20, 20))\n",
215 | "\n",
216 | "# Predict using X_test (512x512x3)\n",
217 | "Y_predB = model.predict(X_test)\n",
218 | "Y_predB = Y_predB.reshape(N1, N2, c)\n",
219 | "axA.imshow(Y_predB)\n",
220 | "axA.set_title(f'$\\hat{{Y}}_{{test}}$ ({N1} x {N2})', size=20)\n",
221 | "\n",
222 | "plt.show()"
223 | ]
224 | },
225 | {
226 | "cell_type": "markdown",
227 | "metadata": {},
228 | "source": [
229 | "## Learning process visualization\n",
230 | "---"
231 | ]
232 | },
233 | {
234 | "cell_type": "code",
235 | "execution_count": null,
236 | "metadata": {},
237 | "outputs": [],
238 | "source": [
239 | "from IPython.display import HTML\n",
240 | "\n",
241 | "HTML(\n",
242 | " ''\n",
243 | ")"
244 | ]
245 | }
246 | ],
247 | "metadata": {
248 | "kernelspec": {
249 | "display_name": "Python [conda env:tfgpu]",
250 | "language": "python",
251 | "name": "conda-env-tfgpu-py"
252 | },
253 | "language_info": {
254 | "codemirror_mode": {
255 | "name": "ipython",
256 | "version": 3
257 | },
258 | "file_extension": ".py",
259 | "mimetype": "text/x-python",
260 | "name": "python",
261 | "nbconvert_exporter": "python",
262 | "pygments_lexer": "ipython3",
263 | "version": "3.7.7"
264 | }
265 | },
266 | "nbformat": 4,
267 | "nbformat_minor": 2
268 | }
269 |
--------------------------------------------------------------------------------
/ML-and-AI/pixel-art-depixelization-deepNN.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Depixelizing Pixel Art using Deep Neural Networks\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [pixel-art-depixelization-deepNN.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/ML-and-AI/pixel-art-depixelization-deepNN.ipynb)\n",
12 | "---\n",
13 | "A pretty naive approach that *upscales* and *depixelizes* a very low-res pixel art using deep *Neural Network*.\n",
14 | "\n",
15 | "The main idea is given the 2D coordinate inputs, get the relative pixel color as the output. To avoid the color interpolation and *blurry* results, store the original color pallete and transpose it using the concept of *one-hot* encodation."
16 | ]
17 | },
18 | {
19 | "cell_type": "code",
20 | "execution_count": null,
21 | "metadata": {},
22 | "outputs": [],
23 | "source": [
24 | "%matplotlib inline\n",
25 | "import matplotlib\n",
26 | "import matplotlib.pyplot as plt\n",
27 | "import numpy as np\n",
28 | "from PIL import Image\n",
29 | "\n",
30 | "import tensorflow as tf"
31 | ]
32 | },
33 | {
34 | "cell_type": "code",
35 | "execution_count": null,
36 | "metadata": {},
37 | "outputs": [],
38 | "source": [
39 | "plt.rcParams['figure.figsize'] = (20, 10)"
40 | ]
41 | },
42 | {
43 | "cell_type": "markdown",
44 | "metadata": {},
45 | "source": [
46 | "## Data exploration\n",
47 | "---\n",
48 | "Read a very low-res pixel art image (preferably 8bits to avoid a very large color pallete)."
49 | ]
50 | },
51 | {
52 | "cell_type": "code",
53 | "execution_count": null,
54 | "metadata": {},
55 | "outputs": [],
56 | "source": [
57 | "### Read input image ###\n",
58 | "img_in = Image.open('../_data/pixel-art-mario.png')\n",
59 | "img_in = np.asarray(img_in)/255\n",
60 | "n1, n2, c = img_in.shape\n",
61 | "\n",
62 | "### Split channels ###\n",
63 | "R, G, B = img_in[:,:,0], img_in[:,:,1], img_in[:,:,2]\n",
64 | "\n",
65 | "### Get color pallete ###\n",
66 | "color_pallete = np.unique(\n",
67 | " np.array([R.ravel(), G.ravel(), B.ravel()]).T,\n",
68 | " axis=0\n",
69 | ")\n",
70 | "color_pallete = color_pallete[color_pallete.sum(axis=1).argsort()]\n",
71 | "\n",
72 | "### Coordiantes ###\n",
73 | "T, S = np.mgrid[0:n1, 0:n2]\n",
74 | "# Standardize coordinates\n",
75 | "S = (S - S.mean())/S.std()\n",
76 | "T = (T - T.mean())/T.std()"
77 | ]
78 | },
79 | {
80 | "cell_type": "code",
81 | "execution_count": null,
82 | "metadata": {},
83 | "outputs": [],
84 | "source": [
85 | "# Visualize data\n",
86 | "fig, [axA, axB] = plt.subplots(1, 2)\n",
87 | "\n",
88 | "ST = np.stack([S, T, S*0], axis=2)\n",
89 | "ST = (ST - ST.min())/(ST.max() - ST.min())\n",
90 | "ST[:,:,2] = 0\n",
91 | "axA.imshow(ST); axA.axis('off')\n",
92 | "axA.set_title('X Train')\n",
93 | "axA.text(1, 3, f'({S.min():.3f}, {T.min():.3f})', color='w', size=20)\n",
94 | "axA.text(21, 3, f'({S.max():.3f}, {T.min():.3f})', color='w', size=20)\n",
95 | "axA.text(1, 29, f'({S.min():.3f}, {T.max():.3f})', color='w', size=20)\n",
96 | "axA.text(21, 29, f'({S.max():.3f}, {T.max():.3f})', color='w', size=20)\n",
97 | "\n",
98 | "axB.imshow(img_in)\n",
99 | "axB.set_title('Input image')\n",
100 | "\n",
101 | "# Color pallete\n",
102 | "fig, ax = plt.subplots(1, 1)\n",
103 | "\n",
104 | "ax.imshow(color_pallete[:, np.newaxis, :].reshape((1, -1, 3)))\n",
105 | "ax.set_title('Color Pallete'); ax.axis('off')\n",
106 | "\n",
107 | "plt.show()"
108 | ]
109 | },
110 | {
111 | "cell_type": "markdown",
112 | "metadata": {},
113 | "source": [
114 | "## Data preparation\n",
115 | "---"
116 | ]
117 | },
118 | {
119 | "cell_type": "code",
120 | "execution_count": null,
121 | "metadata": {},
122 | "outputs": [],
123 | "source": [
124 | "# Train data\n",
125 | "X_train = np.array([S.ravel(), T.ravel()]).T\n",
126 | "\n",
127 | "Y_train = np.array([R.ravel(), G.ravel(), B.ravel()]).T\n",
128 | "Y_train_pallete = np.unique(Y_train, axis=0)\n",
129 | "Y_train_pallete = Y_train_pallete[Y_train_pallete.sum(axis=1).argsort()]\n",
130 | "# One-hot encoding based on the color pallete\n",
131 | "Y_train_oh = np.zeros((Y_train.shape[0], Y_train_pallete.shape[0]))\n",
132 | "n, m = Y_train_oh.shape\n",
133 | "for i in range(Y_train_oh.shape[0]):\n",
134 | " for j in range(Y_train_oh.shape[1]):\n",
135 | " Y_train_oh[i, j] = 1 if np.array_equal(Y_train[i], Y_train_pallete[j]) else 0"
136 | ]
137 | },
138 | {
139 | "cell_type": "code",
140 | "execution_count": null,
141 | "metadata": {},
142 | "outputs": [],
143 | "source": [
144 | "# Test data\n",
145 | "N1 = N2 = 640\n",
146 | "t, s = np.mgrid[0:N1, 0:N2]\n",
147 | "s = (s - s.mean())/s.std()\n",
148 | "t = (t - t.mean())/t.std()\n",
149 | "X_test = np.array([s.ravel(), t.ravel()], dtype=np.float32).T"
150 | ]
151 | },
152 | {
153 | "cell_type": "markdown",
154 | "metadata": {},
155 | "source": [
156 | "## Deep Neural Network\n",
157 | "---\n",
158 | "The archtecture of the *NeuralNet* is inspired by the concept of a *decoder* of an *autoencoder*. The output is an *one-hot* encoding of the *color pallete*, which is activated by a *softmax* function."
159 | ]
160 | },
161 | {
162 | "cell_type": "code",
163 | "execution_count": null,
164 | "metadata": {},
165 | "outputs": [],
166 | "source": [
167 | "# Avoid error: \"InternalError: Blas GEMM launch failed...\" (RTX card)\n",
168 | "physical_devices = tf.config.experimental.list_physical_devices('GPU')\n",
169 | "tf.config.experimental.set_memory_growth(physical_devices[0], True)"
170 | ]
171 | },
172 | {
173 | "cell_type": "code",
174 | "execution_count": null,
175 | "metadata": {},
176 | "outputs": [],
177 | "source": [
178 | "### Define NN model\n",
179 | "model = tf.keras.Sequential([\n",
180 | " tf.keras.layers.Input(2),\n",
181 | " tf.keras.layers.Dense(8, activation='relu'),\n",
182 | " tf.keras.layers.Dense(32, activation='relu'),\n",
183 | " tf.keras.layers.Dropout(0.125),\n",
184 | " tf.keras.layers.Dense(32, activation='relu'),\n",
185 | " tf.keras.layers.Dense(128, activation='relu'),\n",
186 | " tf.keras.layers.Dropout(0.125),\n",
187 | " tf.keras.layers.Dense(128, activation='relu'),\n",
188 | " tf.keras.layers.Dense(512, activation='relu'),\n",
189 | " tf.keras.layers.Dense(m, activation='softmax')\n",
190 | "])\n",
191 | "\n",
192 | "model.summary()"
193 | ]
194 | },
195 | {
196 | "cell_type": "code",
197 | "execution_count": null,
198 | "metadata": {},
199 | "outputs": [],
200 | "source": [
201 | "model.compile(\n",
202 | " loss='mean_squared_error',\n",
203 | " optimizer='adam',\n",
204 | " metrics=['accuracy']\n",
205 | ")\n",
206 | "\n",
207 | "# Train model\n",
208 | "epochs = 100\n",
209 | "for i in range(10):\n",
210 | " print(f'\\nepochs: {i*epochs:04d} - {(i + 1)*epochs:04d}')\n",
211 | " model.fit(\n",
212 | " X_train, Y_train_oh,\n",
213 | " epochs=epochs - 1,\n",
214 | " verbose=0\n",
215 | " )\n",
216 | " # Verbose\n",
217 | " model.fit(\n",
218 | " X_train, Y_train_oh,\n",
219 | " epochs=1\n",
220 | " )"
221 | ]
222 | },
223 | {
224 | "cell_type": "code",
225 | "execution_count": null,
226 | "metadata": {},
227 | "outputs": [],
228 | "source": [
229 | "fig, [axA, axB] = plt.subplots(1, 2)\n",
230 | "\n",
231 | "axA.imshow(img_in)\n",
232 | "axA.set_title(f'$Y_{{train}}$ ({n1} x {n2})', size=20)\n",
233 | "# Predict using X_train (32x32x3)\n",
234 | "Y_predA = model.predict(X_train)\n",
235 | "Y_predA = np.vstack(\n",
236 | " [Y_train_pallete[i] for i in np.argmax(Y_predA, axis=1)]\n",
237 | ")\n",
238 | "Y_predA = Y_predA.reshape(n1, n2, c)\n",
239 | "axB.imshow(Y_predA)\n",
240 | "axB.set_title(f'$\\hat{{Y}}_{{train}}$ ({n1} x {n2})', size=20)\n",
241 | "\n",
242 | "plt.show()"
243 | ]
244 | },
245 | {
246 | "cell_type": "code",
247 | "execution_count": null,
248 | "metadata": {},
249 | "outputs": [],
250 | "source": [
251 | "fig, axA = plt.subplots(1, 1, figsize=(20, 20))\n",
252 | "\n",
253 | "# Predict using X_test (512x512x3)\n",
254 | "Y_predB = model.predict(X_test)\n",
255 | "Y_predB = np.vstack(\n",
256 | " [Y_train_pallete[i] for i in np.argmax(Y_predB, axis=1)]\n",
257 | ")\n",
258 | "Y_predB = Y_predB.reshape(N1, N2, c)\n",
259 | "axA.imshow(Y_predB)\n",
260 | "axA.set_title(f'$\\hat{{Y}}_{{test}}$ ({N1} x {N2})', size=20)\n",
261 | "\n",
262 | "plt.show()"
263 | ]
264 | },
265 | {
266 | "cell_type": "markdown",
267 | "metadata": {},
268 | "source": [
269 | "## Learning process visualization\n",
270 | "---"
271 | ]
272 | },
273 | {
274 | "cell_type": "code",
275 | "execution_count": null,
276 | "metadata": {},
277 | "outputs": [],
278 | "source": [
279 | "from IPython.display import IFrame\n",
280 | "\n",
281 | "IFrame(\"https://www.youtube.com/embed/ROlbzTyWJDs\", width=\"960\", height=\"540\")"
282 | ]
283 | }
284 | ],
285 | "metadata": {
286 | "kernelspec": {
287 | "display_name": "Python [conda env:tfgpu]",
288 | "language": "python",
289 | "name": "conda-env-tfgpu-py"
290 | },
291 | "language_info": {
292 | "codemirror_mode": {
293 | "name": "ipython",
294 | "version": 3
295 | },
296 | "file_extension": ".py",
297 | "mimetype": "text/x-python",
298 | "name": "python",
299 | "nbconvert_exporter": "python",
300 | "pygments_lexer": "ipython3",
301 | "version": "3.7.7"
302 | }
303 | },
304 | "nbformat": 4,
305 | "nbformat_minor": 2
306 | }
307 |
--------------------------------------------------------------------------------
/ML-and-AI/text-generation_markov-chain.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Text Generation [Markov Chain]\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [text-generation_markov-chain.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/ML-and-AI/text-generation_markov-chain.ipynb)\n",
12 | "---\n",
13 | "Text generation with [*Markov Chain*](https://en.wikipedia.org/wiki/Markov_chain), using characters as base.\n",
14 | "\n",
15 | "A *Markov chain* is a sequence $x_1, x_2, x_3, ..., x_n$ of random variables - in our case, random characters. The distribution of the conditional probabilities of $x_{n+1}$ is a function of $x_n$, where:\n",
16 | "\n",
17 | "$$ \\large \\displaystyle \n",
18 | "\\Pr(X_{n+1}=x|X_{0},X_{1},X_{2},\\ldots ,X_{n})=\\Pr(X_{n+1}=x|X_{n})\n",
19 | "$$"
20 | ]
21 | },
22 | {
23 | "cell_type": "code",
24 | "execution_count": null,
25 | "metadata": {},
26 | "outputs": [],
27 | "source": [
28 | "# Scraping libraries\n",
29 | "import requests\n",
30 | "from bs4 import BeautifulSoup\n",
31 | "\n",
32 | "import numpy as np"
33 | ]
34 | },
35 | {
36 | "cell_type": "markdown",
37 | "metadata": {},
38 | "source": [
39 | "## Data Scraping\n",
40 | "---\n",
41 | "As data, we are going to use lyrics from one of my favorite hard rock band.. **Van Halen**. To get those lyrics, let's scrape this data in the website [AllTheLyrics](https://www.allthelyrics.com) and process them to build a text corpus."
42 | ]
43 | },
44 | {
45 | "cell_type": "code",
46 | "execution_count": null,
47 | "metadata": {},
48 | "outputs": [],
49 | "source": [
50 | "# Request and parse\n",
51 | "PAGE = \"https://www.allthelyrics.com\"\n",
52 | "URL = f'{PAGE}/lyrics/van_halen'\n",
53 | "request = requests.get(URL).text\n",
54 | "parse = BeautifulSoup(request, \"html.parser\")"
55 | ]
56 | },
57 | {
58 | "cell_type": "code",
59 | "execution_count": null,
60 | "metadata": {},
61 | "outputs": [],
62 | "source": [
63 | "%%time\n",
64 | "np.random.seed(1)\n",
65 | "# Define how many lyrics will be considered\n",
66 | "# p = 0.1 indicates that 10% will be read\n",
67 | "p = 0.2 # ! Parameter\n",
68 | "\n",
69 | "# Init text corpus\n",
70 | "TEXT = \"\"\n",
71 | "\n",
72 | "# Find all \n",
73 | "ITEM = parse.find_all(\"li\", {\"class\": \"lyrics-list-item\"})\n",
74 | "ITEM_alpha = np.random.choice([0, 1], len(ITEM), p=[1 - p, p])\n",
75 | "\n",
76 | "for i, item in enumerate(ITEM):\n",
77 | " link = item.find(\"a\")\n",
78 | " if not link or not ITEM_alpha[i]:\n",
79 | " continue\n",
80 | " url = f'{PAGE}{link[\"href\"]}'\n",
81 | " request_ = requests.get(url).text\n",
82 | " parse_ = BeautifulSoup(request_, \"html.parser\")\n",
83 | " TEXT += parse_.find(\"div\", {\"class\": \"content-text-inner\"}).text\n",
84 | " print(f'{100*i/len(ITEM):>06.02f} %', end=\"\\r\")\n",
85 | "TEXT = TEXT.replace(\"\\n\", \" \")\n",
86 | "print(f'{100:>06.02f} %')"
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "execution_count": null,
92 | "metadata": {},
93 | "outputs": [],
94 | "source": [
95 | "# Find all characters and symbols in the text\n",
96 | "SYMBOLS = sorted(set(TEXT))\n",
97 | "SYMBOLS_N = len(SYMBOLS)\n",
98 | "print(SYMBOLS)"
99 | ]
100 | },
101 | {
102 | "cell_type": "markdown",
103 | "metadata": {},
104 | "source": [
105 | "## Transition Matrix\n",
106 | "---\n",
107 | "[Transition](https://en.wikipedia.org/wiki/Markov_chain#Transitions) matrix contains all probilities for the next event, considering the current one. For example, considering the possibilities **A**, **B** and **C**:\n",
108 | "\n",
109 | "| | A | B | C |\n",
110 | "| :-: | :--: | :--: | :-: |\n",
111 | "| A | 0.1 | 0.6 | 0.3 |\n",
112 | "| B | 0.25 | 0.05 | 0.7 |\n",
113 | "| C | 0.7 | 0.3 | 0 |\n",
114 | "\n",
115 | "If the current state is **A**, the probability of getting **B** is *0.6*.\n",
116 | "\n",
117 | "In this case, the transition matrix has order 1. For nth-order matrices, we consider the last **n** states in sequence. For example, a 2nd-order matrix would be:\n",
118 | "\n",
119 | "| | A | B | C |\n",
120 | "| :-: | :--: | :--: | :-: |\n",
121 | "| AA | 0.1 | 0.6 | 0.3 |\n",
122 | "| AB | 0.25 | 0.05 | 0.7 |\n",
123 | "| : | ... | ... | ... |\n",
124 | "| CA | 0.7 | 0.3 | 0 |\n",
125 | "| : | ... | ... | ... |\n",
126 | "\n",
127 | "The higher the order, the more \"readable\" the generated text will be.\n",
128 | "\n",
129 | "To build our transion matrix we have basically to calculate the probability of the states, depending on the order we want to use."
130 | ]
131 | },
132 | {
133 | "cell_type": "code",
134 | "execution_count": null,
135 | "metadata": {},
136 | "outputs": [],
137 | "source": [
138 | "def order_sequences(TEXT, order):\n",
139 | " \"\"\"\n",
140 | " Return all character sequences with length equal to the order\n",
141 | " \"\"\"\n",
142 | " TEXT_N = len(TEXT)\n",
143 | " ORDERS = [TEXT[i:i + order] for i in range(TEXT_N - order)]\n",
144 | " return sorted(set(ORDERS))"
145 | ]
146 | },
147 | {
148 | "cell_type": "code",
149 | "execution_count": null,
150 | "metadata": {},
151 | "outputs": [],
152 | "source": [
153 | "def transition_matrix(TEXT, ORDERS, order):\n",
154 | " \"\"\"\n",
155 | " Build transition matrix\n",
156 | " \"\"\"\n",
157 | " ORDERS_N = len(ORDERS)\n",
158 | " P = np.ones([ORDERS_N, SYMBOLS_N])*1e-8\n",
159 | " for i, e1 in enumerate(TEXT[order:], order):\n",
160 | " i1 = SYMBOLS.index(e1)\n",
161 | " e2 = TEXT[i-order:i]\n",
162 | " i2 = ORDERS.index(e2)\n",
163 | " P[i2, i1] += 1\n",
164 | " P = P/P.sum(axis=1)[:,np.newaxis]\n",
165 | " return P"
166 | ]
167 | },
168 | {
169 | "cell_type": "markdown",
170 | "metadata": {},
171 | "source": [
172 | "## Text Generation\n",
173 | "---\n",
174 | "Having the transition matrix, we can start building the text generation procedure. The first step is to define the inital state and ganerate the following states by using the probabilities and choosing randomly."
175 | ]
176 | },
177 | {
178 | "cell_type": "code",
179 | "execution_count": null,
180 | "metadata": {},
181 | "outputs": [],
182 | "source": [
183 | "def text_generation(TEXT, order, lines):\n",
184 | " \"\"\"\n",
185 | " Generate text\n",
186 | " \"\"\"\n",
187 | " # Get transition matrix\n",
188 | " ORDERS = order_sequences(TEXT, order)\n",
189 | " P = transition_matrix(TEXT, ORDERS, order)\n",
190 | " # Count the occurences in the text, for each sequence\n",
191 | " # and define its probabilities\n",
192 | " ORDERS_count = np.array([TEXT.count(o) for o in ORDERS])\n",
193 | " ORDERS_p = ORDERS_count/ORDERS_count.sum()\n",
194 | " # Build text\n",
195 | " LINE = []\n",
196 | " for _ in range(lines):\n",
197 | " # Define initial chain of characters randomly\n",
198 | " line = np.random.choice(ORDERS, 1, p=ORDERS_p)[0]\n",
199 | " symbol = line[-1]\n",
200 | " line_s = np.random.randint(20, 50)\n",
201 | " while (len(line) < line_s) or (symbol not in [\" \", \",\", \".\", \"!\"]):\n",
202 | " p = P[0]*0 + 1\n",
203 | " index0 = ORDERS.index(line[-order:])\n",
204 | " p *= P[index0]\n",
205 | " index1 = np.random.choice(SYMBOLS_N, 1, p=p/p.sum())[0]\n",
206 | " symbol = SYMBOLS[index1]\n",
207 | " line += symbol\n",
208 | " LINE += [line]\n",
209 | " return \"\\n\".join(LINE)"
210 | ]
211 | },
212 | {
213 | "cell_type": "markdown",
214 | "metadata": {},
215 | "source": [
216 | "## Examples\n",
217 | "---\n",
218 | "In order to visualize the impact of the order in the transition matrix, let's generate texts with multiple nth-order matrices."
219 | ]
220 | },
221 | {
222 | "cell_type": "markdown",
223 | "metadata": {},
224 | "source": [
225 | "### 1st-order Matrix\n",
226 | "---\n",
227 | "In this case, we just consider the current character probabilities, which is likely to produce a weird text."
228 | ]
229 | },
230 | {
231 | "cell_type": "code",
232 | "execution_count": null,
233 | "metadata": {},
234 | "outputs": [],
235 | "source": [
236 | "np.random.seed(1)\n",
237 | "print(text_generation(TEXT, 1, 8), end=\"\\n\\n\")\n",
238 | "print(text_generation(TEXT, 1, 8))"
239 | ]
240 | },
241 | {
242 | "cell_type": "markdown",
243 | "metadata": {},
244 | "source": [
245 | "### 3rd-order Matrix\n",
246 | "---\n",
247 | "In this case, we consider the last 3 characters probabilities, which is likely to produce a more comprehensive words."
248 | ]
249 | },
250 | {
251 | "cell_type": "code",
252 | "execution_count": null,
253 | "metadata": {},
254 | "outputs": [],
255 | "source": [
256 | "np.random.seed(1)\n",
257 | "print(text_generation(TEXT, 3, 8), end=\"\\n\\n\")\n",
258 | "print(text_generation(TEXT, 3, 8))"
259 | ]
260 | },
261 | {
262 | "cell_type": "markdown",
263 | "metadata": {},
264 | "source": [
265 | "### 7th-order Matrix\n",
266 | "---\n",
267 | "In this case, we consider the last 7 characters probabilities, which is likely to produce a little more comprehensive sentences."
268 | ]
269 | },
270 | {
271 | "cell_type": "code",
272 | "execution_count": null,
273 | "metadata": {},
274 | "outputs": [],
275 | "source": [
276 | "np.random.seed(1)\n",
277 | "print(text_generation(TEXT, 7, 8), end=\"\\n\\n\")\n",
278 | "print(text_generation(TEXT, 7, 8))"
279 | ]
280 | }
281 | ],
282 | "metadata": {
283 | "kernelspec": {
284 | "display_name": "Python 3",
285 | "language": "python",
286 | "name": "python3"
287 | },
288 | "language_info": {
289 | "codemirror_mode": {
290 | "name": "ipython",
291 | "version": 3
292 | },
293 | "file_extension": ".py",
294 | "mimetype": "text/x-python",
295 | "name": "python",
296 | "nbconvert_exporter": "python",
297 | "pygments_lexer": "ipython3",
298 | "version": "3.7.10"
299 | }
300 | },
301 | "nbformat": 4,
302 | "nbformat_minor": 2
303 | }
304 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Creative Coding Notebooks
2 |
3 | [](https://diegoinacio.github.io/creative-coding-notebooks/)
4 |
5 | This is an `authorial set` of fundamental _Python recipes_ in notebook format. I started this project with the sole purpose of helping people to understand **Creative Coding** and **Computer Art** concepts as clearly and succinctly as I could.
6 |
7 | In addition, I also developed a bit more appealing way to publish these notebooks, in order to make the experience a little more pleasant and productive. You can check it by visiting the [cookbook page](https://diegoinacio.github.io/creative-coding-notebooks/).
8 |
9 | [](https://diegoinacio.github.io/creative-coding-notebooks/)
10 |
11 | You can join the [discussion](https://github.com/diegoinacio/creative-coding-notebooks/discussions) section to ask questions and suggest new ideas. And to follow what lies ahead, check out my [python notebook content](https://github.com/users/diegoinacio/projects/6) board.
12 |
13 | [](https://github.com/diegoinacio/creative-coding-notebooks/discussions)
14 |
15 | This project is _secretly_ part of the collection [Python Notebooks](https://diegoinacio.github.io/python-notebooks/), which is a gathering of cookbooks on **Computer Science**, **Data Science**, **Machine Learning**, **Computer Vision** and more.
16 |
17 | [](https://diegoinacio.github.io/python-notebooks/)
18 |
19 | If you feel that something here has helped you in somehow, please consider [supporting](https://ko-fi.com/diegoinacio/) this project:
20 |
21 | [](https://ko-fi.com/diegoinacio/)
22 |
23 | Created with ❤️ by [Diego Inácio](https://diegoinacio.github.io/)
24 |
--------------------------------------------------------------------------------
/Simulation/README.md:
--------------------------------------------------------------------------------
1 | # Simulation
2 |
3 | Physics, nonlinear system, dynamics, chaotic stuff, natural phenomena ..
4 |
--------------------------------------------------------------------------------
/Simulation/mandelbrot-set.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Mandelbrot Set\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [mandelbrot-set.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Simulation/mandelbrot-set.ipynb)\n",
12 | "---\n",
13 | "A very basic implementation of [mandelbrot set](https://en.wikipedia.org/wiki/Mandelbrot_set) algorithm with some performatic improvements using [Numba](https://numba.pydata.org/)."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib\n",
24 | "import matplotlib.pyplot as plt\n",
25 | "import numpy as np\n",
26 | "\n",
27 | "from numba import prange, vectorize, int64, float64"
28 | ]
29 | },
30 | {
31 | "cell_type": "markdown",
32 | "metadata": {},
33 | "source": [
34 | "Considering $z_0 = 0$ and the constant $c = x + iy$, we can calculate the *mandelbrot set* for each point as:\n",
35 | "\n",
36 | "$$ \\large\n",
37 | "\\begin{aligned}\n",
38 | "z_1 & = z_0^2 + c \\\\\n",
39 | " & = 0^2 + x + iy \\\\\n",
40 | " & = x + iy \\\\\n",
41 | "z_2 & = z_1^2 + c \\\\\n",
42 | " & = (x + iy)^2 + x + iy \\\\\n",
43 | " & = x^2 + i^2y^2 + i2xy + x + iy \\\\\n",
44 | " & = x^2 - y^2 + x + i(2xy + y) \\\\\n",
45 | "z_{n+1} & = z_n^2+c\n",
46 | "\\end{aligned} \n",
47 | "$$"
48 | ]
49 | },
50 | {
51 | "cell_type": "code",
52 | "execution_count": null,
53 | "metadata": {},
54 | "outputs": [],
55 | "source": [
56 | "@vectorize(\n",
57 | " [float64(float64, float64, int64)],\n",
58 | " target='parallel'\n",
59 | ")\n",
60 | "def mandelbrot(r, i, iters):\n",
61 | " c = complex(r, i)\n",
62 | " z = 0 + c\n",
63 | " for n in prange(iters):\n",
64 | " if z.real**2 + z.imag**2 > 4:\n",
65 | " return n\n",
66 | " z = z**2 + c\n",
67 | " return 0\n",
68 | "\n",
69 | "def mandelbrot_set(rmin, rmax, imin, imax, iters, size):\n",
70 | " # Build complex plane\n",
71 | " N = size if isinstance(size, complex) else 1j*size\n",
72 | " i, r = np.mgrid[imin:imax:N, rmin:rmax:N].astype(np.float64)\n",
73 | " # Calculate mandelbrot\n",
74 | " MB = mandelbrot(r, i, iters)\n",
75 | "\n",
76 | " return np.log10(MB + 1)"
77 | ]
78 | },
79 | {
80 | "cell_type": "code",
81 | "execution_count": null,
82 | "metadata": {},
83 | "outputs": [],
84 | "source": [
85 | "%%time\n",
86 | "N = 2048j\n",
87 | "rmin, imin, rmax, imax = -1.5, -1, 0.5, 1\n",
88 | "mbs = mandelbrot_set(\n",
89 | " rmin, rmax, imin, imax, 1024, N\n",
90 | ")\n",
91 | "\n",
92 | "fig, ax = plt.subplots(1, 1, figsize=(18, 18))\n",
93 | "plt.imshow(mbs, cmap=\"rainbow\")\n",
94 | "plt.xticks(\n",
95 | " np.linspace(0, N.imag, 20 + 1),\n",
96 | " [f'{e:.02f}' for e in np.linspace(rmin, rmax, 20 + 1)])\n",
97 | "plt.yticks(\n",
98 | " np.linspace(0, N.imag, 20 + 1),\n",
99 | " [f'{e:.02f}' for e in np.linspace(imin, imax, 20 + 1)])\n",
100 | "plt.show()"
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "execution_count": null,
106 | "metadata": {},
107 | "outputs": [],
108 | "source": [
109 | "fig, AX = plt.subplots(2, 2, figsize=(18, 18))\n",
110 | "\n",
111 | "center = np.array((-0.4505, 0.555))\n",
112 | "side = 0.001\n",
113 | "(rmin, imin), (rmax, imax) = center - side/2, center + side/2\n",
114 | "mbA = mandelbrot_set(rmin, rmax, imin, imax, 100000, 2048j)\n",
115 | "AX[0,0].imshow(mbA, cmap=\"prism\")\n",
116 | "AX[0,0].axis(\"off\")\n",
117 | "AX[0,0].set_title(\n",
118 | " f'Re[{rmin:.06f}, {rmax:.06f}] Im[{imin:.06f}, {imax:.06f}]',\n",
119 | " fontsize=15\n",
120 | ")\n",
121 | "\n",
122 | "center = np.array((-0.3, 0.625))\n",
123 | "side = 0.01\n",
124 | "(rmin, imin), (rmax, imax) = center - side/2, center + side/2\n",
125 | "mbB = mandelbrot_set(rmin, rmax, imin, imax, 100000, 2048j)\n",
126 | "AX[0,1].imshow(mbB**0.455, cmap=\"prism\")\n",
127 | "AX[0,1].axis(\"off\")\n",
128 | "AX[0,1].set_title(\n",
129 | " f'Re[{rmin:.06f}, {rmax:.06f}] Im[{imin:.06f}, {imax:.06f}]',\n",
130 | " fontsize=15\n",
131 | ")\n",
132 | "\n",
133 | "center = np.array((-0.4505, 0.555))\n",
134 | "side = 0.00001\n",
135 | "(rmin, imin), (rmax, imax) = center - side/2, center + side/2\n",
136 | "mbC = mandelbrot_set(rmin, rmax, imin, imax, 1000000, 2048j)\n",
137 | "AX[1,0].imshow(mbC, cmap=\"prism\")\n",
138 | "AX[1,0].axis(\"off\")\n",
139 | "AX[1,0].set_title(\n",
140 | " f'Re[{rmin:.06f}, {rmax:.06f}] Im[{imin:.06f}, {imax:.06f}]',\n",
141 | " fontsize=15\n",
142 | ")\n",
143 | "\n",
144 | "center = np.array((-0.3, 0.624))\n",
145 | "side = 0.0001\n",
146 | "(rmin, imin), (rmax, imax) = center - side/2, center + side/2\n",
147 | "mbD = mandelbrot_set(rmin, rmax, imin, imax, 1000000, 2048)\n",
148 | "AX[1,1].imshow(mbD, cmap=\"prism\")\n",
149 | "AX[1,1].axis(\"off\")\n",
150 | "AX[1,1].set_title(\n",
151 | " f'Re[{rmin:.06f}, {rmax:.06f}] Im[{imin:.06f}, {imax:.06f}]',\n",
152 | " fontsize=15\n",
153 | ")\n",
154 | "\n",
155 | "plt.tight_layout()\n",
156 | "plt.show()"
157 | ]
158 | }
159 | ],
160 | "metadata": {
161 | "kernelspec": {
162 | "display_name": "Python 3",
163 | "language": "python",
164 | "name": "python3"
165 | },
166 | "language_info": {
167 | "codemirror_mode": {
168 | "name": "ipython",
169 | "version": 3
170 | },
171 | "file_extension": ".py",
172 | "mimetype": "text/x-python",
173 | "name": "python",
174 | "nbconvert_exporter": "python",
175 | "pygments_lexer": "ipython3",
176 | "version": "3.7.7"
177 | }
178 | },
179 | "nbformat": 4,
180 | "nbformat_minor": 4
181 | }
182 |
--------------------------------------------------------------------------------
/Simulation/output/NLDC_cellularAutomaton1D_anim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Simulation/output/NLDC_cellularAutomaton1D_anim.gif
--------------------------------------------------------------------------------
/Simulation/output/NLDC_cellularAutomaton2D_anim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Simulation/output/NLDC_cellularAutomaton2D_anim.gif
--------------------------------------------------------------------------------
/Simulation/output/NLDC_cellularAutomaton2D_animA.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Simulation/output/NLDC_cellularAutomaton2D_animA.gif
--------------------------------------------------------------------------------
/Simulation/output/NLDC_cellularAutomaton2D_animB.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Simulation/output/NLDC_cellularAutomaton2D_animB.gif
--------------------------------------------------------------------------------
/Simulation/output/NLDC_cellularAutomaton2D_animC.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Simulation/output/NLDC_cellularAutomaton2D_animC.gif
--------------------------------------------------------------------------------
/Simulation/output/NLDC_reactionDiffusion.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Simulation/output/NLDC_reactionDiffusion.gif
--------------------------------------------------------------------------------
/Sound-Design/README.md:
--------------------------------------------------------------------------------
1 | # Sound Design
2 |
3 | Algorithmic composition, audio programming, sound effects, audio synthesis ..
4 |
--------------------------------------------------------------------------------
/Sound-Design/_utils.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import matplotlib.gridspec as gridspec
3 | import librosa
4 | import librosa.display
5 | import numpy as np
6 |
7 | def summary(x):
8 | if x.ndim == 1:
9 | SUM = ('\n{0:>10s}: {1:>15.4f}').format('min', np.amin(x))
10 | SUM += ('\n{0:>10s}: {1:>15.4f}').format('1st Quar', np.percentile(x, 25))
11 | SUM += ('\n{0:>10s}: {1:>15.4f}').format('median', np.median(x))
12 | SUM += ('\n{0:>10s}: {1:>15.4f}').format('mean', np.mean(x))
13 | SUM += ('\n{0:>10s}: {1:>15.4f}').format('3rd Quar', np.percentile(x, 75))
14 | SUM += ('\n{0:>10s}: {1:>15.4f}').format('max', np.amax(x))
15 | SUM += ('\n{0:>10s}: {1:>15.4f}').format('sigma', np.std(x))
16 | elif x.ndim == 2:
17 | E = x[:,0]
18 | D = x[:,1]
19 | SUM = ('{0:>%ss} {1:>%ss}' % (27, 15)).format('L', 'R')
20 | SUM += ('\n{0:>10s}: {1:>15.4f} {2:>15.4f}').format('min', np.amin(E), np.amin(D))
21 | SUM += ('\n{0:>10s}: {1:>15.4f} {2:>15.4f}').format('1st Quar', np.percentile(E, 25), np.percentile(D, 25))
22 | SUM += ('\n{0:>10s}: {1:>15.4f} {2:>15.4f}').format('median', np.median(E), np.median(D))
23 | SUM += ('\n{0:>10s}: {1:>15.4f} {2:>15.4f}').format('mean', np.mean(E), np.mean(D))
24 | SUM += ('\n{0:>10s}: {1:>15.4f} {2:>15.4f}').format('3rd Quar', np.percentile(E, 75), np.percentile(D, 75))
25 | SUM += ('\n{0:>10s}: {1:>15.4f} {2:>15.4f}').format('max', np.amax(E), np.amax(D))
26 | SUM += ('\n{0:>10s}: {1:>15.4f} {2:>15.4f}').format('sigma', np.std(E), np.std(D))
27 | else:
28 | raise ValueError('Invalid argument! It is not an audio..')
29 | print(SUM)
30 |
31 | def audiovis(x, fs=44100, **kwargs):
32 | dx, dy = (1536, 512) if 'dims' not in kwargs else kwargs['dims']
33 | dpi = 72 if 'dpi' not in kwargs else kwargs['dpi']
34 | text = '' if 'text' not in kwargs else kwargs['text']
35 |
36 | samples = x.shape[0]
37 | time = samples/fs
38 | if 'time' not in kwargs:
39 | to, ti = [0, time]
40 | else:
41 | to, ti = kwargs['time'][[0, -1]]
42 | tmin, tmax = (to, ti) if 'tlim' not in kwargs else kwargs['tlim']
43 | t = np.linspace(to, ti, samples)
44 |
45 | if x.ndim == 1:
46 | print('audio mono')
47 | fig = plt.figure(figsize=(dx/dpi, dy/dpi))
48 | plt.plot(t, x)
49 | plt.xlim([tmin, tmax])
50 | elif x.ndim == 2:
51 | print('audio stereo')
52 | fig = plt.figure(figsize=(dx/dpi, 2*dy/dpi))
53 | plt.subplot(2, 1, 1)
54 | plt.plot(t, x[:, 0], color='#00ff88')
55 | plt.xlim([tmin, tmax])
56 | plt.subplot(2, 1, 2)
57 | plt.plot(t, x[:, 1], color='#0088ff')
58 | plt.xlim([tmin, tmax])
59 | else:
60 | raise ValueError('Invalid argument! It is not an audio..')
61 | plt.title(text)
62 | plt.show()
63 |
64 | def spectrogram(x, fs=44100, **kwargs):
65 | dx, dy = (1536, 512) if 'dims' not in kwargs else kwargs['dims']
66 | dpi = 72 if 'dpi' not in kwargs else kwargs['dpi']
67 | fmin, fmax = [0, 8000] if 'flim' not in kwargs else kwargs['flim']
68 | text = '' if 'text' not in kwargs else kwargs['text']
69 |
70 | x = x.astype(np.float32)
71 |
72 | if x.ndim == 1:
73 | print('audio mono')
74 | fig = plt.figure(figsize=(dx/dpi, dy/dpi))
75 | X = np.abs(librosa.stft(x))
76 | X = librosa.amplitude_to_db(X, ref=np.max)
77 | librosa.display.specshow(X, sr=fs, y_axis='linear')
78 | plt.ylim([fmin, fmax])
79 | plt.colorbar(format='%+2.0f dB')
80 | elif x.ndim == 2:
81 | print('audio stereo')
82 | fig = plt.figure(figsize=(dx/dpi, 2*dy/dpi))
83 | plt.subplot(2, 1, 1)
84 | X = np.abs(librosa.stft(x[:, 0]))
85 | X = librosa.amplitude_to_db(X, ref=np.max)
86 | librosa.display.specshow(X, sr=fs, y_axis='linear')
87 | plt.ylim([fmin, fmax])
88 | plt.colorbar(format='%+2.0f dB')
89 | plt.subplot(2, 1, 2)
90 | X = np.abs(librosa.stft(x[:, 1]))
91 | X = librosa.amplitude_to_db(X, ref=np.max)
92 | librosa.display.specshow(X, sr=fs, y_axis='linear')
93 | plt.ylim([fmin, fmax])
94 | plt.colorbar(format='%+2.0f dB')
95 | else:
96 | raise ValueError('Invalid argument! It is not an audio..')
97 | plt.title(text)
98 | plt.show()
--------------------------------------------------------------------------------
/Sound-Design/musical-notes-physics.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# The physics of musical notes\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [musical-notes-physics.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Sound-Design/musical-notes-physics.ipynb)\n",
12 | "---\n",
13 | "A brief overview of how to calculate the frequency of notes and their wavelengths."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib.pyplot as plt\n",
24 | "from IPython.display import Audio\n",
25 | "import numpy as np\n",
26 | "import pandas as pd"
27 | ]
28 | },
29 | {
30 | "cell_type": "code",
31 | "execution_count": null,
32 | "metadata": {},
33 | "outputs": [],
34 | "source": [
35 | "plt.rcParams['figure.figsize'] = (16, 4)"
36 | ]
37 | },
38 | {
39 | "cell_type": "markdown",
40 | "metadata": {},
41 | "source": [
42 | "$$\n",
43 | "\\large f_n=f_0 \\times a^{n-49}\n",
44 | "$$\n",
45 | "\n",
46 | "where:\n",
47 | "- $f_{0}$ is the reference frequency for $A_4$, usually is 440 Hz;\n",
48 | "- $a$ is equivalent to $\\sqrt[12]{2}$ or $2^{\\frac{1}{12}}$;\n",
49 | "- $n$ denotes the note index."
50 | ]
51 | },
52 | {
53 | "cell_type": "code",
54 | "execution_count": null,
55 | "metadata": {},
56 | "outputs": [],
57 | "source": [
58 | "def frequencies(f0=440, no=9):\n",
59 | " '''\n",
60 | " Returns the frequency table for all note within the octaves 0-8\n",
61 | " no = number of octaves\n",
62 | " '''\n",
63 | " ne = 12\n",
64 | " a = 2**(1/ne)\n",
65 | " n = np.arange(no*ne).reshape((no, ne)).T - 8\n",
66 | " return f0*a**(n - 49)"
67 | ]
68 | },
69 | {
70 | "cell_type": "code",
71 | "execution_count": null,
72 | "metadata": {},
73 | "outputs": [],
74 | "source": [
75 | "def wavelengths(f, c=343):\n",
76 | " '''\n",
77 | " Returns the wavelength table in cm\n",
78 | " c is the speed of sound in air. Temperature 20°C\n",
79 | " '''\n",
80 | " return 100*c/f"
81 | ]
82 | },
83 | {
84 | "cell_type": "code",
85 | "execution_count": null,
86 | "metadata": {},
87 | "outputs": [],
88 | "source": [
89 | "fn = frequencies() # f in Hz\n",
90 | "wl = wavelengths(fn) # wavelenght in cm\n",
91 | "fw = np.vstack((fn, wl))\n",
92 | "fw = fw.reshape(\n",
93 | " (12, -1), order='F'\n",
94 | ")"
95 | ]
96 | },
97 | {
98 | "cell_type": "code",
99 | "execution_count": null,
100 | "metadata": {},
101 | "outputs": [],
102 | "source": [
103 | "octaves = [('Octave {0}'.format(o), e) for o in range(9) for e in [r'$f$', r'$\\lambda$']]\n",
104 | "scale = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']"
105 | ]
106 | },
107 | {
108 | "cell_type": "code",
109 | "execution_count": null,
110 | "metadata": {},
111 | "outputs": [],
112 | "source": [
113 | "notes = pd.DataFrame(fw, index=scale, columns=octaves)\n",
114 | "notes.columns = pd.MultiIndex.from_tuples(notes.columns, names=['Octave','Hz | cm'])\n",
115 | "notes.T.round(2)"
116 | ]
117 | }
118 | ],
119 | "metadata": {
120 | "kernelspec": {
121 | "display_name": "Python 3",
122 | "language": "python",
123 | "name": "python3"
124 | },
125 | "language_info": {
126 | "codemirror_mode": {
127 | "name": "ipython",
128 | "version": 3
129 | },
130 | "file_extension": ".py",
131 | "mimetype": "text/x-python",
132 | "name": "python",
133 | "nbconvert_exporter": "python",
134 | "pygments_lexer": "ipython3",
135 | "version": "3.7.7"
136 | }
137 | },
138 | "nbformat": 4,
139 | "nbformat_minor": 2
140 | }
141 |
--------------------------------------------------------------------------------
/Sound-Design/waveform_sinusoidal.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Sinusoidal Periodic Waveform\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [waveform_sinusoidal.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Sound-Design/waveform_sinusoidal.ipynb)\n",
12 | "---\n",
13 | "Overview about *sinusoidal periodic waveform* or *sine wave function*."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib.pyplot as plt\n",
24 | "from IPython.display import Audio\n",
25 | "import numpy as np\n",
26 | "\n",
27 | "from _utils import *"
28 | ]
29 | },
30 | {
31 | "cell_type": "code",
32 | "execution_count": null,
33 | "metadata": {},
34 | "outputs": [],
35 | "source": [
36 | "fs = 44100 # Sampling rate\n",
37 | "dur = 3 # Duration in seconds\n",
38 | "t = np.linspace(0, dur, fs*dur) # Time vector"
39 | ]
40 | },
41 | {
42 | "cell_type": "markdown",
43 | "metadata": {},
44 | "source": [
45 | "## Sine wave\n",
46 | "---\n",
47 | "$$ \\large\n",
48 | "x(t)=A sin(2\\pi f t + \\phi)=A sin(\\omega t + \\phi)\n",
49 | "$$\n",
50 | "\n",
51 | "where,\n",
52 | "\n",
53 | "- $A$ = The aplitude;\n",
54 | "- $f$ = The ordinary frequency;\n",
55 | "- $\\omega$ = The angular frequency;\n",
56 | "- $\\phi$ = The phase."
57 | ]
58 | },
59 | {
60 | "cell_type": "code",
61 | "execution_count": null,
62 | "metadata": {},
63 | "outputs": [],
64 | "source": [
65 | "A = 1\n",
66 | "f = 220\n",
67 | "omega = 2*np.pi*f\n",
68 | "phi = 0\n",
69 | "\n",
70 | "x = A*np.sin(omega*t + phi)"
71 | ]
72 | },
73 | {
74 | "cell_type": "code",
75 | "execution_count": null,
76 | "metadata": {},
77 | "outputs": [],
78 | "source": [
79 | "Audio(x, rate=fs)"
80 | ]
81 | },
82 | {
83 | "cell_type": "code",
84 | "execution_count": null,
85 | "metadata": {},
86 | "outputs": [],
87 | "source": [
88 | "summary(x)"
89 | ]
90 | },
91 | {
92 | "cell_type": "code",
93 | "execution_count": null,
94 | "metadata": {},
95 | "outputs": [],
96 | "source": [
97 | "audiovis(x, tlim=[0, 0.1])"
98 | ]
99 | },
100 | {
101 | "cell_type": "code",
102 | "execution_count": null,
103 | "metadata": {},
104 | "outputs": [],
105 | "source": [
106 | "spectrogram(x, flim=[0,1000])"
107 | ]
108 | },
109 | {
110 | "cell_type": "markdown",
111 | "metadata": {},
112 | "source": [
113 | "## Changing the parameters\n",
114 | "---"
115 | ]
116 | },
117 | {
118 | "cell_type": "code",
119 | "execution_count": null,
120 | "metadata": {},
121 | "outputs": [],
122 | "source": [
123 | "plt.rcParams['figure.figsize'] = (16, 4)"
124 | ]
125 | },
126 | {
127 | "cell_type": "markdown",
128 | "metadata": {},
129 | "source": [
130 | "### Amplitude\n",
131 | "---"
132 | ]
133 | },
134 | {
135 | "cell_type": "code",
136 | "execution_count": null,
137 | "metadata": {},
138 | "outputs": [],
139 | "source": [
140 | "A1 = 1\n",
141 | "A2 = 0.5\n",
142 | "x1 = A1*np.sin(2*np.pi*2*t + 0)\n",
143 | "x2 = A2*np.sin(2*np.pi*2*t + 0)"
144 | ]
145 | },
146 | {
147 | "cell_type": "code",
148 | "execution_count": null,
149 | "metadata": {},
150 | "outputs": [],
151 | "source": [
152 | "plt.plot(t, x1, label=r'$A_1={:.02f}$'.format(A1))\n",
153 | "plt.plot(t, x2, label=r'$A_2={:.02f}$'.format(A2))\n",
154 | "plt.legend()\n",
155 | "plt.show()"
156 | ]
157 | },
158 | {
159 | "cell_type": "markdown",
160 | "metadata": {},
161 | "source": [
162 | "### Frequency\n",
163 | "---"
164 | ]
165 | },
166 | {
167 | "cell_type": "code",
168 | "execution_count": null,
169 | "metadata": {},
170 | "outputs": [],
171 | "source": [
172 | "f1 = 220\n",
173 | "f2 = 440\n",
174 | "x1 = np.sin(2*np.pi*f1*t + 0)\n",
175 | "x2 = np.sin(2*np.pi*f2*t + 0)"
176 | ]
177 | },
178 | {
179 | "cell_type": "code",
180 | "execution_count": null,
181 | "metadata": {},
182 | "outputs": [],
183 | "source": [
184 | "plt.plot(t, x1, label=r'$f_1={0} \\quad Hz$'.format(f1))\n",
185 | "plt.plot(t, x2, label=r'$f_2={0} \\quad Hz$'.format(f2))\n",
186 | "plt.legend(fontsize=12); plt.xlim([0, 0.01])\n",
187 | "plt.show()"
188 | ]
189 | },
190 | {
191 | "cell_type": "code",
192 | "execution_count": null,
193 | "metadata": {},
194 | "outputs": [],
195 | "source": [
196 | "spectrogram(x1 + x2, flim=[0, 1000])"
197 | ]
198 | },
199 | {
200 | "cell_type": "markdown",
201 | "metadata": {},
202 | "source": [
203 | "### Phase\n",
204 | "---"
205 | ]
206 | },
207 | {
208 | "cell_type": "code",
209 | "execution_count": null,
210 | "metadata": {},
211 | "outputs": [],
212 | "source": [
213 | "phi1 = 0\n",
214 | "phi2 = 2*np.pi/5\n",
215 | "x1 = np.sin(2*np.pi*1*t + phi1)\n",
216 | "x2 = np.sin(2*np.pi*1*t + phi2)"
217 | ]
218 | },
219 | {
220 | "cell_type": "code",
221 | "execution_count": null,
222 | "metadata": {},
223 | "outputs": [],
224 | "source": [
225 | "plt.plot(t, x1, label=r'$\\phi_1=0 \\quad rad \\cdot s^{-1}$')\n",
226 | "plt.plot(t, x2, label=r'$\\phi_2=\\frac{2\\pi}{5} \\quad rad \\cdot s^{-1}$')\n",
227 | "plt.legend(fontsize=12)\n",
228 | "plt.show()"
229 | ]
230 | }
231 | ],
232 | "metadata": {
233 | "kernelspec": {
234 | "display_name": "Python [conda env:sounding]",
235 | "language": "python",
236 | "name": "conda-env-sounding-py"
237 | },
238 | "language_info": {
239 | "codemirror_mode": {
240 | "name": "ipython",
241 | "version": 3
242 | },
243 | "file_extension": ".py",
244 | "mimetype": "text/x-python",
245 | "name": "python",
246 | "nbconvert_exporter": "python",
247 | "pygments_lexer": "ipython3",
248 | "version": "3.7.4"
249 | }
250 | },
251 | "nbformat": 4,
252 | "nbformat_minor": 2
253 | }
254 |
--------------------------------------------------------------------------------
/Tips-and-Tricks/README.md:
--------------------------------------------------------------------------------
1 | # Tips and Tricks
2 |
3 | A gathering of _Tips & Tricks_ involving any supporting information for _creative coding_ in general.
4 |
--------------------------------------------------------------------------------
/Tips-and-Tricks/audio_libraries.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Python Audio Libraries\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [audio_libraries.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Tips-and-Tricks/audio_libraries.ipynb)\n",
12 | "---\n",
13 | "Brief overview about some of the main python libraries which promote input and output of digital audio files."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib.pyplot as plt\n",
24 | "from IPython.display import Audio\n",
25 | "import numpy as np\n",
26 | "\n",
27 | "from _utils import *"
28 | ]
29 | },
30 | {
31 | "cell_type": "markdown",
32 | "metadata": {},
33 | "source": [
34 | "## Scipy\n",
35 | "---\n",
36 | "Reading and writing audio files using [SciPy](https://www.scipy.org/).\n",
37 | "\n",
38 | "### Installation\n",
39 | "---\n",
40 | "Install by command line:\n",
41 | "``` python\n",
42 | ">>> conda install scipy\n",
43 | "```\n",
44 | "or\n",
45 | "``` python\n",
46 | ">>> pip install scipy\n",
47 | "```\n",
48 | "\n",
49 | "### Input\n",
50 | "---"
51 | ]
52 | },
53 | {
54 | "cell_type": "code",
55 | "execution_count": null,
56 | "metadata": {},
57 | "outputs": [],
58 | "source": [
59 | "from scipy.io import wavfile"
60 | ]
61 | },
62 | {
63 | "cell_type": "code",
64 | "execution_count": null,
65 | "metadata": {},
66 | "outputs": [],
67 | "source": [
68 | "%%time\n",
69 | "try:\n",
70 | " fs, x_scipy = wavfile.read('../_data/A4_cello01.wav')\n",
71 | " x_scipy = x_scipy.astype(np.float32)\n",
72 | " x_scipy /= np.abs(x_scipy).max(axis=0)\n",
73 | "except:\n",
74 | " print('Can not load audio!')"
75 | ]
76 | },
77 | {
78 | "cell_type": "code",
79 | "execution_count": null,
80 | "metadata": {},
81 | "outputs": [],
82 | "source": [
83 | "audiovis(x_scipy, fs)"
84 | ]
85 | },
86 | {
87 | "cell_type": "code",
88 | "execution_count": null,
89 | "metadata": {},
90 | "outputs": [],
91 | "source": [
92 | "Audio(x_scipy.min(axis=1), rate=fs)"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "metadata": {},
98 | "source": [
99 | "### Analysis\n",
100 | "---"
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "execution_count": null,
106 | "metadata": {},
107 | "outputs": [],
108 | "source": [
109 | "summary_audio(x_scipy)"
110 | ]
111 | },
112 | {
113 | "cell_type": "code",
114 | "execution_count": null,
115 | "metadata": {},
116 | "outputs": [],
117 | "source": [
118 | "%%time\n",
119 | "spectrogram(x_scipy, fs=fs, ws=2048)"
120 | ]
121 | },
122 | {
123 | "cell_type": "markdown",
124 | "metadata": {},
125 | "source": [
126 | "### Output\n",
127 | "---"
128 | ]
129 | },
130 | {
131 | "cell_type": "code",
132 | "execution_count": null,
133 | "metadata": {},
134 | "outputs": [],
135 | "source": [
136 | "#wavfile.write('_output/audio_scipy.wav', fs, x_scipy)"
137 | ]
138 | },
139 | {
140 | "cell_type": "markdown",
141 | "metadata": {},
142 | "source": [
143 | "## pySoundFile\n",
144 | "---\n",
145 | "Reading and writing audio files using [pySoundFile](https://pysoundfile.readthedocs.io).\n",
146 | "\n",
147 | "### Installation\n",
148 | "---\n",
149 | "Install by command line:\n",
150 | "``` python\n",
151 | ">>> conda install -c conda-forge pysoundfile\n",
152 | "```\n",
153 | "or\n",
154 | "``` python\n",
155 | ">>> pip install pysoundfile\n",
156 | "```\n",
157 | "\n",
158 | "### Input\n",
159 | "---"
160 | ]
161 | },
162 | {
163 | "cell_type": "code",
164 | "execution_count": null,
165 | "metadata": {},
166 | "outputs": [],
167 | "source": [
168 | "import soundfile"
169 | ]
170 | },
171 | {
172 | "cell_type": "code",
173 | "execution_count": null,
174 | "metadata": {},
175 | "outputs": [],
176 | "source": [
177 | "%%time\n",
178 | "try:\n",
179 | " x_soundfile, fs = soundfile.read('../_data/A4_cello01.wav')\n",
180 | "except:\n",
181 | " print('Can not load audio!')"
182 | ]
183 | },
184 | {
185 | "cell_type": "code",
186 | "execution_count": null,
187 | "metadata": {},
188 | "outputs": [],
189 | "source": [
190 | "audiovis(x_soundfile, fs)"
191 | ]
192 | },
193 | {
194 | "cell_type": "code",
195 | "execution_count": null,
196 | "metadata": {},
197 | "outputs": [],
198 | "source": [
199 | "Audio(x_soundfile.min(axis=1), rate=fs)"
200 | ]
201 | },
202 | {
203 | "cell_type": "markdown",
204 | "metadata": {},
205 | "source": [
206 | "### Analysis\n",
207 | "---"
208 | ]
209 | },
210 | {
211 | "cell_type": "code",
212 | "execution_count": null,
213 | "metadata": {},
214 | "outputs": [],
215 | "source": [
216 | "summary_audio(x_soundfile)"
217 | ]
218 | },
219 | {
220 | "cell_type": "code",
221 | "execution_count": null,
222 | "metadata": {},
223 | "outputs": [],
224 | "source": [
225 | "%%time\n",
226 | "spectrogram(x_soundfile)"
227 | ]
228 | },
229 | {
230 | "cell_type": "markdown",
231 | "metadata": {},
232 | "source": [
233 | "### Output\n",
234 | "---"
235 | ]
236 | },
237 | {
238 | "cell_type": "code",
239 | "execution_count": null,
240 | "metadata": {},
241 | "outputs": [],
242 | "source": [
243 | "#soundfile.write('_output/audio_soundfile.wav', x_soundfile, fs)"
244 | ]
245 | },
246 | {
247 | "cell_type": "markdown",
248 | "metadata": {},
249 | "source": [
250 | "## LibROSA\n",
251 | "---\n",
252 | "Reading and writing audio files using [LibROSA](http://librosa.github.io/librosa/).\n",
253 | "\n",
254 | "### Installation\n",
255 | "---\n",
256 | "Install by command line:\n",
257 | "``` python\n",
258 | ">>> conda install -c conda-forge librosa\n",
259 | "```\n",
260 | "or\n",
261 | "``` python\n",
262 | ">>> pip install librosa\n",
263 | "```\n",
264 | "\n",
265 | "### Input\n",
266 | "---"
267 | ]
268 | },
269 | {
270 | "cell_type": "code",
271 | "execution_count": null,
272 | "metadata": {},
273 | "outputs": [],
274 | "source": [
275 | "import librosa"
276 | ]
277 | },
278 | {
279 | "cell_type": "code",
280 | "execution_count": null,
281 | "metadata": {},
282 | "outputs": [],
283 | "source": [
284 | "%%time\n",
285 | "try:\n",
286 | " x_librosa, fs = librosa.load('../_data/A4_cello01.wav', mono=False)\n",
287 | " x_librosa = x_librosa.T\n",
288 | "except:\n",
289 | " print('Can not load audio!')"
290 | ]
291 | },
292 | {
293 | "cell_type": "code",
294 | "execution_count": null,
295 | "metadata": {},
296 | "outputs": [],
297 | "source": [
298 | "audiovis(x_librosa, fs)"
299 | ]
300 | },
301 | {
302 | "cell_type": "code",
303 | "execution_count": null,
304 | "metadata": {},
305 | "outputs": [],
306 | "source": [
307 | "Audio(x_librosa.min(axis=1), rate=fs)"
308 | ]
309 | },
310 | {
311 | "cell_type": "markdown",
312 | "metadata": {},
313 | "source": [
314 | "### Analysis\n",
315 | "---"
316 | ]
317 | },
318 | {
319 | "cell_type": "code",
320 | "execution_count": null,
321 | "metadata": {},
322 | "outputs": [],
323 | "source": [
324 | "summary_audio(x_librosa)"
325 | ]
326 | },
327 | {
328 | "cell_type": "code",
329 | "execution_count": null,
330 | "metadata": {},
331 | "outputs": [],
332 | "source": [
333 | "%%time\n",
334 | "spectrogram(x_librosa)"
335 | ]
336 | },
337 | {
338 | "cell_type": "markdown",
339 | "metadata": {},
340 | "source": [
341 | "### Saída\n",
342 | "---"
343 | ]
344 | },
345 | {
346 | "cell_type": "code",
347 | "execution_count": null,
348 | "metadata": {},
349 | "outputs": [],
350 | "source": [
351 | "#librosa.output.write_wav('_output/audio_librosa.wav', x_librosa, fs)"
352 | ]
353 | }
354 | ],
355 | "metadata": {
356 | "kernelspec": {
357 | "display_name": "Python [conda env:sounding] *",
358 | "language": "python",
359 | "name": "conda-env-sounding-py"
360 | },
361 | "language_info": {
362 | "codemirror_mode": {
363 | "name": "ipython",
364 | "version": 3
365 | },
366 | "file_extension": ".py",
367 | "mimetype": "text/x-python",
368 | "name": "python",
369 | "nbconvert_exporter": "python",
370 | "pygments_lexer": "ipython3",
371 | "version": "3.7.4"
372 | }
373 | },
374 | "nbformat": 4,
375 | "nbformat_minor": 2
376 | }
377 |
--------------------------------------------------------------------------------
/Tips-and-Tricks/connect_openai_api.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "selective-opinion",
6 | "metadata": {},
7 | "source": [
8 | "# Connect to OpenAI API\n",
9 | "---\n",
10 | "- Author: Diego Inácio\n",
11 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
12 | "- Notebook: [connect_openai_api.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Tips-and-Tricks/connect_openai_api.ipynb)\n",
13 | "---\n",
14 | "Step by step how to connect to *OpenAI API* and brief introduction.\n",
15 | "\n",
16 | "[OpenAI's API](https://openai.com/api/) is a set of tools and services that allow developers to train and deploy AI models. The API provides access to OpenAI's vast collection of resources, including datasets, algorithms, and pretrained models. The API also allows developers to create and train their own AI models."
17 | ]
18 | },
19 | {
20 | "cell_type": "code",
21 | "execution_count": null,
22 | "id": "velvet-cooper",
23 | "metadata": {},
24 | "outputs": [],
25 | "source": [
26 | "from IPython.display import (\n",
27 | " HTML, display\n",
28 | ")\n",
29 | "\n",
30 | "import os\n",
31 | "import dotenv as de\n",
32 | "\n",
33 | "import openai"
34 | ]
35 | },
36 | {
37 | "attachments": {},
38 | "cell_type": "markdown",
39 | "id": "exceptional-debate",
40 | "metadata": {},
41 | "source": [
42 | "## Installation\n",
43 | "---\n",
44 | "To install the unofficial API and libraries, just the following command for pip or anaconda:\n",
45 | "\n",
46 | "``` python\n",
47 | ">>> pip install openai\n",
48 | "```\n",
49 | "\n",
50 | "or \n",
51 | "\n",
52 | "``` python\n",
53 | ">>> conda install -c conda-forge openai\n",
54 | "```"
55 | ]
56 | },
57 | {
58 | "cell_type": "markdown",
59 | "id": "modern-hundred",
60 | "metadata": {},
61 | "source": [
62 | "## Getting the API key\n",
63 | "---\n",
64 | "In order to connect to the *OpenAI's API* the developer needs access to an **API key**. To get one, first create an account at [beta.openai.com](https://beta.openai.com/) and [create a new secret key](https://beta.openai.com/account/api-keys) by accessing their user settings.\n",
65 | "\n",
66 | "After creating, save this secret key somewhere safe and accessible. You won't be able to view it again through your OpenAI account. If you lose this secret key, you'll need to generate a new one. The generated key must seem like:\n",
67 | "\n",
68 | "| SECRET KEY | CREATED | LAST USED |\n",
69 | "| :--------: | :----------: | :-------: |\n",
70 | "| sk-...Ksf8 | Jan 01, 2022 | Never |\n",
71 | "\n",
72 | "To configure the API with our generated secret key, use the python command:\n",
73 | "\n",
74 | "``` python\n",
75 | "openai.api_key = \n",
76 | "```\n",
77 | "\n",
78 | "In order to protect your key from explicit usage, I strongly recommend using some environment variable method or so. For this example, I'll be using [dotenv](https://pypi.org/project/python-dotenv/) and an external `.env` file."
79 | ]
80 | },
81 | {
82 | "cell_type": "code",
83 | "execution_count": null,
84 | "id": "regional-polls",
85 | "metadata": {},
86 | "outputs": [],
87 | "source": [
88 | "de.load_dotenv(de.find_dotenv())\n",
89 | "\n",
90 | "OPENAI_API_KEY = os.environ.get(\"OPENAI_API_KEY\")\n",
91 | "\n",
92 | "openai.api_key = OPENAI_API_KEY"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "id": "american-brunswick",
98 | "metadata": {},
99 | "source": [
100 | "## Connection test\n",
101 | "---\n",
102 | "To test the connection with OpenAI API, we will generate natural language text using a [GPT-3](https://beta.openai.com/docs/models/gpt-3) model."
103 | ]
104 | },
105 | {
106 | "cell_type": "code",
107 | "execution_count": null,
108 | "id": "mental-student",
109 | "metadata": {},
110 | "outputs": [],
111 | "source": [
112 | "PROMPT = \"What is Creative Coding?\"\n",
113 | "\n",
114 | "response = openai.Completion.create(\n",
115 | " model=\"text-davinci-003\",\n",
116 | " prompt=PROMPT,\n",
117 | " max_tokens=100\n",
118 | ")\n",
119 | "\n",
120 | "print(response[\"choices\"][0][\"text\"])"
121 | ]
122 | }
123 | ],
124 | "metadata": {
125 | "kernelspec": {
126 | "display_name": "Python [conda env:root] *",
127 | "language": "python",
128 | "name": "conda-root-py"
129 | },
130 | "language_info": {
131 | "codemirror_mode": {
132 | "name": "ipython",
133 | "version": 3
134 | },
135 | "file_extension": ".py",
136 | "mimetype": "text/x-python",
137 | "name": "python",
138 | "nbconvert_exporter": "python",
139 | "pygments_lexer": "ipython3",
140 | "version": "3.7.10"
141 | }
142 | },
143 | "nbformat": 4,
144 | "nbformat_minor": 5
145 | }
146 |
--------------------------------------------------------------------------------
/Tips-and-Tricks/matplotlib_animation.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Matplotlib Animation\n",
8 | "---\n",
9 | "- Author: Diego Inácio\n",
10 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
11 | "- Notebook: [matplotlib_animation.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Tips-and-Tricks/matplotlib_animation.ipynb)\n",
12 | "---\n",
13 | "Examples of animated visualization using *Matplotlib*."
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": null,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "%matplotlib inline\n",
23 | "import matplotlib.pyplot as plt\n",
24 | "from matplotlib import cm\n",
25 | "import numpy as np\n",
26 | "from numba import jit\n",
27 | "import imageio as iio\n",
28 | "import os, sys\n",
29 | "\n",
30 | "import matplotlib.animation as manim"
31 | ]
32 | },
33 | {
34 | "cell_type": "code",
35 | "execution_count": null,
36 | "metadata": {},
37 | "outputs": [],
38 | "source": [
39 | "plt.rcParams['figure.figsize'] = (16, 8)"
40 | ]
41 | },
42 | {
43 | "cell_type": "markdown",
44 | "metadata": {},
45 | "source": [
46 | "## Exporting image sequence\n",
47 | "---"
48 | ]
49 | },
50 | {
51 | "cell_type": "markdown",
52 | "metadata": {},
53 | "source": [
54 | "### Color shifting\n",
55 | "---"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": null,
61 | "metadata": {},
62 | "outputs": [],
63 | "source": [
64 | "fig, (axA, axB) = plt.subplots(1, 2)\n",
65 | "\n",
66 | "imgA = iio.imread('../_data/babuino.png')/255\n",
67 | "frames = 4\n",
68 | "\n",
69 | "for frame in range(frames):\n",
70 | " imgA = (imgA + frame/frames) % 1\n",
71 | " axA.imshow(imgA)\n",
72 | "\n",
73 | " axB.hist(imgA[..., 0].ravel(), bins=256, range=(0.0, 1.0), fc='r', alpha=0.5)\n",
74 | " axB.hist(imgA[..., 1].ravel(), bins=256, range=(0.0, 1.0), fc='g', alpha=0.5)\n",
75 | " axB.hist(imgA[..., 2].ravel(), bins=256, range=(0.0, 1.0), fc='b', alpha=0.5)\n",
76 | " \n",
77 | " plt.tight_layout()\n",
78 | "\n",
79 | " plt.savefig('output/matplotlib_animation_colorShift.{0:04d}.png'.format(frame))\n",
80 | " axA.cla(); axB.cla()\n",
81 | "\n",
82 | "plt.close()"
83 | ]
84 | },
85 | {
86 | "cell_type": "code",
87 | "execution_count": null,
88 | "metadata": {},
89 | "outputs": [],
90 | "source": [
91 | "%%HTML\n",
92 | "\n",
93 | " \n",
94 | "  | \n",
95 | "  | \n",
96 | "
\n",
97 | " \n",
98 | "  | \n",
99 | "  | \n",
100 | "
\n",
101 | "
"
102 | ]
103 | },
104 | {
105 | "cell_type": "markdown",
106 | "metadata": {},
107 | "source": [
108 | "## Exporting GIFs\n",
109 | "---\n",
110 | "\n",
111 | "Linux e OSX\n",
112 | "``` python\n",
113 | ">>> conda install --channel conda-forge imagemagick\n",
114 | "```\n",
115 | "\n",
116 | "For windows folow [ImageMagick download](https://imagemagick.org/script/download.php)."
117 | ]
118 | },
119 | {
120 | "cell_type": "code",
121 | "execution_count": null,
122 | "metadata": {},
123 | "outputs": [],
124 | "source": [
125 | "# windows user only\n",
126 | "plt.rcParams[\"animation.convert_path\"] = r\"C:\\Program Files\\ImageMagick-7.0.10-Q16-HDRI\\magick.exe\""
127 | ]
128 | },
129 | {
130 | "cell_type": "markdown",
131 | "metadata": {},
132 | "source": [
133 | "### Reaction-Diffusion system\n",
134 | "---"
135 | ]
136 | },
137 | {
138 | "cell_type": "code",
139 | "execution_count": null,
140 | "metadata": {},
141 | "outputs": [],
142 | "source": [
143 | "@jit(nopython=True, parallel=True)\n",
144 | "def nabla2f(Z):\n",
145 | " '''\n",
146 | " Laplace operator\n",
147 | " '''\n",
148 | " Zup = Z[0:-2,1:-1]\n",
149 | " Zdown = Z[2:,1:-1]\n",
150 | " Zleft = Z[1:-1,0:-2]\n",
151 | " Zright = Z[1:-1,2:]\n",
152 | " Zcenter = Z[1:-1,1:-1]\n",
153 | " return Zup + Zleft + Zdown + Zright - 4*Zcenter\n",
154 | "\n",
155 | "@jit(nopython=True, parallel=True)\n",
156 | "def reactionDiffusion(U, V, u, v, ru, rv, f, k, iters):\n",
157 | " '''\n",
158 | " Reaction diffusion system\n",
159 | " '''\n",
160 | " for i in range(iters):\n",
161 | " u += ru*nabla2f(U) - u*v**2 + f*(1 - u)\n",
162 | " v += rv*nabla2f(V) + u*v**2 - (f + k)*v\n",
163 | " return V"
164 | ]
165 | },
166 | {
167 | "cell_type": "code",
168 | "execution_count": null,
169 | "metadata": {},
170 | "outputs": [],
171 | "source": [
172 | "fig, ax = plt.subplots(figsize=(2048//72, 512//72))\n",
173 | "\n",
174 | "# gif parameters\n",
175 | "N1, N2 = 128j, 512j\n",
176 | "M1, M2 = int(N1.imag), int(N2.imag)\n",
177 | "iters = 70\n",
178 | "frames = 30\n",
179 | "\n",
180 | "# RD system initialization\n",
181 | "np.random.seed(sum(map(lambda c: ord(c), 'reaction diffusion')))\n",
182 | "U = np.zeros((M1 + 2, M2 + 2)); u = U[1:-1, 1:-1]\n",
183 | "V = np.zeros((M1 + 2, M2 + 2)); v = V[1:-1, 1:-1]\n",
184 | "t, s = np.mgrid[-0.25:0.25:N1, -1:1:N2]\n",
185 | "fo = 5\n",
186 | "u += np.sin(np.pi*s*fo)*np.sin(np.pi*t*fo) >= 2**0.5/2\n",
187 | "v += np.cos(np.pi*s*fo)*np.cos(np.pi*t*fo) >= 2**0.5/2\n",
188 | "e = 0.4\n",
189 | "u += np.random.random((M1, M2))*e - e\n",
190 | "v += np.random.random((M1, M2))*e - e\n",
191 | "\n",
192 | "f, k, ru, rv = 0.06, 0.062, 0.19, 0.05\n",
193 | "\n",
194 | "def animation(frame):\n",
195 | " plt.cla(); #ax.set_ylim(-1, 1); ax.set_title('White Noise')\n",
196 | " RD = reactionDiffusion(U, V, u, v, ru, rv, f, k, iters)\n",
197 | " imshow = ax.imshow(RD, vmin=RD.min(), vmax=RD.max())\n",
198 | " plt.tight_layout()\n",
199 | " return imshow\n",
200 | "\n",
201 | "anim = manim.FuncAnimation(fig, animation, frames=30, interval=100)\n",
202 | "\n",
203 | "anim.save('output/matplotlib_animation_reactionDiffusion.gif', writer=\"imagemagick\", extra_args=\"convert\")\n",
204 | "plt.close()\n",
205 | "\n",
206 | "# Solve repetition problem\n",
207 | "! magick convert _output/matplotlib_animation_reactionDiffusion.gif -loop 0 _output/matplotlib_animation_reactionDiffusion.gif\n",
208 | "! echo GIF exported and reconverted. Disregard the message above."
209 | ]
210 | },
211 | {
212 | "cell_type": "markdown",
213 | "metadata": {},
214 | "source": [
215 | ""
216 | ]
217 | },
218 | {
219 | "cell_type": "markdown",
220 | "metadata": {},
221 | "source": [
222 | "## Exporting videos\n",
223 | "---\n",
224 | "\n",
225 | "``` python\n",
226 | ">>> conda install --channel conda-forge ffmpeg\n",
227 | "```"
228 | ]
229 | },
230 | {
231 | "cell_type": "code",
232 | "execution_count": null,
233 | "metadata": {},
234 | "outputs": [],
235 | "source": [
236 | "img = iio.imread('../_data/ship.png')/255\n",
237 | "IMG = np.fft.fft2(img)\n",
238 | "IMG = np.fft.fftshift(IMG)\n",
239 | "\n",
240 | "fig, (axA, axB) = plt.subplots(1, 2)\n",
241 | "\n",
242 | "axA.imshow(img, cmap='gray')\n",
243 | "axA.set_title('input image')\n",
244 | "\n",
245 | "axB.imshow(np.log10(1 + abs(IMG)), cmap='gray')\n",
246 | "axB.set_title('spectrum')\n",
247 | "\n",
248 | "plt.show()"
249 | ]
250 | },
251 | {
252 | "cell_type": "markdown",
253 | "metadata": {},
254 | "source": [
255 | "### Band-pass filter\n",
256 | "---"
257 | ]
258 | },
259 | {
260 | "cell_type": "code",
261 | "execution_count": null,
262 | "metadata": {},
263 | "outputs": [],
264 | "source": [
265 | "t, s = np.mgrid[-1:1:512j, -1:1:512j]\n",
266 | "d = (s**2 + t**2)**0.5\n",
267 | "f = lambda mu, sigma: 1/(sigma*(2*np.pi)**0.5)*np.exp(-1/2*((d - mu)/sigma)**2)\n",
268 | "\n",
269 | "FFMpegWriter = manim.writers['ffmpeg']\n",
270 | "metadata = dict(title='Band-pass filter', artist='Diego Inácio',\n",
271 | " comment='Exporting movies using Python and Matplotlib')\n",
272 | "writer = FFMpegWriter(fps=15, metadata=metadata)\n",
273 | "\n",
274 | "fig, (axA, axB) = plt.subplots(1, 2)\n",
275 | "\n",
276 | "mu, sigma = -0.5, 0.1\n",
277 | "frames = 90\n",
278 | "with writer.saving(fig, 'output/matplotlib_animation_BPF.mp4', frames):\n",
279 | " for i in range(frames):\n",
280 | " H = f(mu, sigma)\n",
281 | " axA.imshow(H, cmap='gray')\n",
282 | " axA.set_title(r'filter H, $\\sigma={0}$, $\\mu={1:.2f}$'.format(sigma, mu))\n",
283 | "\n",
284 | " img_H = np.fft.ifftshift(H*IMG)\n",
285 | " img_H = np.fft.ifft2(img_H).real\n",
286 | " axB.imshow(img_H, cmap='gray')\n",
287 | " axB.set_title('filtered image')\n",
288 | " \n",
289 | " mu += 2/frames\n",
290 | " writer.grab_frame()\n",
291 | " print('{:06.2f} %'.format(100*(i + 1)/frames), end='\\r', flush=True)\n",
292 | "plt.close()"
293 | ]
294 | },
295 | {
296 | "cell_type": "code",
297 | "execution_count": null,
298 | "metadata": {},
299 | "outputs": [],
300 | "source": [
301 | "%%HTML\n",
302 | ""
305 | ]
306 | }
307 | ],
308 | "metadata": {
309 | "kernelspec": {
310 | "display_name": "Python 3",
311 | "language": "python",
312 | "name": "python3"
313 | },
314 | "language_info": {
315 | "codemirror_mode": {
316 | "name": "ipython",
317 | "version": 3
318 | },
319 | "file_extension": ".py",
320 | "mimetype": "text/x-python",
321 | "name": "python",
322 | "nbconvert_exporter": "python",
323 | "pygments_lexer": "ipython3",
324 | "version": "3.7.7"
325 | }
326 | },
327 | "nbformat": 4,
328 | "nbformat_minor": 2
329 | }
330 |
--------------------------------------------------------------------------------
/Tips-and-Tricks/output/matplotlib_animation_BPF.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Tips-and-Tricks/output/matplotlib_animation_BPF.mp4
--------------------------------------------------------------------------------
/Tips-and-Tricks/output/matplotlib_animation_colorShift.0000.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Tips-and-Tricks/output/matplotlib_animation_colorShift.0000.png
--------------------------------------------------------------------------------
/Tips-and-Tricks/output/matplotlib_animation_colorShift.0001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Tips-and-Tricks/output/matplotlib_animation_colorShift.0001.png
--------------------------------------------------------------------------------
/Tips-and-Tricks/output/matplotlib_animation_colorShift.0002.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Tips-and-Tricks/output/matplotlib_animation_colorShift.0002.png
--------------------------------------------------------------------------------
/Tips-and-Tricks/output/matplotlib_animation_colorShift.0003.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Tips-and-Tricks/output/matplotlib_animation_colorShift.0003.png
--------------------------------------------------------------------------------
/Tips-and-Tricks/output/matplotlib_animation_reactionDiffusion.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/Tips-and-Tricks/output/matplotlib_animation_reactionDiffusion.gif
--------------------------------------------------------------------------------
/Tips-and-Tricks/web-scraping.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "selective-opinion",
6 | "metadata": {},
7 | "source": [
8 | "# Web Scraping\n",
9 | "---\n",
10 | "- Author: Diego Inácio\n",
11 | "- GitHub: [github.com/diegoinacio](https://github.com/diegoinacio)\n",
12 | "- Notebook: [web-scraping.ipynb](https://github.com/diegoinacio/creative-coding-notebooks/blob/master/Tips-and-Tricks/web-scraping.ipynb)\n",
13 | "---\n",
14 | "Some demonstrations of how to scrape data on the web.\n",
15 | "\n",
16 | "[Web scraping](https://en.wikipedia.org/wiki/Web_scraping) or **web data extraction** is a process that allows us to collect structured (or even unstructured) data from the web via requests."
17 | ]
18 | },
19 | {
20 | "cell_type": "code",
21 | "execution_count": null,
22 | "id": "velvet-cooper",
23 | "metadata": {},
24 | "outputs": [],
25 | "source": [
26 | "# Scraping libraries\n",
27 | "import requests\n",
28 | "from bs4 import BeautifulSoup\n",
29 | "\n",
30 | "# Display libraries\n",
31 | "from IPython.display import display, HTML, Image, Audio"
32 | ]
33 | },
34 | {
35 | "cell_type": "markdown",
36 | "id": "talented-breed",
37 | "metadata": {},
38 | "source": [
39 | "## Request and HTML Parsing\n",
40 | "---\n",
41 | "The libraries we need are:\n",
42 | "- **Requests**: Allows us to send *HTTP requests* in an extremely easily way.\n",
43 | "- **Beautiful Soup**: Allows us to extract data from HTML files and parse it to a Python objct.\n",
44 | "\n",
45 | "For the following example, let's take the content table from the page [Ordinary Differential Equation](https://en.wikipedia.org/wiki/Ordinary_differential_equation) on wikipedia."
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "execution_count": null,
51 | "id": "inclusive-serial",
52 | "metadata": {},
53 | "outputs": [],
54 | "source": [
55 | "# Request and parse\n",
56 | "URL = \"https://en.wikipedia.org/wiki/Ordinary_differential_equation\"\n",
57 | "html_text = requests.get(URL).text\n",
58 | "parse = BeautifulSoup(html_text, \"html.parser\")\n",
59 | "\n",
60 | "# Get content table\n",
61 | "content_table = (\n",
62 | " parse\n",
63 | " .find(\"div\", {\"id\": \"mw-content-text\"})\n",
64 | " .find(\"div\", {\"id\": \"toc\"})\n",
65 | " .find(\"ul\")\n",
66 | ")\n",
67 | "\n",
68 | "# Change href for each item to redirect to actual page\n",
69 | "for a in content_table.find_all(\"a\"):\n",
70 | " new_URL = URL + a[\"href\"]\n",
71 | " a[\"href\"] = new_URL\n",
72 | "\n",
73 | "# Display content\n",
74 | "HTML(str(content_table))"
75 | ]
76 | },
77 | {
78 | "cell_type": "markdown",
79 | "id": "temporal-economics",
80 | "metadata": {},
81 | "source": [
82 | "## Structured Data\n",
83 | "---\n",
84 | "Scraping structured data with examples."
85 | ]
86 | },
87 | {
88 | "cell_type": "markdown",
89 | "id": "entitled-jason",
90 | "metadata": {},
91 | "source": [
92 | "### HTML Tables\n",
93 | "---\n",
94 | "Getting data from HTML tables.\n",
95 | "\n",
96 | "For the following example, let's take a currency exchange table for Brazillian Real."
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": null,
102 | "id": "excess-throw",
103 | "metadata": {},
104 | "outputs": [],
105 | "source": [
106 | "URL = \"https://www.x-rates.com/table/?from=BRL&amount=1\"\n",
107 | "html_text = requests.get(URL).text\n",
108 | "parse = BeautifulSoup(html_text, \"html.parser\")\n",
109 | "\n",
110 | "table = parse.find(\"table\")\n",
111 | "\n",
112 | "HTML(str(table))"
113 | ]
114 | },
115 | {
116 | "cell_type": "markdown",
117 | "id": "thorough-digest",
118 | "metadata": {},
119 | "source": [
120 | "Having the HTML data, we can bind it to a dataframe using *Pandas* library.\n"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": null,
126 | "id": "endless-underground",
127 | "metadata": {},
128 | "outputs": [],
129 | "source": [
130 | "import pandas as pd\n",
131 | "\n",
132 | "df_table = pd.read_html(str(table))[0]\n",
133 | "df_table"
134 | ]
135 | },
136 | {
137 | "cell_type": "markdown",
138 | "id": "fleet-caribbean",
139 | "metadata": {},
140 | "source": [
141 | "### Consuming open data\n",
142 | "---\n",
143 | "We can read a csv file on the web simply using its url as an argument."
144 | ]
145 | },
146 | {
147 | "cell_type": "code",
148 | "execution_count": null,
149 | "id": "compact-electricity",
150 | "metadata": {},
151 | "outputs": [],
152 | "source": [
153 | "import json\n",
154 | "\n",
155 | "URL = \"https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv\"\n",
156 | "df_csv = pd.read_csv(URL)\n",
157 | "df_csv"
158 | ]
159 | },
160 | {
161 | "cell_type": "markdown",
162 | "id": "middle-purchase",
163 | "metadata": {},
164 | "source": [
165 | "## Unstructured Data\n",
166 | "---\n",
167 | "Scraping unstructured data with examples."
168 | ]
169 | },
170 | {
171 | "cell_type": "markdown",
172 | "id": "naked-essex",
173 | "metadata": {},
174 | "source": [
175 | "### NoSQL file\n",
176 | "---\n",
177 | "Reading static *json* files from the web. For dynamic APIs would be almost the same process."
178 | ]
179 | },
180 | {
181 | "cell_type": "code",
182 | "execution_count": null,
183 | "id": "anonymous-indicator",
184 | "metadata": {},
185 | "outputs": [],
186 | "source": [
187 | "URL = \"https://www.plus2net.com/php_tutorial/student.json\"\n",
188 | "json_file = requests.get(URL).json()\n",
189 | "\n",
190 | "json_file"
191 | ]
192 | },
193 | {
194 | "cell_type": "markdown",
195 | "id": "stable-slide",
196 | "metadata": {},
197 | "source": [
198 | "### Image data\n",
199 | "---\n",
200 | "Scraping *img* elements on google images search engine."
201 | ]
202 | },
203 | {
204 | "cell_type": "code",
205 | "execution_count": null,
206 | "id": "simple-lying",
207 | "metadata": {},
208 | "outputs": [],
209 | "source": [
210 | "# Request | image search for \"zebra\" with large results\n",
211 | "URL = \"https://www.google.com/search?q=zebra&tbm=isch\"\n",
212 | "html_text = requests.get(URL).text\n",
213 | "parse = BeautifulSoup(html_text, 'html.parser')\n",
214 | "\n",
215 | "# Find all img and show 5 of them\n",
216 | "IMG = parse.find_all(\"img\")[1:6]\n",
217 | "\n",
218 | "mount = \"\"\n",
219 | "for img in IMG:\n",
220 | " img[\"style\"] = \"float: left\"\n",
221 | " mount += str(img)\n",
222 | "\n",
223 | "mount = f'Image Scraping
{mount}'\n",
224 | "\n",
225 | "HTML(mount)"
226 | ]
227 | },
228 | {
229 | "cell_type": "markdown",
230 | "id": "authentic-rabbit",
231 | "metadata": {},
232 | "source": [
233 | "### Audio data\n",
234 | "---\n",
235 | "Scraping audio data from web pages.\n",
236 | "\n",
237 | "For the following example, let's find all audio elements in a page."
238 | ]
239 | },
240 | {
241 | "cell_type": "code",
242 | "execution_count": null,
243 | "id": "first-basket",
244 | "metadata": {},
245 | "outputs": [],
246 | "source": [
247 | "mount = \"\"\n",
248 | "TITLE, SOURCE = [], []\n",
249 | "\n",
250 | "# Request and parsing\n",
251 | "URL = \"https://en.wikipedia.org/wiki/Additive_synthesis\"\n",
252 | "html_text = requests.get(URL).text\n",
253 | "parse = BeautifulSoup(html_text, 'html.parser')\n",
254 | "\n",
255 | "# Find all audio elements\n",
256 | "AUDIO = parse.find_all(\"audio\")\n",
257 | "\n",
258 | "# Procedure for each audio element\n",
259 | "for audio in AUDIO:\n",
260 | " title = audio[\"data-mwtitle\"]\n",
261 | " source = audio.find(\"source\")\n",
262 | " src = source[\"src\"]\n",
263 | " mount += f'''\n",
264 | " \n",
265 | "
{title}
\n",
266 | "
\n",
270 | "
{src}\n",
271 | "
\n",
272 | " '''\n",
273 | " TITLE.append(title)\n",
274 | " SOURCE.append(src)\n",
275 | "\n",
276 | "# Output\n",
277 | "mount = f'
Audio Scraping
{mount}'\n",
278 | "HTML(mount)"
279 | ]
280 | }
281 | ],
282 | "metadata": {
283 | "kernelspec": {
284 | "display_name": "Python [conda env:root] *",
285 | "language": "python",
286 | "name": "conda-root-py"
287 | },
288 | "language_info": {
289 | "codemirror_mode": {
290 | "name": "ipython",
291 | "version": 3
292 | },
293 | "file_extension": ".py",
294 | "mimetype": "text/x-python",
295 | "name": "python",
296 | "nbconvert_exporter": "python",
297 | "pygments_lexer": "ipython3",
298 | "version": "3.7.10"
299 | }
300 | },
301 | "nbformat": 4,
302 | "nbformat_minor": 5
303 | }
304 |
--------------------------------------------------------------------------------
/_data/A4_cello-pizzicato.aiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/A4_cello-pizzicato.aiff
--------------------------------------------------------------------------------
/_data/A4_cello01.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/A4_cello01.wav
--------------------------------------------------------------------------------
/_data/A4_cello02.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/A4_cello02.wav
--------------------------------------------------------------------------------
/_data/A4_flute-bad-richness.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/A4_flute-bad-richness.wav
--------------------------------------------------------------------------------
/_data/A4_flute-vibrato.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/A4_flute-vibrato.wav
--------------------------------------------------------------------------------
/_data/A4_flute01.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/A4_flute01.wav
--------------------------------------------------------------------------------
/_data/A4_oboe01.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/A4_oboe01.wav
--------------------------------------------------------------------------------
/_data/A4_piano01.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/A4_piano01.wav
--------------------------------------------------------------------------------
/_data/A4_sax-alto.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/A4_sax-alto.wav
--------------------------------------------------------------------------------
/_data/A4_sax-soprano.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/A4_sax-soprano.wav
--------------------------------------------------------------------------------
/_data/A4_sax-tenor.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/A4_sax-tenor.wav
--------------------------------------------------------------------------------
/_data/Additive_Synthesis_Harmonic.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/Additive_Synthesis_Harmonic.ogg
--------------------------------------------------------------------------------
/_data/Additive_Synthesis_Inharmonic.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/Additive_Synthesis_Inharmonic.ogg
--------------------------------------------------------------------------------
/_data/Additive_synthesis_bell.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/Additive_synthesis_bell.ogg
--------------------------------------------------------------------------------
/_data/aerial01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/aerial01.png
--------------------------------------------------------------------------------
/_data/aerial02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/aerial02.png
--------------------------------------------------------------------------------
/_data/aerial03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/aerial03.png
--------------------------------------------------------------------------------
/_data/babuino.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/babuino.png
--------------------------------------------------------------------------------
/_data/cameraman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/cameraman.png
--------------------------------------------------------------------------------
/_data/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/earth.png
--------------------------------------------------------------------------------
/_data/f16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/f16.png
--------------------------------------------------------------------------------
/_data/fruits.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/fruits.png
--------------------------------------------------------------------------------
/_data/pimentos.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/pimentos.png
--------------------------------------------------------------------------------
/_data/pixel-art-gitlab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/pixel-art-gitlab.png
--------------------------------------------------------------------------------
/_data/pixel-art-mario.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/pixel-art-mario.png
--------------------------------------------------------------------------------
/_data/pixel-art-sonic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/pixel-art-sonic.png
--------------------------------------------------------------------------------
/_data/pixel-art-yoshi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/pixel-art-yoshi.png
--------------------------------------------------------------------------------
/_data/sailboat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/sailboat.png
--------------------------------------------------------------------------------
/_data/ship.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/ship.png
--------------------------------------------------------------------------------
/_data/sphere_16bits.tiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/sphere_16bits.tiff
--------------------------------------------------------------------------------
/_data/sphere_32bits.tiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/sphere_32bits.tiff
--------------------------------------------------------------------------------
/_data/sphere_8bits.tiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/sphere_8bits.tiff
--------------------------------------------------------------------------------
/_data/tomography.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/tomography.png
--------------------------------------------------------------------------------
/_data/woman01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/woman01.png
--------------------------------------------------------------------------------
/_data/woman02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/woman02.png
--------------------------------------------------------------------------------
/_data/woman03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/_data/woman03.png
--------------------------------------------------------------------------------
/docs/assets/icons/go_python_notebooks.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/assets/icons/join_discussion.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/assets/icons/support_this_project.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/assets/icons/visit_cookbook.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/assets/images/social-preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoinacio/creative-coding-notebooks/a2d55791b6b5143b779f0f417645934ac7526306/docs/assets/images/social-preview.png
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
Redirecting ..
12 |
13 |
14 |
15 |
16 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/docs/style.css:
--------------------------------------------------------------------------------
1 | @import url("fontawesome-all.min.css");
2 | @import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400|Passion+One:400");
3 |
4 | * {
5 | margin: 0;
6 | padding: 0;
7 | border: 0;
8 | }
9 |
10 | body {
11 | margin: auto;
12 | width: 736px;
13 | font: 20px Helvetica, sans-serif;
14 | background-color: #252525;
15 | color: gray;
16 | }
17 |
18 | h1 {
19 | font-size: 2.5em;
20 | font-weight: 300;
21 | margin: 1em 0 1em 0;
22 | font-family: "Passion One", cursive;
23 | color: white;
24 | }
25 |
26 | h2 {
27 | margin: 1em 0 1em 0;
28 | }
29 |
30 | article {
31 | display: block;
32 | text-align: left;
33 | width: 650px;
34 | margin: 0 auto;
35 | }
36 |
37 | a {
38 | color: #f2b90d;
39 | text-decoration: none;
40 | }
41 |
42 | a:hover {
43 | color: white;
44 | text-decoration: none;
45 | }
46 |
47 | .signature {
48 | margin: 1em 0 1em 0;
49 | }
50 |
--------------------------------------------------------------------------------