diff --git a/jupyter.ipynb b/jupyter.ipynb index feb02cc..0b3c7e9 100644 --- a/jupyter.ipynb +++ b/jupyter.ipynb @@ -1,194 +1,58 @@ { "cells": [ - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "# Introduction" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "[Jupyter](http://jupyter.org/) is an interactive browser based notebook environment where we can combine text, code execution and visualization. It supports multiple programming languages through it's language specific kernel plugins. However, it is widely used with Python in scientific computing and data science communities. The availability of large number of high quality open source libraries useful for many tasks in scientific computing,numerical linear algebra, machine learning and visualization ensures that Python is being widely used in these fields. Jupyter notebooks are an excellent environment for learning and teaching because of the interactivity.\n", - "\n", - "In this short blogpost, I will explore few topics to illustrate the interactivity of the jupyter environment and the availability of high quality libraries in the python ecosystem.\n", - "- Montecarlo calculation of $\\pi$\n", - "- Image Compression using Singular value decomposition" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "# A note on installation of jupyter" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "Installation of jupyter and other important packages individually is cumbersome. Thanks to [Anaconda](https://www.anaconda.com/products/individual) we have Anaconda python distribution in which almost all of the useful packages are bundled. Install anaconda.\n", - "\n", - "But it is even better not setting up any python environment at all on your computer. Instead, you can use free online python environments- [colab notebooks](https://colab.research.google.com/) from google or [sagemaker studio lab notebook](https://studiolab.sagemaker.aws/) from aws. Watch [this video](https://www.youtube.com/watch?v=SP-WBt2b54o) from the twitter user [1littlecoder](https://twitter.com/1littlecoder) on getting started with sagemaker studio lab." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - " # Montecarlo calculation of $\\pi$" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "I had earlier written about calculating the mathematical constant $\\pi$ using [montecarlo method](https://medium.com/@rameshputalapattu/life-of-pi-a-gophers-tale-2e6922b80792). It involves generating random points on a unit square and counting the number of points inside the unit quarter circle. We will write a function ```mc_pi``` to calculate $\\pi$. In that function, we will also visualize the process of montecarlo simulation using matplotlib library." - ] - }, { "cell_type": "code", - "execution_count": 22, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, + "execution_count": null, "outputs": [], "source": [ + "import IPython\n", "import numpy as np\n", - "import matplotlib.pyplot as plt\n" - ] - }, - { - "cell_type": "code", - "execution_count": 23, + "import matplotlib.pyplot as plt\n", + "from skimage import data\n", + "from skimage.color import rgb2gray\n", + "from skimage import img_as_ubyte,img_as_float\n", + "from numpy.linalg import svd\n", + "from PIL import Image\n", + "# change the cell width\n", + "from IPython.core.display import display, HTML\n", + "display(HTML(\"\"))\n" + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%%\n" } - }, + } + }, + { + "cell_type": "code", + "execution_count": null, "outputs": [], "source": [ "#This line is required to display visualizations in the browser\n", "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "def mc_pi(ntrials):\n", - " \"\"\"\n", - " calculate the value of pi using montecarlo method and visualize the process\n", - " \n", - " \"\"\"\n", - " x = np.random.random(ntrials)\n", - " y = np.random.random(ntrials)\n", - " #masking\n", - " inside_circle = x**2+y**2 < 1\n", - " unit_circle_x = np.linspace(0,1,100)\n", - " unit_circle = [unit_circle_x,np.sqrt(1.0-unit_circle_x**2)]\n", - " plt.plot(*unit_circle,color='black')\n", - " plt.scatter(x[inside_circle],y[inside_circle],marker='.',color='blue',s=1)\n", - " plt.scatter(x[~inside_circle],y[~inside_circle],marker='.',color='red',s=1)\n", - " plt.title(\"value of $\\pi$=\"+str( 4.0*np.sum(inside_circle)/float(ntrials)))\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "We are able to write the function ```mc_pi``` without making use of any explicit ```for``` loops - thanks to vectorization features in numpy library. Due to a concept called broadcasting in numpy, we are able to subtract a vector from a scalar (1.0 - unit_circle_x**2 ) to compute the y co-ordinate of the unit circle. \n", - "\n", - "Now we will make use of ipywidgets module to pass the parameter interactively to the function ```mc_pi```. ipywidgets module provide widgets to generate the UI controls in the notebook itself with which the user can interact. We can drag the slider and observe how the value of pi calculated by mc_pi function changes with the number of trials." - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "62e9cd302c2a459bba91ee276347ef20", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "interactive(children=(IntSlider(value=49991, description='ntrials', max=100000, min=1, step=10), Output()), _d…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } ], - "source": [ - "from ipywidgets import interact,interactive,interact_manual\n", - "mc_widget=interactive(mc_pi,ntrials=(1,100000,10));\n", - "mc_widget" - ] + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } }, { "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, "source": [ "### SVD and Image compression" - ] - }, - { - "cell_type": "markdown", + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%% md\n" } - }, + } + }, + { + "cell_type": "markdown", "source": [ "Now we will explore how to apply Singular Value Decomposition of a matrix to the problem of image compression. SVD decomposes a rectangular matrix $M$ to a three parts.\n", "$M=U\\Sigma V^T$ -\n", @@ -204,46 +68,33 @@ "Here $\\sigma_1,\\sigma_2,\\sigma_3 ...$ are singular values. $u_1,u_2,u_3 ...$ and $v_1,v_2,v_3 ...$ are left and right singular vectors respectively.\n", "\n", "Image compression using SVD involves taking advantage of the fact that very few of the singular values are large. Although images from the real world are of full rank, they have low effective rank which means that only few of the singular values of the SVD of images will be large." - ] - }, - { - "cell_type": "markdown", + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%% md\n" } - }, + } + }, + { + "cell_type": "markdown", "source": [ "### skimage image processing library\n", "\n", "We will use skimage image processing library (from sci-kit family of packages) for working with images in python. skimage has a module called data which makes available a set of images for exploration. We will load some images and convert them into a gray scale format. These images are stored in a python dict object gray_images." - ] + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } }, { "cell_type": "code", - "execution_count": 26, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, + "execution_count": null, "outputs": [], "source": [ - "from skimage import data\n", - "from skimage.color import rgb2gray" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "from skimage import img_as_ubyte,img_as_float\n", "gray_images = {\n", " \"cat\":rgb2gray(img_as_float(data.chelsea())),\n", " \"astro\":rgb2gray(img_as_float(data.astronaut())),\n", @@ -253,15 +104,16 @@ " \"blobs\":data.binary_blobs(),\n", " \"coffee\":rgb2gray(img_as_float(data.coffee()))\n", "}" - ] + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } }, { "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, "source": [ "### svd in python\n", "We will use ```numpy.linalg``` library's ```svd``` function to compute svd of a matrix in python. The svd function returns U,s,V .\n", @@ -273,29 +125,17 @@ "\n", " reconst_matrix = np.dot(U[:,:k],np.dot(np.diag(s[:k]),V[:k,:]))\n", " " - ] + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } }, { "cell_type": "code", - "execution_count": 28, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "from numpy.linalg import svd\n" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, + "execution_count": null, "outputs": [], "source": [ "def compress_svd(image,k):\n", @@ -309,28 +149,30 @@ " reconst_matrix = np.dot(U[:,:k],np.dot(np.diag(s[:k]),V[:k,:]))\n", "\n", " return reconst_matrix,s" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "### Compress gray scale images\n", - "The function ```compress_show_gray_images``` below takes in the image name (img_name) and number of singular values/vectors(k) to be used in the compressed reconstruction. It also plots the singular values and the image." - ] - }, - { - "cell_type": "code", - "execution_count": 30, + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%%\n" } - }, + } + }, + { + "cell_type": "markdown", + "source": [ + "### Compress gray scale images\n", + "The function ```compress_show_gray_images``` below takes in the image name (img_name) and number of singular values/vectors(k) to be used in the compressed reconstruction. It also plots the singular values and the image." + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } + }, + { + "cell_type": "code", + "execution_count": null, "outputs": [], "source": [ "def compress_show_gray_images(img_name,k):\n", @@ -347,31 +189,30 @@ " axes[1].set_title(\"compression ratio={:.2f}\".format(compression_ratio)+\"%\")\n", " axes[1].imshow(reconst_img,cmap='gray')\n", " axes[1].axis('off')\n", - " fig.tight_layout()\n", - " \n", - " \n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "Use the below interactive widget to explore how the quality of the reconstructed image varies with $k$" - ] - }, - { - "cell_type": "code", - "execution_count": 31, + " fig.tight_layout()" + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%%\n" } - }, + } + }, + { + "cell_type": "markdown", + "source": [ + "Use the below interactive widget to explore how the quality of the reconstructed image varies with $k$" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } + }, + { + "cell_type": "code", + "execution_count": null, "outputs": [], "source": [ "def compute_k_max(img_name):\n", @@ -390,19 +231,18 @@ "def update_k_max(*args):\n", " img_name=list_widget.value\n", " int_slider_widget.max = compute_k_max(img_name)\n", - "list_widget.observe(update_k_max,'value')\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 32, + "list_widget.observe(update_k_max,'value')\n" + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%%\n" } - }, + } + }, + { + "cell_type": "code", + "execution_count": null, "outputs": [], "source": [ "# Print matrices\n", @@ -420,125 +260,92 @@ " print('*' * 100)\n", " print(f\"Shape of V matrix: {V[:k,:].shape}\")\n", " print(f\"V MATRIX: {V[:k,:]}\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": 33, + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "69f9d84be21d4b09b9b7687b9ac5277c", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "interactive(children=(Dropdown(description='img_name', options=('cat', 'astro', 'camera', 'coin', 'clock', 'bl…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - } - ], + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], "source": [ "interact(print_matrices, img_name=list_widget, k=int_slider_widget)" - ] - }, - { - "cell_type": "code", - "execution_count": 34, + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "962ee74402d742d2aa9fac156d95ee88", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "interactive(children=(Dropdown(description='img_name', options=('cat', 'astro', 'camera', 'coin', 'clock', 'bl…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], "source": [ "interact(compress_show_gray_images,img_name=list_widget,k=int_slider_widget);" - ] + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } }, { "cell_type": "markdown", + "source": [ + "### Load color images" + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%% md\n" } - }, - "source": [ - "### Load color images" - ] + } }, { "cell_type": "code", - "execution_count": 35, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, + "execution_count": null, "outputs": [], "source": [ "color_images = {\n", " \"cat\":img_as_float(data.chelsea()),\n", " \"astro\":img_as_float(data.astronaut()),\n", - " \"coffee\":img_as_float(data.coffee())\n", - " \n", + " \"coffee\":img_as_float(data.coffee()),\n", + " \"koala\": img_as_float(Image.open('koala.jpeg')),\n", + " \"orange\": img_as_float(Image.open('orange.jpeg'))\n", "}" - ] + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } }, { "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, "source": [ "### Compress color images\n", "\n", "Color images are represented in python as 3 dimensional numpy arrays - the third dimension to represent the color values (red,green blue). However, svd method is applicable to two dimensional matrices. So we have to find a way to convert the 3 dimensional array to 2 dimensional arrays, apply svd and reconstruct it back as a 3 dimensional array . There are two ways to do it. We will show both these methods below .\n", " - reshape method\n", " - Layer method\n" - ] - }, - { - "cell_type": "markdown", + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%% md\n" } - }, + } + }, + { + "cell_type": "markdown", "source": [ "#### Reshape method to compress a color image\n", "This method involves flattening the third dimension of the image array into the second dimension using numpy's reshape method .\n", @@ -549,16 +356,17 @@ " \n", " ```image_reconst = image_reconst.reshape(original_shape)```\n", "\n" - ] + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } }, { "cell_type": "code", - "execution_count": 36, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, + "execution_count": null, "outputs": [], "source": [ "def compress_show_color_images_reshape(img_name,k):\n", @@ -573,27 +381,29 @@ " compression_ratio =100.0* (k*(original_shape[0] + 3*original_shape[1])+k)/(original_shape[0]*original_shape[1]*original_shape[2])\n", " plt.title(\"compression ratio={:.2f}\".format(compression_ratio)+\"%\")\n", " plt.imshow(image_reconst)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "Here is the interactive widget to explore image compression of color images using the reshape method. By dragging the slider to vary $k$, observe how image quality varies. Also, we can explore different images by selecting through the drop down widget." - ] - }, - { - "cell_type": "code", - "execution_count": 37, + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%%\n" } - }, + } + }, + { + "cell_type": "markdown", + "source": [ + "Here is the interactive widget to explore image compression of color images using the reshape method. By dragging the slider to vary $k$, observe how image quality varies. Also, we can explore different images by selecting through the drop down widget." + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } + }, + { + "cell_type": "code", + "execution_count": null, "outputs": [], "source": [ "def compute_k_max_color_images(img_name):\n", @@ -608,81 +418,44 @@ " img_name=list_widget.value\n", " int_slider_widget.max = compute_k_max_color_images(img_name)\n", "list_widget.observe(update_k_max_color,'value')" - ] - }, - { - "cell_type": "code", - "execution_count": 38, + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "cbd795b4af504c9998a5d9f0b41c0d47", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "interactive(children=(Dropdown(description='img_name', options=('cat', 'astro', 'coffee'), value='cat'), IntSl…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], "source": [ "interact(print_matrices, img_name=list_widget, k=int_slider_widget)" - ] - }, - { - "cell_type": "code", - "execution_count": 39, + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "42e07c36e033494a8c242ed336d6f2d8", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "interactive(children=(Dropdown(description='img_name', options=('cat', 'astro', 'coffee'), value='cat'), IntSl…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], "source": [ "interact(compress_show_color_images_reshape,img_name=list_widget,k=int_slider_widget);" - ] + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } }, { "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, "source": [ "### Layers method to compress color images\n", "In the function ```compress_show_color_images_layer```, we treat a color image as a stack of 3 seperate two dimensional images (Red,blue and green layers) . We apply the truncated svd reconstruction on each two dimensional layer seperately.\n", @@ -699,16 +472,17 @@ "\n", "\n", " " - ] + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } }, { "cell_type": "code", - "execution_count": 40, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, + "execution_count": null, "outputs": [], "source": [ "def compress_show_color_images_layer(img_name,k):\n", @@ -726,27 +500,29 @@ " compression_ratio =100.0*3* (k*(original_shape[0] + original_shape[1])+k)/(original_shape[0]*original_shape[1]*original_shape[2])\n", " plt.title(\"compression ratio={:.2f}\".format(compression_ratio)+\"%\")\n", " plt.imshow(image_reconst, vmin=0, vmax=255)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "Here is the widget to explore layers method of compressing color images." - ] - }, - { - "cell_type": "code", - "execution_count": 41, + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%%\n" } - }, + } + }, + { + "cell_type": "markdown", + "source": [ + "Here is the widget to explore layers method of compressing color images." + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } + }, + { + "cell_type": "code", + "execution_count": null, "outputs": [], "source": [ "def compute_k_max_color_images_layers(img_name):\n", @@ -761,57 +537,27 @@ " img_name=list_widget.value\n", " int_slider_widget.max = compute_k_max_color_images_layers(img_name)\n", "list_widget.observe(update_k_max_color_layers,'value')" - ] - }, - { - "cell_type": "code", - "execution_count": 42, + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a76ffdc4780549c8b0e5fef4db6d4f01", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "interactive(children=(Dropdown(description='img_name', options=('cat', 'astro', 'coffee'), value='cat'), IntSl…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], "source": [ "interact(compress_show_color_images_layer,img_name=list_widget,k=int_slider_widget);" - ] - }, - { - "cell_type": "code", - "execution_count": null, + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [] + } } ], "metadata": { @@ -830,7 +576,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.13" + "version": "3.8.9" } }, "nbformat": 4, diff --git a/koala.jpeg b/koala.jpeg new file mode 100644 index 0000000..1d0d2bb Binary files /dev/null and b/koala.jpeg differ diff --git a/orange.jpeg b/orange.jpeg new file mode 100644 index 0000000..a12e03e Binary files /dev/null and b/orange.jpeg differ