Commit 0d477978 authored by abharadwaj1's avatar abharadwaj1
Browse files

added folder

parent f3a160be
%% Cell type:markdown id: tags:
# Introduction to Image Processing
The simplest signal is a sinusoidal wave. Sinusoidal waves have three independant parameters. They are:
* Amplitude, $A$
* Frequency, $f$
* Phase, $\phi $
The relationship between these parameters is given by the mathematical formula:
\begin{equation}
f(t) =A \cdot cos(2 \pi f \cdot t - \phi)
\end{equation}
Where the variable $t$ represents time.
In the following Illustrative, you can play around these values to get an intuitive feel of these variables
%% Cell type:code id: tags:
``` python
from misc import *
out = interact(plotwave,Amplitude=IntSlider(description="Amplitude",value=2,min=-4,max=4),Frequency=IntSlider(description="Freq (Hz)",value=4,min=1,max=8),Phase=FloatSlider(description="Phase (rad)",value=0.0,min=-2*pi,max=2*pi,step=0.5))
```
%%%% Output: display_data
%% Cell type:markdown id: tags:
Signals in real life applications, such as those recieved by your phone during a call, or a radio telescope observing the universe, or the signals from the gravitational wave detectors (LIGO/VIRGO) are quite obviously not simple sinusoids.
%% Cell type:markdown id: tags:
Processing any piece of data would require a mathematical way to describe these signals. Given that real life data are not simple sinusoids, it would require near infinite amounts of parameters to describe such data mathematically. Fortunately, as we shall see in this course, $all$ data can be expressed as a sum of simple sinusoids. Thus, you learn a powerful way to process real life data with arbitrary precision through this course!
%% Cell type:markdown id: tags:
## Fourier Series
In this part, we shall see that $any$ 1 dimensional curve, can be split into a sum of simple sine waves.
To begin with, let us consider a box function.
%% Cell type:markdown id: tags:
Here, play with this interactive to get an intuitive feel for the box function
%% Cell type:code id: tags:
``` python
from misc import *
play_with_box_wave()
```
%%%% Output: display_data
%%%% Output: execute_result
<function misc.play_with_box_wave.<locals>.plotbox(width)>
%% Cell type:markdown id: tags:
For the purpose of this tutorial, let us consider a box function $b(x)$, which has the value $1$ for $-a/2 \lt x \lt a/2$ and 0 otherwise. We shall input this function b(x) for x = 250, and try to decompose it into sinusoidal waves
%% Cell type:code id: tags:
``` python
plt.plot(play_with_box_wave.plotbox(width=250,return_label=True))
```
%%%% Output: error
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-2-4ba5f1e5083d> in <module>
----> 1 plt.plot(plotbox(width=250,return_label=True))
NameError: name 'plotbox' is not defined
%% Cell type:markdown id: tags:
As we learnt before, a sinusoidal wave requires three parameters: (Amplitude: $A$, Frequency: $f$, Phase: $\phi$)
In it's most general form, a Fourier Series can be represented in the following way
\begin{equation}
f(x) = A_0 + \sum\limits_{k=1}^F A_k \cdot cos(\frac{2 \pi k \cdot x}{P} - \phi_k)
\end{equation}
where F is the maximum frequency upto which analysis is done. Since we have set the range of frequencies that we need to study, the question now becomes to find the amplitudes and phases for all such frequencies. In the equation above, $P$ is the period of our input signal. For an arbitrary signal, $P$ is nothing but the length of the signal itself. $A_0$ is the constant term, or it can be considered as the amplitude of the wave having zero frequency.
%% Cell type:markdown id: tags:
For each frequency component $k$, the amplitude and phase can be found out in the following way:
\begin{equation}
a_k = \frac{2}{P} \sum\limits_{i=0}^P s(i) \cdot cos(\frac{2\pi i \cdot k}{P}) \\
b_k = \frac{2}{P} \sum\limits_{i=0}^P s(i) \cdot sin(\frac{2\pi i \cdot k}{P}) \\
A_k = \sqrt(a_k^2 + b_k^2) \\
\phi_k = tan^{-1}(\frac{b_k}{a_k}) \\
\end{equation}
%% Cell type:markdown id: tags:
As we increase the number of frequencies analysed, the reconstructed function looks closer to the input step function $s(x)$. Here, check for yourself!
%% Cell type:code id: tags:
``` python
play_with_reconstruction(getbox(500))
```
%% Cell type:markdown id: tags:
Let's have a look at the different sinusoidal waves that make up the step function as we decomposed before. Suppose we choose to reconstruct with 10 waves.
%% Cell type:code id: tags:
``` python
get_ipython().magic('matplotlib notebook')
out = interact_manual(interactive_reconstruction,InputSignal=fixed(box_input),F=IntSlider(value=3,min=1,max=15,step=1))
```
%% Cell type:markdown id: tags:
Let us now use a randomly generated curve and see if that can also be reconstructed using sin waves
%% Cell type:code id: tags:
``` python
get_ipython().magic('matplotlib inline')
randomlines = plot_random_lines()
```
%% Cell type:code id: tags:
``` python
out = interact(reconstruct,InputSignal=fixed(randomlines),tot_freq=IntSlider(value=20,min=1,max=100,step=1),return_label=fixed(False))
```
%% Cell type:code id: tags:
``` python
get_ipython().magic('matplotlib notebook')
out = interact_manual(interactive_reconstruction,InputSignal=fixed(randomlines),F=IntSlider(value=3,min=1,max=15,step=1))
```
%% Cell type:code id: tags:
``` python
```
%% Cell type:markdown id: tags:
## 2-D Image Processing
Now that we considered 1-D signals and how the Fourier Transforms of those look like, let us move to signals which vary across two dimensions. An image taken by a digital camera is the most common example of a 2D signal.
What do we mean when we say that an image is a 2-D signal? It means, essentially that an image is nothing but a matrix of numbers. We can actually see this matrix in any data management software like Python, Excel or Matlab.
%% Cell type:code id: tags:
``` python
from misc import *
```
%% Cell type:code id: tags:
``` python
I = rgb2gray(plt.imread('cameraman.bmp'))
get_pixel_values(I)
```
%%%% Output: display_data
%%%% Output: execute_result
<function misc.display_df(Image, i, j, box)>
%% Cell type:markdown id: tags:
Have a look at this image. Move the black rectangle around and see the numbers which form the image at this location.
%% Cell type:markdown id: tags:
Each number in this matrix represents a 'pixel value'. When recording an image, photons excites several pixels in a detector and the resulting pattern is what we call an image. For image analysis, the pixel size is important as we shall see later.
Next, we shall try to understand the concepts of spatial frequency and how the 1D analysis we did before applies to images.
name: ip_teaching
channels:
- defaults
dependencies:
- alabaster=0.7.12=py37_0
- argh=0.26.2=py37_0
- argon2-cffi=20.1.0=py37he774522_1
- astroid=2.4.2=py37_0
- atomicwrites=1.4.0=py_0
- attrs=20.1.0=py_0
- autopep8=1.5.4=py_0
- babel=2.8.0=py_0
- backcall=0.2.0=py_0
- bcrypt=3.2.0=py37he774522_0
- bleach=3.1.5=py_0
- brotlipy=0.7.0=py37he774522_1000
- ca-certificates=2020.7.22=0
- certifi=2020.6.20=py37_0
- cffi=1.14.2=py37h7a1dbc1_0
- chardet=3.0.4=py37_1003
- cloudpickle=1.6.0=py_0
- colorama=0.4.3=py_0
- console_shortcut=0.1.1=4
- cryptography=3.1=py37h7a1dbc1_0
- decorator=4.4.2=py_0
- defusedxml=0.6.0=py_0
- diff-match-patch=20200713=py_0
- docutils=0.16=py37_1
- entrypoints=0.3=py37_0
- flake8=3.8.3=py_0
- future=0.18.2=py37_1
- icu=58.2=ha925a31_3
- idna=2.10=py_0
- imagesize=1.2.0=py_0
- importlib-metadata=1.7.0=py37_0
- importlib_metadata=1.7.0=0
- intervaltree=3.1.0=py_0
- ipykernel=5.3.4=py37h5ca1d4c_0
- ipython=7.18.1=py37h5ca1d4c_0
- ipython_genutils=0.2.0=py37_0
- isort=5.4.2=py37_0
- jedi=0.17.1=py37_0
- jinja2=2.11.2=py_0
- jpeg=9b=hb83a4c4_2
- jsonschema=3.2.0=py37_1
- jupyter_client=6.1.6=py_0
- jupyter_core=4.6.3=py37_0
- keyring=21.4.0=py37_0
- lazy-object-proxy=1.4.3=py37he774522_0
- libpng=1.6.37=h2a8f88b_0
- libsodium=1.0.18=h62dcd97_0
- libspatialindex=1.9.3=h33f27b4_0
- m2w64-gcc-libgfortran=5.3.0=6
- m2w64-gcc-libs=5.3.0=7
- m2w64-gcc-libs-core=5.3.0=7
- m2w64-gmp=6.1.0=2
- m2w64-libwinpthread-git=5.0.0.4634.697f757=2
- markupsafe=1.1.1=py37hfa6e2cd_1
- mccabe=0.6.1=py37_1
- mistune=0.8.4=py37hfa6e2cd_1001
- msys2-conda-epoch=20160418=1
- nbconvert=5.6.1=py37_1
- nbformat=5.0.7=py_0
- notebook=6.1.1=py37_0
- numpydoc=1.1.0=py_0
- openssl=1.1.1g=he774522_1
- packaging=20.4=py_0
- pandoc=2.10.1=0
- pandocfilters=1.4.2=py37_1
- paramiko=2.7.2=py_0
- parso=0.7.0=py_0
- pathtools=0.1.2=py_1
- pexpect=4.8.0=py37_1
- pickleshare=0.7.5=py37_1001
- pip=20.2.2=py37_0
- pluggy=0.13.1=py37_0
- prometheus_client=0.8.0=py_0
- prompt-toolkit=3.0.7=py_0
- psutil=5.7.2=py37he774522_0
- pycodestyle=2.6.0=py_0
- pycparser=2.20=py_2
- pydocstyle=5.1.1=py_0
- pyflakes=2.2.0=py_0
- pygments=2.6.1=py_0
- pylint=2.6.0=py37_0
- pynacl=1.4.0=py37h62dcd97_1
- pyopenssl=19.1.0=py_1
- pyparsing=2.4.7=py_0
- pyqt=5.9.2=py37h6538335_2
- pyrsistent=0.16.0=py37he774522_0
- pysocks=1.7.1=py37_1
- python=3.7.9=h60c2a47_0
- python-dateutil=2.8.1=py_0
- python-jsonrpc-server=0.3.4=py_1
- python-language-server=0.34.1=py37_0
- pytz=2020.1=py_0
- pywin32=227=py37he774522_1
- pywin32-ctypes=0.2.0=py37_1001
- pywinpty=0.5.7=py37_0
- pyyaml=5.3.1=py37he774522_1
- pyzmq=19.0.1=py37ha925a31_1
- qdarkstyle=2.8.1=py_0
- qt=5.9.7=vc14h73c81de_0
- qtawesome=0.7.2=py_0
- qtconsole=4.7.6=py_0
- qtpy=1.9.0=py_0
- requests=2.24.0=py_0
- rope=0.17.0=py_0
- rtree=0.9.4=py37h21ff451_1
- send2trash=1.5.0=py37_0
- setuptools=49.6.0=py37_0
- sip=4.19.8=py37h6538335_0
- six=1.15.0=py_0
- snowballstemmer=2.0.0=py_0
- sortedcontainers=2.2.2=py_0
- sphinx=3.2.1=py_0
- sphinxcontrib-applehelp=1.0.2=py_0
- sphinxcontrib-devhelp=1.0.2=py_0
- sphinxcontrib-htmlhelp=1.0.3=py_0
- sphinxcontrib-jsmath=1.0.1=py_0
- sphinxcontrib-qthelp=1.0.3=py_0
- sphinxcontrib-serializinghtml=1.1.4=py_0
- spyder=4.1.5=py37_0
- spyder-kernels=1.9.4=py37_0
- sqlite=3.33.0=h2a8f88b_0
- terminado=0.8.3=py37_0
- testpath=0.4.4=py_0
- toml=0.10.1=py_0
- tornado=6.0.4=py37he774522_1
- traitlets=4.3.3=py37_0
- typed-ast=1.4.1=py37he774522_0
- ujson=1.35=py37hfa6e2cd_0
- urllib3=1.25.10=py_0
- vc=14.1=h0510ff6_4
- vs2015_runtime=14.16.27012=hf0eaf9b_3
- watchdog=0.10.3=py37_0
- wcwidth=0.2.5=py_0
- webencodings=0.5.1=py37_1
- wheel=0.35.1=py_0
- win_inet_pton=1.1.0=py37_0
- wincertstore=0.2=py37_0
- winpty=0.4.3=4
- wrapt=1.11.2=py37he774522_0
- yaml=0.2.5=he774522_0
- yapf=0.30.0=py_0
- zeromq=4.3.2=ha925a31_3
- zipp=3.1.0=py_0
- zlib=1.2.11=h62dcd97_4
- pip:
- cycler==0.10.0
- imageio==2.9.0
- ipysheet==0.4.4
- ipywidgets==7.5.1
- joblib==0.16.0
- kiwisolver==1.2.0
- matplotlib==3.3.1
- networkx==2.5
- numpy==1.19.2
- pandas==1.1.2
- pillow==7.2.0
- pywavelets==1.1.1
- scikit-image==0.17.2
- scikit-learn==0.23.2
- scipy==1.5.2
- threadpoolctl==2.1.0
- tifffile==2020.9.3
- widgetsnbextension==3.5.1
prefix: C:\Users\abharadwaj1\Anaconda3\envs\ip_teaching
# -*- coding: utf-8 -*-
"""
Created on Wed Sep 16 13:39:21 2020
@author: abharadwaj1
"""
import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as image
def sobel(size=3,ax='xy'):
sobelx = cv2.getDerivKernels(1, 0, size)
sobely = cv2.getDerivKernels(0, 1, size)
if ax.lower()=='x':
return np.outer(sobelx[0],sobelx[1])
elif ax.lower()=='y':
return np.outer(sobely[0],sobely[1])
elif ax.lower()=='xy':
return np.outer(sobelx[0],sobelx[1]),np.outer(sobely[0],sobely[1])
def sharpen(size=3):
output = np.ones((size,size)) * -1
output[size//2,size//2] = size**2
return output
def box_blur(size=3):
output = np.ones((size,size)) * 1/size**2
return output
def gaussian_blur(size=3):
std = size/4
xo,yo = size//2,size//2
y,x = np.ogrid[0:size,0:size]
xv,yv = np.meshgrid(x,y)
gauss_output = (np.exp(-1*( ((xv-xo)**2 / (2*std**2)) + ( (yv-yo)**2 / (2*std**2) ))))*1/(2*np.pi*std**2)
return gauss_output
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment