AppliedMachineAndDeepLearni.../conv_animation.ipynb

196 lines
59 KiB
Plaintext
Raw Permalink Normal View History

2023-10-09 10:02:01 +00:00
{
"cells": [
{
"cell_type": "markdown",
"source": [
"| Credentials | |\n",
"|----|----------------------------------|\n",
"|Host | Montanuniversitaet Leoben |\n",
"|Web | https://cps.unileoben.ac.at |\n",
"|Mail | cps@unileoben.ac.at |\n",
"|Author | Fotios Lygerakis |\n",
"|Corresponding Authors | fotios.lygerakis@unileoben.ac.at |\n",
"|Last edited | 28.09.2023 |"
],
"metadata": {
"collapsed": false
},
"id": "e94a99fbf273dd6e"
},
{
"cell_type": "markdown",
"source": [
"This notebook contains code for visualizing the convolution operation."
],
"metadata": {
"collapsed": false
},
"id": "ffa147d97adb2a8"
},
{
"cell_type": "code",
"execution_count": 19,
"outputs": [
{
"data": {
"text/plain": "<Figure size 1500x500 with 3 Axes>",
"image/png": "iVBORw0KGgoAAAANSUhEUgAABdEAAAH/CAYAAAC4vJRfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAACc6UlEQVR4nOzde5yMdf/H8ffsadZhD9YuFoucrfMhEkIUQpG6ReVQud2i+xZS24F02g6IStFRflEKUSnnUw45poiccmbXae2ymD3M9ftj7dixO1h25rI7r+fjMQ8z3/leM+/ru+uanc9853tZDMMwBAAAAAAAAAAAsvExOwAAAAAAAAAAADcriugAAAAAAAAAALhAER0AAAAAAAAAABcoogMAAAAAAAAA4AJFdAAAAAAAAAAAXKCIDgAAAAAAAACACxTRAQAAAAAAAABwgSI6AAAAAAAAAAAuUEQHAAAAAAAAAMAFiuhAPjN58mRZLBbt27fvmvtu2LDB/cFuQhUqVFCfPn3MjnHDLBaLXn75ZbNjAAC8SKtWrdSqVSuzYwAAYLply5bJYrFo2bJlefq4ffr0UYUKFfL0MQG4D0X0AupmK56eO3dOL7/88jW/6GS+SM2YMcO9wQqIDz/8UJMnT87zx3355ZdlsVh04sQJp/aDBw+qUqVKCgsL06ZNm/L8ec2QnJysV199VXXq1FHhwoUVEhKiFi1aaMqUKTIMw+x4AIB8yNXfY4mJiWrcuLECAwM1b948k9IBAOBee/bsUf/+/VWxYkUFBgYqODhYzZo10/jx43X+/Hmz43nEkSNH9PLLL2vz5s1mR8nm5MmTeuaZZ1StWjUFBgYqLCxM7dq1008//XRDjztt2jSNGzcub0Jexc08vih4/MwOAO9w7tw5jRo1SpKY1XSDHn30UT300EOyWq2Otg8//FDh4eEemXV9+PBhtW7dWqdOndKiRYvUoEEDtz+nu8XHx6tNmzbavn27HnroIQ0aNEgXLlzQzJkz1bt3b/3888+aOnWqfH19zY4KAMjnkpKSdPfdd+vPP//U999/r/bt25sdCQCAPDd37lw9+OCDslqt6tWrl2rVqqWUlBStXLlSzzzzjP766y99/PHHZsd0uyNHjmjUqFGqUKGC6tWr53TfJ598IrvdbkquHTt2qE2bNjp+/Lj69u2rRo0a6fTp05o6dao6d+6sYcOG6Z133rmux542bZq2bt2qwYMH523oHFxpfIG8RhEdyGd8fX1NK+YeOXJErVu31smTJ7Vw4UI1bNjwhh8zOTlZRYoUyYN01693797avn27vv/+e917772O9v/+97965plnNHr0aNWvX1/PPvusxzLZ7XalpKQoMDDQY88JAHCvM2fOqF27dtq8ebNmzZqlDh063NDjXbhwQQEBAfLx4culAICbx969e/XQQw+pfPnyWrJkiSIjIx33DRw4ULt379bcuXNNTHhz8Pf3N+V5U1NT9cADDyghIUErVqxQkyZNHPc9/fTTevjhhzV69Gg1atRI3bt3NyUjcDPiL24v0qdPHxUtWlSHDx9Wly5dVLRoUUVERGjYsGFKT0939Nu3b58sFotGjx6td999V+XLl1ehQoXUsmVLbd261ekxXa2XmXVtr3379ikiIkKSNGrUKFksluta4zlzaZGdO3fqkUceUUhIiCIiIvTSSy/JMAwdPHhQ9913n4KDg1WqVCmNGTPGafuUlBSNGDFCDRs2VEhIiIoUKaIWLVpo6dKl2Z7r5MmTevTRRxUcHKzQ0FD17t1bf/zxhywWS7ZlU/7++2898MADCgsLU2BgoBo1aqQffvjhqvvToEED3X///U5ttWvXlsVi0Z9//ulomz59uiwWi7Zv3y4p+5roFSpU0F9//aXly5c7xvbyn4nNZtOQIUMUERGhIkWKqGvXrjp+/PhVM2Z19OhRtW7dWseOHdOCBQvUqFGjXI9DZvbly5frySefVIkSJVS2bFlJGb9LtWrV0rZt29S6dWsVLlxYZcqU0dtvv50ti81m08iRI1W5cmVZrVZFRUVp+PDhstlsudonSfrtt980f/589enTx6mAnik2NlZVqlTRW2+9pfPnzys1NVVhYWHq27dvtr5JSUkKDAzUsGHDcp3VYrFo0KBBmjp1qmrWrCmr1eryK/779+/Xk08+qWrVqqlQoUIqXry4HnzwQad18v/55x9ZLBa9++672bZfvXq1LBaLvv7662sdJgDADTp79qzat2+vTZs2aebMmerYsaPjvsOHD+uxxx5TyZIlZbVaVbNmTX3++edO22cudffNN9/oxRdfVJkyZVS4cGElJSVd8994UsaHtOPGjVPNmjUVGBiokiVLqn///kpISPDIOAAACr63335bZ8+e1WeffeZUQM9UuXJl/e9//3PcTktL06uvvqpKlSrJarWqQoUKev7557O9Z6pQoYI6deqklStXOpZFq1ixoqZMmeLos2HDBlksFn355ZfZnnf+/PmyWCxOy5X8/vvv6tChg4KDg1W0aFG1adNGv/3221X30dX5t7LWSJYtW6Zbb71VktS3b1/H+/XMmkJOa6InJydr6NChioqKktVqVbVq1TR69OhsS4xmvn+cPXu2atWq5fj74VqWiZs5c6a2bt2q5557zqmALmVM2ps0aZJCQ0Odajauzs12+XrxrVq10ty5c7V//37H/mbuY2bf6dOn6/nnn1epUqVUpEgR3XvvvTp48KDT4+bF+AJ5jZnoXiY9PV3t2rVTkyZNNHr0aC1atEhjxoxRpUqVNGDAAKe+U6ZM0ZkzZzRw4EBduHBB48eP15133qktW7aoZMmS1/ycERER+uijjzRgwAB17drVUTiuU6fOde1D9+7dVaNGDb355puaO3euXnvtNYWFhWnSpEm688479dZbb2nq1KkaNmyYbr31Vt1xxx2SMgqcn376qXr06KF+/frpzJkz+uyzz9SuXTutW7fO8dUfu92uzp07a926dRowYICqV6+uOXPmqHfv3tmy/PXXX2rWrJnKlCmj5557TkWKFNG3336rLl26aObMmeratavL/WjRooVTEfPUqVP666+/5OPjo19//dUxPr/++qsiIiJUo0aNHB9n3Lhxeuqpp1S0aFG98MILkpTt5/PUU0+pWLFiGjlypPbt26dx48Zp0KBBmj59+jWNeXx8vB544AHFxcVpwYIFjheq6x2HJ598UhERERoxYoSSk5Md7QkJCWrfvr3uv/9+/etf/9KMGTP07LPPqnbt2o7Zena7Xffee69Wrlypf//736pRo4a2bNmid999Vzt37tTs2bOvaZ8y/fjjj5KkXr165Xi/n5+fevbsqVGjRmnVqlVq27atunbtqlmzZmnSpEkKCAhw9J09e7ZsNpseeuih68q6ZMkSffvttxo0aJDCw8NdnmRm/fr1Wr16tR566CGVLVtW+/bt00cffaRWrVpp27ZtKly4sCpWrKhmzZpp6tSpevrpp522nzp1qoKCgnTfffflaqwAANcnOTlZHTp00Pr16zVjxgx16tTJcV98fLxuu+02x5vhiIgI/fLLL3r88ceVlJSU7avQr776qgICAjRs2DDZbDbH69C1/o3Xv39/TZ48WX379tV///tf7d27Vx988IF+//13rVq1yrRZcQCAguPHH39UxYoVdfvtt19T/yeeeEJffvmlHnjgAQ0dOlRr165VbGys49vCWe3evVsPPPCAHn/8cfXu3Vuff/65+vTpo4YNG6pmzZpq1KiRKlasqG+//Tbbe/jp06erWLFiateunaSM97EtWrRQcHCwhg8fLn9/f02aNEmtWrXS8uXLsxWYc6tGjRp65ZVXNGLECP373/9WixYtJMnluBiGoXvvvVdLly7V448/rnr16mn+/Pl65plndPjw4WwTpFauXKlZs2bpySefVFBQkN577z1169ZNBw4cUPHixV3mutp74JCQEN1333368ssvtXv3blWuXPma9/mFF15QYmKiDh065MhbtGhRpz6vv/66LBaLnn32WR07dkzjxo1T27ZttXnzZhUqVOianyu34wvcMAMF0hdffGFIMtavX+9o6927tyH
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib.patches as patches\n",
"from matplotlib.animation import FuncAnimation, PillowWriter\n",
"\n",
"# Sample image (5x5)\n",
"image = np.array([\n",
" [1, 2, 3, 4, 5],\n",
" [5, 4, 3, 2, 1],\n",
" [1, 2, 3, 4, 5],\n",
" [5, 4, 3, 2, 1],\n",
" [1, 2, 3, 4, 5]\n",
"])\n",
"\n",
"# Kernel (3x3)\n",
"kernel = np.array([\n",
" [1, 0, -1],\n",
" [1, 0, -1],\n",
" [1, 0, -1]\n",
"])\n",
"# # kernel (2x2)\n",
"# kernel = np.array([\n",
"# [1, 0],\n",
"# [1, 0]\n",
"# ])\n",
"\n",
"# Stride and Padding\n",
"stride = 1\n",
"padding = 1\n",
"\n",
"# Create padded image\n",
"padded_image = np.pad(image, ((padding, padding), (padding, padding)))\n",
"\n",
"# Calculate output dimensions\n",
"output_dim = ((image.shape[0] - kernel.shape[0] + 2*padding) // stride) + 1\n",
"\n",
"# Initialize the convolution output\n",
"conv_output = np.zeros((output_dim, output_dim))\n",
"\n",
"# Calculate all possible top-left positions for the kernel\n",
"positions = [(y, x) for y in range(0, padded_image.shape[0] - kernel.shape[0] + 1, stride)\n",
" for x in range(0, padded_image.shape[1] - kernel.shape[1] + 1, stride)]\n",
"\n",
"# Set up the plotting with three subplots for the image, kernel, and convolution output\n",
"fig, (ax1, ax_kernel, ax2) = plt.subplots(1, 3, figsize=(15, 5))\n",
"ax1.imshow(padded_image, cmap='viridis', aspect='equal') # Use equal aspect for square pixels\n",
"ax_kernel.imshow(kernel, cmap='viridis', aspect='equal') # Display the kernel\n",
"ax2.imshow(conv_output, cmap='viridis', aspect='equal', vmin=-15, vmax=15) # Use equal aspect and set vmin, vmax for consistent color scaling\n",
"\n",
"# Add subplot titles\n",
"ax1.set_title(\"Input Image with Kernel Overlay\")\n",
"ax_kernel.set_title(\"Kernel\")\n",
"ax2.set_title(\"Convolution Output\")\n",
"\n",
"# Display numbers on the matrix for the padded image\n",
"for i in range(padded_image.shape[0]):\n",
" for j in range(padded_image.shape[1]):\n",
" ax1.text(j, i, str(padded_image[i, j]), ha='center', va='center', color='red')\n",
"\n",
"# Display numbers on the kernel\n",
"for i in range(kernel.shape[0]):\n",
" for j in range(kernel.shape[1]):\n",
" ax_kernel.text(j, i, str(kernel[i, j]), ha='center', va='center', color='red')\n",
"\n",
"# Kernel rectangle overlay on ax1\n",
"rect = patches.Rectangle((-0.5, -0.5), kernel.shape[1], kernel.shape[0], \n",
" linewidth=3, edgecolor='blue', facecolor='none')\n",
"ax1.add_patch(rect)\n",
"\n",
"# Animation function\n",
"def animate(i):\n",
" y, x = positions[i]\n",
" rect.set_xy((x-0.5, y-0.5))\n",
"\n",
" # Compute the convolution for the current position\n",
" region = padded_image[y:y+kernel.shape[0], x:x+kernel.shape[1]]\n",
" conv_value = np.sum(region * kernel)\n",
" \n",
" # Correctly compute the position in the output matrix\n",
" out_y = y // stride\n",
" out_x = x // stride\n",
" conv_output[out_y, out_x] = conv_value\n",
"\n",
" # Update the convolution output display\n",
" ax2.imshow(conv_output, cmap='viridis', aspect='equal', vmin=-15, vmax=15) # Adjusted colormap and vmin, vmax for better visualization\n",
"\n",
" # Display numbers on the matrix for the convolution output\n",
" for i in range(conv_output.shape[0]):\n",
" for j in range(conv_output.shape[1]):\n",
" ax2.text(j, i, f\"{conv_output[i, j]:.1f}\", ha='center', va='center', color='red')\n",
"\n",
" return rect,\n",
"\n",
"\n",
"# Create animation with increased interval for slower movement\n",
"ani = FuncAnimation(fig, animate, frames=len(positions), interval=2000, blit=True, repeat_delay=10000) # interval set to 5000 for slower movement\n",
"\n",
"# Title and layout\n",
"# title_text = f\"Kernel Size: {kernel.shape[0]}x{kernel.shape[1]}, Stride: {stride}, Padding: {padding}\"\n",
"# fig.suptitle(title_text, fontsize=16)\n",
"\n",
"# Adjust subplot spacing and layout\n",
"plt.subplots_adjust(wspace=0.5)\n",
"plt.tight_layout()\n",
"\n",
"# Save and show\n",
"writer = PillowWriter(fps=2)\n",
"ani.save(f\"convolution_animation_with_output_k{kernel.shape[0]}_s{stride}_p{padding}.gif\", writer=writer)\n",
"plt.show()\n"
],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2023-09-26T11:48:00.679662904Z",
"start_time": "2023-09-26T11:47:47.667621921Z"
}
},
"id": "7e43a9eac318f3c3"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [],
"metadata": {
"collapsed": false
},
"id": "bce4c6c7bb659beb"
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}