Skip to content

Instantly share code, notes, and snippets.

@thepatrickniyo
Created June 30, 2025 09:34
Show Gist options
  • Save thepatrickniyo/2a0632f5dc0fc1a0338fb2cf0fdce0f2 to your computer and use it in GitHub Desktop.
Save thepatrickniyo/2a0632f5dc0fc1a0338fb2cf0fdce0f2 to your computer and use it in GitHub Desktop.
Kernels and Convolution.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": [],
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/thepatrickniyo/2a0632f5dc0fc1a0338fb2cf0fdce0f2/kernels-and-convolution.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "MjQI6ZcWPqg5"
},
"outputs": [],
"source": [
"#!/usr/bin/env python3\n",
"\n",
"import numpy as np\n",
"\n",
"IMAGE = np.array([[1,0,0.13,0.16,0,1],\n",
" [0,0.13,0,0,1,0],\n",
" [0.6,0.13,0.06,1,0,0], # Added a 0 to match column count\n",
" [0,1,1,1,1,0],\n",
" [1,0,1,1,1,0], # Removed extra 1 to match column count\n",
" [1,1,0,0,1,1]])\n",
"\n",
"def convolve_grayscale_valid(image, kernel):\n",
" h, w = image.shape\n",
" kh, kw = kernel.shape\n",
"\n",
" # Calculate the dimensions of the output convolved image\n",
" output_h = h - kh + 1\n",
" output_w = w - kw + 1\n",
"\n",
" convolved_image = np.zeros((output_h, output_w))\n",
"\n",
" for i in range(output_h):\n",
" for j in range(output_w):\n",
" overlapped_area = image[i:i+kh, j:j+kw]\n",
" convolved_image[i,j] = np.sum(overlapped_area * kernel)\n",
"\n",
" return convolved_image"
]
},
{
"cell_type": "code",
"source": [
"#Theory number Anesu\n",
"\n",
"By the size of the convolved\n",
"\n",
"9*9 image\n",
"3*3 Kernel\n",
"\n",
"4*4 conv_img\n",
"\n",
"og_img_width - kernel_width+1\n",
"\n",
"7*7 conv_img"
],
"metadata": {
"id": "Q-B2aiIwRNc5",
"outputId": "b062b7f4-1ebf-46a1-c35a-20d34acb9529",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 106
}
},
"execution_count": null,
"outputs": [
{
"output_type": "error",
"ename": "SyntaxError",
"evalue": "invalid syntax (ipython-input-1-2377775834.py, line 3)",
"traceback": [
"\u001b[0;36m File \u001b[0;32m\"/tmp/ipython-input-1-2377775834.py\"\u001b[0;36m, line \u001b[0;32m3\u001b[0m\n\u001b[0;31m By the size of the convolved\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"#!/usr/bin/env python3\n",
"\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from tensorflow import keras # <--- Add this import\n",
"\n",
"def convolve_grayscale_valid(image, kernel):\n",
" # image is now a single 2D array (height, width)\n",
" h, w = image.shape\n",
"\n",
" kh, kw = kernel.shape\n",
"\n",
" # Let's initialize the variables for height and width\n",
" new_h = h - kh + 1\n",
" new_w = w - kw + 1\n",
"\n",
" # convolved_image is now a single 2D array\n",
" convolved_image = np.zeros((new_h, new_w))\n",
"\n",
" for i in range(new_h):\n",
" for j in range(new_w):\n",
" # No need for batch dimension (:) anymore\n",
" overlapped_area = image[i:i+kh, j:j+kw]\n",
" convolved_image[i, j] = np.sum(overlapped_area * kernel)\n",
"\n",
" return convolved_image\n",
"\n",
"if __name__ == '__main__':\n",
" # Load MNIST dataset directly using Keras\n",
" # The dataset comes as (training_images, training_labels), (test_images, test_labels)\n",
" (images, _), (_, _) = keras.datasets.mnist.load_data()\n",
"\n",
" # Normalize images: pixel values typically range from 0-255.\n",
" # We convert them to float32 and scale them to 0-1 for better processing.\n",
" images = images.astype('float32') / 255.0\n",
"\n",
" # Select only the first image from the dataset for demonstration\n",
" single_image = images[0]\n",
" print(\"Original image shape:\", single_image.shape)\n",
"\n",
" # Define the kernel for edge detection (e.g., Sobel-like vertical edge detector)\n",
" kernel = np.array([[1, 0, -1],\n",
" [1, 0, -1],\n",
" [1, 0, -1]])\n",
"\n",
" # Perform the convolution on the single image\n",
" convolved_single_image = convolve_grayscale_valid(single_image, kernel)\n",
" print(\"Convolved image shape:\", convolved_single_image.shape)\n",
"\n",
" # Display the original and convolved images\n",
" plt.figure(figsize=(10, 5))\n",
"\n",
" plt.subplot(1, 2, 1)\n",
" plt.imshow(single_image, cmap='gray')\n",
" plt.title(\"Original Image\")\n",
" plt.axis('off') # Hide axes for cleaner image display\n",
"\n",
" plt.subplot(1, 2, 2)\n",
" plt.imshow(convolved_single_image, cmap='gray')\n",
" plt.title(\"Convolved Image (Edge Detection)\")\n",
" plt.axis('off') # Hide axes\n",
" plt.show()"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 480
},
"id": "9jgYyPzxROyP",
"outputId": "5c65bdf9-2393-4d4a-8340-896f03583b28"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz\n",
"\u001b[1m11490434/11490434\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 0us/step\n",
"Original image shape: (28, 28)\n",
"Convolved image shape: (26, 26)\n"
]
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 1000x500 with 2 Axes>"
],
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAxoAAAGKCAYAAACLuTc4AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAMpJJREFUeJzt3XlYlPX+//H3MMCwj6IoKAqCJqCouVSmJmbmSS3tWBrmmqmno5XnlJ2yzCVTK/VoaqnV18zsm7mUtpulleXpa+WaV7mklrixCAooCPP5/eGPOYyDyuf2I7g8H9flddU9n/e8P3MP3MNr7s2mlFICAAAAAAb5VPYEAAAAAFx9CBoAAAAAjCNoAAAAADCOoAEAAADAOIIGAAAAAOMIGgAAAACMI2gAAAAAMI6gAQAAAMA4ggYAAAAA4wgaMGLcuHFis9ks1b755ptis9lk3759ZidVyr59+8Rms8mbb755yXoAwJVu3bp1YrPZZN26dRXee+DAgRIbG1vhfS9nf//736VTp05GnzM2NlYGDhxo9DkhkpKSIikpKZe0x5NPPik33njjJe1hGkHjGvfLL79I3759pXbt2uJwOKRWrVpy//33yy+//FLZU6sUJR+yy5Ytq+ypALiC7NmzR4YNGyZxcXESEBAgYWFh0qZNG5k5c6acPHmysqd3VUlJSZHGjRtX9jQuub1798rrr78uo0ePdi8r+dLsXP+mTJlSiTM+v5LP15J/DodDatasKSkpKTJp0iRJT0+3/NwHDx6UcePGyebNm81NuAw7duyQcePGXdIvRs9n5MiRsmXLFlm1alWl9LfCt7IngMqzYsUKSU1NlfDwcBk8eLDUq1dP9u3bJ2+88YYsW7ZM3n33Xbn77rvL9VzPPPOMPPnkk5bm0a9fP7nvvvvE4XBYqgeAyvTxxx/LvffeKw6HQ/r37y+NGzeWwsJCWb9+vYwaNUp++eUXmT9/fmVPE1eYmTNnSr169aRDhw5ej6WmpkqXLl28ll9//fUVMbWL8sgjj0irVq2kuLhY0tPT5fvvv5exY8fK9OnT5b333pNbb71V+zkPHjwo48ePl9jYWGnWrJn5Sf9/O3bskPHjx0tKSorX3rfVq1dfsr4lIiMjpXv37jJ16lS56667Lnk/Ewga16g9e/ZIv379JC4uTr755huJiIhwP/boo49Ku3btpF+/frJ161aJi4s75/Pk5eVJcHCw+Pr6iq+vtR8nu90udrvdUi0AVKa9e/fKfffdJzExMfLVV19JVFSU+7Hhw4fL7t275eOPP67EGeJKdPr0aVm8eLH87W9/K/Px5s2bS9++fSt4Vma0a9dO7rnnHo9lW7Zskdtvv1169uwpO3bs8Pg9ulL4+/tXSJ9evXrJvffeK7///vt5/z67XHDo1DXqpZdekvz8fJk/f75HyBARqV69usybN0/y8vLkxRdfdC8vOQ9jx44d0qdPH6lataq0bdvW47HSTp48KY888ohUr15dQkND5a677pK0tDSx2Wwybtw497iyztGIjY2Vbt26yfr16+WGG26QgIAAiYuLk7feesujR1ZWljz++OOSnJwsISEhEhYWJnfccYds2bLF0Jr672vbuXOn9O3bV5xOp0RERMiYMWNEKSV//vmndO/eXcLCwiQyMlKmTZvmUV9YWCjPPvustGjRQpxOpwQHB0u7du1k7dq1Xr0yMzOlX79+EhYWJlWqVJEBAwbIli1byjy/5Ndff5V77rlHwsPDJSAgQFq2bHlF7U4FrgYvvvii5ObmyhtvvFHmH0f169eXRx991P3/RUVF8txzz0l8fLw4HA6JjY2V0aNHS0FBgUddebaBP/74o9hsNlm4cKFX388//1xsNpt89NFH7mWbNm2SO+64Q8LCwiQkJEQ6duwo//nPf877+kaMGCEhISGSn5/v9VhqaqpERkZKcXGxe9mnn34q7dq1k+DgYAkNDZWuXbuWeSjuBx98II0bN5aAgABp3LixvP/+++edx4XYbDYZMWKELF26VJKSkiQwMFBat24t27ZtExGRefPmSf369SUgIEBSUlK8Dn359ttv5d5775W6deuKw+GQOnXqyD/+8Y8yD3sr6VF67mWdX+JyuWTGjBnSqFEjCQgIkJo1a8qwYcPk2LFjF3w969evl4yMDLntttssrxOllEycOFGio6MlKChIOnTocM7Dordu3Srt27eXwMBAiY6OlokTJ8qCBQvKPH+yvO+xjqZNm8qMGTMkOztbZs+e7fFYWlqaPPDAA1KzZk1xOBzSqFEj+Z//+R/34+vWrZNWrVqJiMigQYPch2aV/sz84Ycf5C9/+Ys4nU4JCgqS9u3by3fffec1j7S0NBk8eLDUqlVLHA6H1KtXTx566CEpLCyUN998U+69914REenQ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DeXnn38ud6/yePDBB93/bbfbpWXLlqKUksGDB7uXV6lSxWuOdrvdfeymy+WSrKwsKSoqkpYtW3rM8bPPPhM/Pz8ZMmSIe5mPj48MHz7cYx5ZWVny1VdfSa9eveTEiROSkZEhGRkZkpmZKZ07d5Zdu3ZJWlqa0dcOwFvJtvFC29ISn3zyiYiI/POf//RY/thjj4mIeJ3LUZ5tYO/eveX06dOyYsUK97LVq1dLdna29O7dW0TObBtXr14tPXr08DimOyoqSvr06SPr16/32s6XsNlscu+998onn3wiubm57uVLliyR2rVruw+f/eKLLyQ7O1tSU1Pd26SMjAyx2+1y4403ug8VPXTokGzevFkGDBggTqfT/XydOnWSpKSkC63C8+rYsaPH4UsllwHt2bOnx3tUsrz0egwMDHT/d15enmRkZMjNN98sSinZtGmTiJw54Xjbtm3Sv39/CQkJcY9v3769JCcne8xl6dKl4nQ6pVOnTh7ro0WLFhISElLmobOlZWZmStWqVc/5+NChQ+WLL77w+leyDtesWSOFhYXy8MMPexzWPHLkSK/n+uyzz6R169YeJ1GHh4fL/fff7zGuvO/xxQgJCXH/jaKUkuXLl8udd94pSimPnp07d5acnJwLfs5v3rxZdu3aJX369JHMzEx3fV5ennTs2FG++eYbcblc4nK55IMPPpA777xTWrZs6fU8Vi7f/8knn0hkZKSkpqa6l/n5+ckjjzwiubm58vXXX3uM7927t8d7XvK7X/rntETVqlUlIyNDe06VgZPBr0ElG9ySX+ZzOVcgqVev3gV77N+/X3x8fLzG1q9fv9zzrFu3rteyqlWrehzf6nK5ZObMmfLKK6/I3r17PY4VrlatWrl7WZmP0+mUgIAAqV69utfyzMxMj2ULFy6UadOmya+//iqnT592Ly+9fvbv3y9RUVESFBTkUXv2Otu9e7copWTMmDEyZsyYMud69OhRqV27dvlfHABtYWFhInLhbWmJku3i2b/TkZGRUqVKFdm/f7/H8vJsA5s2bSoJCQmyZMkS95ceS5YskerVq7uv3pOeni75+fnSsGFDr+dLTEwUl8slf/75pzRq1KjMeffu3VtmzJghq1atkj59+khubq588sknMmzYMPcfYLt27RIROecVg0rWVclrbNCggdeYi/2CqKxttIhInTp1ylxeej3+8ccf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IR9//LG0adPGfX+EyZMnS9euXaVt27bywAMPSFZWlsyaNUsaNWpU5h+Dl1pCQoLEx8fL448/LmlpaRIWFibLly8v89ClSZMmSffu3aVNmzYyaNAgOXbsmMyePVsaN27sMff27dvLsGHDZPLkybJ582a5/fbbxc/PT3bt2iVLly6VmTNnet20rrS2bdtKtWrVZM2aNWWeE/Hzzz/L22+/7bU8Pj5eWrduLREREfL444/L5MmTpVu3btKlSxfZtGmTfPrpp157+5944gl5++23pVOnTvLwww9LcHCwvP7661K3bl3Jyspyf/bovMfn8+2338qpU6fcF3D57rvvZNWqVeJ0OuX999/3OCxrypQpsnbtWrnxxhtlyJAhkpSUJFlZWfLzzz/LmjVr3J+P8fHxUqVKFZk7d66EhoZKcHCw3HjjjVKvXj15/fXX5Y477pBGjRrJoEGDpHbt2pKWliZr166VsLAw+fDDD93v7erVq6V9+/YydOhQSUxMlEOHDsnSpUtl/fr1UqVKFWnWrJnY7XZ54YUXJCcnRxwOh9x6661lnoszdOhQmTdvngwcOFB++ukniY2NlWXLlsl3330nM2bMKPdFJM62Zs0aUUpJ9+7dLdVXuIq9yBUuN1u3blWpqakqKipK+fn5qcjISJWamqq2bdvmNbbkMq/p6ennfKy0vLw8NXz4cBUeHq5CQkJUjx491G+//aZExOOSsOe6vG3Xrl29+px9+bhTp06pxx57TEVFRanAwEDVpk0btWHDBq9xJi5ve/brHjBggAoODi5zjqUvvehyudSkSZNUTEyMcjgc6vrrr1cfffSRGjBggNelHNPT01WfPn1UaGiocjqdauDAgeq7775TIqLeffddj7F79uxR/fv3V5GRkcrPz0/Vrl1bdevWTS1btuy8rxGAeTt37lRDhgxRsbGxyt/fX4WGhqo2bdqoWbNmeVyG+vTp02r8+PGqXr16ys/PT9WpU0c99dRTHmOUKv82sMSuXbvclzhdv359mXP8+eefVefOnVVISIgKCgpSHTp0UN9//73HmLMvb1va008/rURE1a9f/5zrYe3atapz587K6XSqgIAAFR8frwYOHKh+/PFHj3HLly9XiYmJyuFwqKSkJLVixYoyt4llOdflbUvf00Op/273X3rppTJfY+nt/I4dO9Rtt92mQkJCVPXq1dWQIUPUli1byvzcePfdd1VCQoJyOByqcePGatWqVapnz54qISHBa67z589XLVq0UIGBgSo0NFQlJyerJ554Qh08ePCCr/ORRx7xWtcXurxt6cvWFhcXq/Hjx7s/H1NSUtT27dtVTEyMxzillNq0aZNq166dcjgcKjo6Wk2ePFm9/PLLSkTc94kovf7K8x6frWS9l/zz8/NTERER6pZbblHPP/+8Onr0aJl1R44cUcOHD1d16tRx/53SsWNHNX/+fI9xK1euVElJScrX19frfdu0aZP661//qqpVq6YcDoeKiYlRvXr1Ul9++aXHc+zfv1/1799fRUREKIfDoeLi4tTw4cM9LlH/2muvqbi4OGW32z1+V8r63Txy5IgaNGiQql69uvL391fJycleP0/n+jlVSnndDkAppXr37q3atm1b5rq6HNmUOs9lDQDDNm/eLNdff728/fbbXpfOQ9k++OADufvuu2X9+vXSpk2byp4OAOAszZo1k4iICK/zOi7G77//LgkJCfLpp59Kx44djT1veY0cOVLmzZsnubm55zxRGRXr8OHDUq9ePXn33XevmD0anKOBS+bkyZNey2bMmCE+Pj4exw/jv85eZ8XFxTJr1iwJCwuT5s2bV9KsAAAiZ66MVFRU5LFs3bp1smXLFklJSTHaKy4uTgYPHixTpkwx+rxlOfuzJzMzUxYtWiRt27YlZFxGZsyYIcnJyVdMyBARYY8GLpnx48fLTz/9JB06dBBfX1/59NNP5dNPP3UftwhvDz74oJw8eVJat24tBQUFsmLFCvn+++9l0qRJ8tRTT1X29ADgmrZv3z657bbbpG/fvlKrVi359ddfZe7cueJ0OmX79u3G799UUZo1ayYpKSmSmJgoR44ckTfeeEMOHjwoX375JV8M4qIQNHDJfPHFFzJ+/HjZsWOH5ObmSt26daVfv37y9NNPV8g11a9E77zzjkybNk12794tp06dkvr168tDDz0kI0aMqOypAcA1LycnR4YOHSrfffedpKenS3BwsHTs2FGmTJli+eIpl4PRo0fLsmXL5MCBA2Kz2aR58+YyduxYLqGOi0bQAAAAAGAc52gAAAAAMI6gAQAAAMA4ggYAAAAA48p9Rq6pOzkDAPRxOl3ZnnnmmcqeAgBcsyZOnHjex9mjAQAAAMA4ggYAAAAA4wgaAAAAAIwjaAAAAAAwjqABAAAA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\n"
},
"metadata": {}
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment