Python introduction
This tutorial is a short reference guide and intro to python, focused on image analysis. In this course you can use whatever language you chose, but the examples and solution proposals I create will only be available in python.
This guide was updated 30. august 2017, but it is only tested in my environment
<my-prompt> uname -a
Linux <hostname> 4.12.8-2-ARCH #1 SMP PREEMPT Fri Aug 18 14:08:02 UTC 2017 x86_64 GNU/Linux
so it is entirely possible that it will not work as expected on your system.
There are two main versions of python available: python 2 (v2.7) and python 3 (v3.5 or v3.6), and somewhat inconvenient, python 3 is not always backwards compatible with python 2. This introduction, and solution proposals will assume python 3.5, so if you are religous about keeping to some other version, this is totally okay, but remember that instructions posted here assumes v3.5.
One of the great advantages with python is its large open community, and the wide variety of usefull libraries. As a matter of convenience, I will help you set up an Anaconda virtual environment, and show you how to install relevant packages. With this, whenever you see me importing something in a python script, I should already have described how to get this package. Anaconda is of course optional, but I highly recommend it.
Table of contents:
Set up python with anaconda
This particular section is written with Linux or Apple Mac in mind, but I am sure that similar things will also work for Windows users.
Python should be included on MacOS, and on most Linux distributions, but for the anaconda version, follow the install instructions at the anaconda site, and verify that anaconda is installed properly. This should be straight forward, and there is no need for me to copy these instructions here.
Create a virtual environment
When working on different projects, it is enormously practical to isolate the different packages you use for the different projects. System-wide installations, with different projects needing different versions of certain packages is a real pain. A virtual environment is a way to isolate a project, such that no conflicts will occur. Below follows a guide on how to create it, but for an external reference, see e.g. here.
Ensure that conda is up to date, and create a virtual environment (this is for python 3.5, but the same is valid for v2.7).
conda update conda
conda create -n my_env_name python=3.5
where my_env_name
is whatever you want (but preferably something meaningful,
like inf4300
).
That is it. You will find the environment located at
/path/to/my/anaconda_folder/envs/my_env_name
which in my case is
/home/oskrede/anaconda3/envs/inf4300
To enter this environment, type
source activate my_env_name
and to exit, type
source deactivate
in the command line (from wherever, i.e. you do not need to be located in any particular folder).
When you are in the virtual environment, your command line prompt will look like this
(my_env_name) <my_prompt>$
and when you enter python, it will be something like this (print python and hit return, write exit() to exit)
(my_env_name) <my_prompt>$ python
Python 3.5.4 | packaged by conda-forge | (default, Aug 10 2017, 01:38:41)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-15)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()
(my_env_name) <my_prompt>$
With an Anaconda virtual environment you can install packages that will be local to this
environment, which is very convenient. To see what packages you have installed at any given time,
you can type conda list
in your shell. If you have followed the instructions above, you should
see something like this
(my_env_name) <my_prompt>$ conda list
# packages in environment at /path/to/anaconda3/envs/my_env_name:
#
ca-certificates 2017.7.27.1 0 conda-forge
certifi 2017.7.27.1 py35_0 conda-forge
ncurses 5.9 10 conda-forge
openssl 1.0.2l 0 conda-forge
pip 9.0.1 py35_0 conda-forge
python 3.5.4 0 conda-forge
readline 6.2 0 conda-forge
setuptools 36.2.2 py35_0 conda-forge
sqlite 3.13.0 1 conda-forge
tk 8.5.19 2 conda-forge
wheel 0.29.0 py35_0 conda-forge
xz 5.2.3 0 conda-forge
zlib 1.2.11 0 conda-forge
To install a new package, we use the command conda install <package_name>
, e.g. using the package
numpy
as an example:
(my_env_name) <my_prompt>$ conda install numpy
Fetching package metadata ...........
Solving package specifications: .
Package plan for installation in environment /path/to/anaconda3/envs/my_env_name:
The following NEW packages will be INSTALLED:
blas: 1.1-openblas conda-forge
libgfortran: 3.0.0-1
numpy: 1.13.1-py35_blas_openblas_201 conda-forge [blas_openblas]
openblas: 0.2.20-1 conda-forge
Proceed ([y]/n)?
As you can see, you are met with a list of additional dependencies that will also need to be
installed. In order to install numpy
together with its dependencies, press y
(for yes). When
the packages are downloaded you will see something like this:
(my_env_name) <my_prompt>$ conda install numpy
Fetching package metadata ...........
Solving package specifications: .
Package plan for installation in environment /path/to/anaconda3/envs/my_env_name:
The following NEW packages will be INSTALLED:
blas: 1.1-openblas conda-forge
libgfortran: 3.0.0-1
numpy: 1.13.1-py35_blas_openblas_201 conda-forge [blas_openblas]
openblas: 0.2.20-1 conda-forge
Proceed ([y]/n)? y
openblas-0.2.2 100% |##########################################################| Time: 0:00:53 330.18 kB/s
numpy-1.13.1-p 100% |##########################################################| Time: 0:00:35 258.10 kB/s
To see if the package was installed correctly, you can check its version number
(my_env_name) <my_prompt>$ python -c "import numpy as np; print(np.__version__)"
1.13.1
Python
Python is a widely used high-level, general-purpose, interpreted, dynamic programming language. Its design philosophy emphasizes code readability, and its syntax allows programmers to express concepts in fewer lines of code than possible in languages such as C++ or Java. The language provides constructs intended to enable clear programs on both a small and large scale.
Python supports multiple programming paradigms, including object-oriented, imperative and functional programming or procedural styles. It features a dynamic type system and automatic memory management and has a large and comprehensive standard library.
-wikipedia
This part is loosely based on excerpts from the more comprehensive python 3 tutorial, and I will try to not go into too much detail. Code blocs will assume that you are in the regular python interpreter:
(my_env_name) <my_prompt>$ python
Python 3.5.4 | packaged by conda-forge | (default, Aug 10 2017, 01:38:41)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-15)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 2 + 2
4
>>>
or in a text editor, but more on that later.
Types and containers
Python has all available types like int
, float
, bool
and string
as you
would expect from any programming language, and they are often implicitly understood
by context (use with care).
Scalar numbers and booleans
>>> some_int = 8
>>> some_float = 8.0
>>> type(some_int) # prints "<class 'int'>"
>>> type(some_float) # prints "<class 'float'>"
>>> is_equal = some_int == some_float
>>> type(is_equal) # prints "<class 'bool'>"
>>> is_equal
True
>>> some_other_int = 4
>>> is_equal = some_int == some_other_int
>>> is_equal
False
>>> t = True
>>> f = False
>>> t and f # Logical AND
False
>>> t or f # Logical OR
True
>>> not t # Logical NOT
False
>>> t != f # Logical XOR
True
Strings
>>> some_string = 'This is a string'
>>> some_other_string = "This is also a string"
>>> type(some_string) # prints "<class 'str'>"
>>> type(some_other_string) # prints "<class 'str'>"
>>> some_string == some_other_string
False
>>> some_other_string = "This is a string"
>>> some_string == some_other_string
True
Lists
Lists are containers, which values are wrapped by square brackets and separated
by commas. They can be sliced, and accesed by their index (note that python is
zero-indexed, and that the slice intervals are from start_index
(inclusive)
to end_index
(exclusive)).
>>> some_list = [2, 3, 5, 7, 11]
>>> type(some_list) # prints "<class 'list'>"
>>> some_list[0]
2
>>> some_list[4]
11
>>> some_list[-1]
11
>>> some_list[0:2]
[2, 3]
>>> some_list[:2]
[2, 3]
>>> some_list[3:5]
[7, 11]
>>> some_list[3:]
[7, 11]
>>> some_list[3:-1]
[7]
>>> some_list[1:5]
[3, 5, 7, 11]
>>> some_list[1:5:1]
[3, 5, 7, 11]
>>> some_list[1:5:2]
[3, 7]
>>> some_list[1:5:3]
[3, 11]
>>> some_other_list = [13, 17, 19, 23]
>>> some_list + some_other_list # List concatenation
[2, 3, 5, 7, 11, 13, 17, 19, 23]
>>> str_list = ['This ', 'is ', 'a ', 'string']
>>> str_list + some_list
['This ', 'is ', 'a ', 'string', 2, 3, 5, 7, 11]
>>> some_list[2] = 1212 # Replace value at index 2 (lists are mutable)
>>> some_list
[2, 3, 1212, 7, 11]
>>> new_list = [] # Initialize empty list
>>> new_list.append(4) # Append to end of list
>>> new_list.append(8)
>>> new_list.append(2)
>>> new_list
[4, 8, 2]
>>> new_list.pop() # Remove last element and return it
2
>>> new_list.remove(8) # Remove element identified by value
>>> new_list
[4]
Dictionaries
Dictionaries are containers which elements can be accessed by keywords, and they have no internal order (you can however sort them by both keywords and values, but I will not go into that here). They are wrapped by curly brackets, key and value pairs are joined by a colon, and separated by commas.
>>> some_dict = {'key1':2, 'key2':'three', 5:'five'}
>>> type(some_dict) # prints "<class 'dict'>"
>>> some_dict.keys()
dict_keys(['key1', 'key2', 5])
>>> some_dict.values()
dict_values([2, 'three', 'five'])
>>> some_dict['key1']
2
>>> some_dict['key2']
'three'
>>> some_dict[5]
'five'
>>> some_dict['new_key'] = 88 # Adding a new value to a new key
>>> some_dict['new_key']
88
>>> some_dict['key2'] = 88 # Replacing a value for an existing key
>>> some_dict['key2']
88
>>> some_other_dict = {} # Empty initialization
>>> some_other_dict['key'] = 'value' # Everything is as expected
>>> some_other_dict
{'key': 'value'}
Basic operations
Scalar numbers
Nothing out of the ordinary here, the basic binary operations works intuitively.
>>> 2 + 2
4
>>> 2 + 3*4
14
>>> (2 + 3)*4
20
>>> 13 / 5 # Floating point division (integer division in python 2)
2.6
>>> 13 // 5 # Integer division (the quotient in Euclidean division)
2
>>> 13 % 5 # Modulo operator (the remainder in Euclidean division)
3
>>> (13 // 5)*5 + (13 % 5) # Check
13
>>> 2**8 # '**' is the power operator
256
>>> a = 3
>>> a += 3 # Increment by 3
>>> a
6
>>> a -= 2 # Decrement by 2
>>> a
4
>>> a *= 3 # Multiply itself by 3
>>> a
12
>>> a /= 4 # Divide itself by 4 (implicit cast to float)
>>> a
3.0
>>> # a++, a-- and the likes does not exist
Strings and lists
We can also use some handy operations on strings
>>> 'This ' + 'is ' + 'a ' + 'string' # String concatenation
'This is a string'
>>> str1 = 'This '
>>> str2 = 'is '
>>> str3 = 'a '
>>> str4 = 'string'
>>> str5 = str1 + str2 + str3 + str4
>>> str5
'This is a string'
>>> str1*3 + str2 + str3 + str4
'This This This is a string'
>>> list(str5) # String to list of characters
['T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g']
>>> word_list = str5.split() # String to list of words separated by ' ' (whitespace is default)
>>> word_list
['This', 'is', 'a', 'string']
>>> str5.split('i') # String to list of words separated by 'i'
['Th', 's ', 's a str', 'ng']
>>> ''.join(word_list) # List to string
'Thisisastring'
>>> ' '.join(word_list) # List to string separated by whitespace
'This is a string'
>>> '_'.join(word_list) # List to string separated by underscore
'This_is_a_string'
>>> str5[8] # Access element
'a'
>>> str5[8:12] # Slicing
'a st'
>>> str5[8] = 'some' # Strings are immutable
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> str5.replace('a string', 'the way to do it') # But this is allowed
'This is the way to do it'
>>> 'string' in str5 # Check if 'string' is contained in str5
True
>>> 'blablabla' in str5
False
>>> some_list = [2, 3, 5, 7, 11]
>>> 5 in some_list # This works also for lists
True
>>> some_dict = {1:2, 3:4, 5:6}
>>> 3 in some_dict # and dictionaries (but defaults to keys)
True
>>> 4 in some_dict
False
>>> 4 in some_dict.values()
True
String formatting
Python string formatting is divided into an old style and a new style, I will cover some of the basics of the new style, but see more at this nice page.
>>> 'One {0}, and another {1}'.format('here', 'one here') # Explicit placement
'One here, and another one here'
>>> 'One {1}, and another {0}'.format('here', 'one here') # Reversed order
'One one here, and another here'
>>> 'One {}, and another {}'.format('here', 'one here') # Implicit order
'One here, and another one here'
>>> '{0:<20} 20 places, and right alignment {1:>20}'.format('Left alignment', '20 places')
'Left alignment 20 places, and right alignment 20 places'
>>> 'Three decimal places (with rounding): {0:.3f}'.format(3.14159265)
'Three decimal places (with rounding): 3.142'
>>> 'Scientific notation: {0:.3e}'.format(0.000314159265)
'Scientific notation: 3.142e-04'
>>> 'Combo: {0:>10,.3f}'.format(3.14159265)
'Combo: 3.142'
Printing
In python 3.x, print
is a function that formats
the input and writes to stdout, and this is actually some of the more visible
differences between python 2 and 3.
String formatting in python
>>> print('Hello world')
Hello world
>>> print('Hello', 'world')
Hello world
>>> print('Hello', 'world', 1, 2.3)
Hello world 1 2.3
Scripting
Up until now, we have been using the built in python interpreter, which is
great for testing small commands, and using python as a calculator, but for
more complex programs, it is simply better to script whatever you want in
your favourite editor, and execute it with python. All commads are similar,
but for code snippets, I use >>>
to explicitly signal that I am in the
command line interpreter.
Simply open a text editor, write some lines
a = 3
b = 4
c = a + b
print(c)
save it as something ending with .py
, and run it.
(my_env_name) <my_prompt>$ python test_script.py
7
You can easily define functions with the def
keyword, followed by the name of
the function, and ending with a colon. You must indent all lines that follows
it if you want them in the function, this is how python handles blocks. Remember
to put the function definition above the statements using it. If you want the
function to return something, you use the ‘return’ keyword.
def add_these(x, y):
z = x + y
return z
a = 3
b = 4
c = add_these(a, b)
print(c) # This will print 7
We have not touched upon compund statements yet, but they are easily available (remember the note about indentation above).
some_list = [1, 2, 3, 4, 5, 4, 3, 2, 1]
# Use i to iterate the list values.
for i in some_list:
if i > 4:
print(i)
# Use i to iterate the list indices.
for i in range(9):
if some_list[i] > 4:
print(i)
Executing it yields
(my_env_name) <my_prompt>$ python test_script.py
5
4
NumPy
NumPy is the fundamental package for scientific computing with Python. It contains among other things:
- a powerful N-dimensional array object
- sophisticated (broadcasting) functions
- tools for integrating C/C++ and Fortran code
- useful linear algebra, Fourier transform, and random number capabilities
Besides its obvious scientific uses, NumPy can also be used as an efficient multi-dimensional container of generic data. Arbitrary data-types can be defined. This allows NumPy to seamlessly and speedily integrate with a wide variety of databases.
Whenever we are going to do some math on larger arrays (which is almost all the time), we will use numpy. If you are already familiar with matlab, you can check out this tutorial. If you followed the instructions above, numpy should already be installed.
Arrays
A numpy array is a container of values of the same data type. It can be multi-dimensional, and the number of elements in each dimension is given by its shape. One can initialize a numpy array by a nested list.
>>> import numpy as np
>>> a = np.array([[1, 2, 3], [4, 5, 6]]) # Create a 2x3 matrix of ints
>>> print(a)
[[1 2 3]
[4 5 6]]
>>> a.shape
(2, 3)
>>> type(a) # prints <class 'numpy.ndarray'>
>>> a.dtype # Should be 'int64', i.e. 64 bits signed integer
dtype('int64')
>>> at = a.T # Transpose
>>> print(at)
[[1 4]
[2 5]
[3 6]]
>>> b = np.array([[1, 2, 3], [3, 2, 1]])
>>> print(a + b) # Element-wise addition
[[2 4 6]
[7 7 7]]
>>> print(a * b) # Element-wise multiplication
[[ 1 4 9]
[12 10 6]]
>>> c = b.dot(at) # Matrix multiplication
>>> print(c)
[[14 32]
[10 28]]
>>> np.linalg.inv(c) # Matrix inverse (note that it lies in numpy linalg)
array([[ 0.38888889, -0.44444444],
[-0.13888889, 0.19444444]])
You can also initialize numpy arrays with some existing ones
>>> import numpy as np
>>> a = np.zeros((2, 3)) # 2x3 array filled with zeros of 64 bit signed floats
>>> print(a)
[[ 0. 0. 0.]
[ 0. 0. 0.]]
>>> print(a.dtype)
float64
>>> b = np.ones((2, 3)) # 2x3 array filled with ones of 64 bit signed floats
>>> print(b)
[[ 1. 1. 1.]
[ 1. 1. 1.]]
>>> c = np.eye(3) # 3x3 identity matrix of 64 bit signed floats
>>> print(b)
[[ 1. 0. 0.]
[ 0. 1. 0.]
[ 0. 0. 1.]]
>>> d = np.random.random((2, 3)) # 2x3 array filled with values in Unif(0, 1)
>>> print(d)
[[ 0.83841548 0.94643209 0.83842389]
[ 0.0357995 0.95270445 0.49803594]]
We can slice and access arrays like with normal python lists, and some more.
>>> import numpy with np
>>> a = np.array([[1, 2, 3], [4, 5, 6]])
>>> print(a[1, 2])
6
>>> print(a[:, 2]) # Note that the result is a 1 dimensional array (no distinction between row and column vector)
[3 6]
>>> b = a > 2 # Boolean array
>>> print(b)
[[False False True]
[ True True True]]
>>> a[b] = 9 # Use this to set all elements larger than 2 to 9
>>> print(a)
[[1 2 9]
[9 9 9]]
For more fun with numpy, see the numpy reference documentation.
SciPy
Scipy is a collection of open source software tools for scientific computing in Python. Its domain reach over libraries such as NumPy and Matplotlib (more about that later), so a comprehensive guide is far beyond the scope of this simple introduction.
I will occationally use functions defined in the scipy library, as they have many great tools for linear algebra, signal processing, fourier transforms, and image analysis (to name a few). You can read more about it in the SciPy documentation.
In order to install scipy with anaconda, just type conda install scipy
in your shell, and follow
the instructions (for compatibility reasons, you might be asked to downgrade the version of numpy
you installed earlier, but this is done automatically).
(my_env_name) <my_prompt>$ conda install scipy
Fetching package metadata ...........
Solving package specifications: .
Package plan for installation in environment /path/to/anaconda3/envs/my_env_name:
The following NEW packages will be INSTALLED:
scipy: 0.19.1-py35_blas_openblas_202 conda-forge [blas_openblas]
The following packages will be DOWNGRADED:
numpy: 1.13.1-py35_blas_openblas_201 conda-forge [blas_openblas] --> 1.13.1-py35_blas_openblas_200 conda-forge [blas_openblas]
openblas: 0.2.20-1 conda-forge --> 0.2.19-2 conda-forge
Proceed ([y]/n)? y
numpy-1.13.1-p 100% |##########################################################| Time: 0:00:15 577.78 kB/s
scipy-0.19.1-p 100% |##########################################################| Time: 0:00:25 1.59 MB/s
(my_env_name) <my_prompt>$ python -c "import numpy as np; import scipy; print(np.__version__); print(scipy.__version__)"
1.13.1
0.19.1
OpenCV
To help us with the image processing and analysis, I choose to use openCV, as it is a great tool for computer vision. From its own front page
It has C++, C, Python and Java interfaces and supports Windows, Linux, Mac OS, iOS and Android. OpenCV was designed for computational efficiency and with a strong focus on real-time applications. Written in optimized C/C++, the library can take advantage of multi-core processing. Enabled with OpenCL, it can take advantage of the hardware acceleration of the underlying heterogeneous compute platform.
Many of the tools provided by openCV is also available in SciPy, and for this class, it is probably sufficient with only one of them. I think, however, that it is valuable to familiarize oneself with the multitude of tooling available, especially if you are to apply image analysis beyond this course in the future.
Installation
We use the conda package manager to install it, as we have done with the above packages.
(my_env_name) <my_prompt>$ conda install opencv
Fetching package metadata ...........
Solving package specifications: .
Package plan for installation in environment /path/to/anaconda3/envs/my_env_name:
The following NEW packages will be INSTALLED:
bzip2: 1.0.6-1 conda-forge
cairo: 1.14.6-4 conda-forge
dbus: 1.10.22-0 conda-forge
expat: 2.2.1-0 conda-forge
ffmpeg: 3.2.4-1 conda-forge
fontconfig: 2.12.1-4 conda-forge
freetype: 2.7-1 conda-forge
gettext: 0.19.7-1 conda-forge
giflib: 5.1.4-0 conda-forge
glib: 2.51.4-0 conda-forge
gst-plugins-base: 1.8.0-0 conda-forge
gstreamer: 1.8.0-2 conda-forge
harfbuzz: 1.3.4-2 conda-forge
hdf5: 1.8.18-0 conda-forge
icu: 58.1-1 conda-forge
jasper: 1.900.1-4 conda-forge
jpeg: 9b-0 conda-forge
libffi: 3.2.1-3 conda-forge
libiconv: 1.14-4 conda-forge
libpng: 1.6.28-0 conda-forge
libtiff: 4.0.6-7 conda-forge
libwebp: 0.5.2-7 conda-forge
libxcb: 1.12-1 conda-forge
libxml2: 2.9.4-4 conda-forge
opencv: 3.2.0-np113py35_blas_openblas_204 conda-forge [blas_openblas]
pcre: 8.39-0 conda-forge
pixman: 0.34.0-0 conda-forge
qt: 5.6.2-3 conda-forge
x264: 20131217-3 conda-forge
xorg-libxau: 1.0.8-3 conda-forge
xorg-libxdmcp: 1.1.2-3 conda-forge
Proceed ([y]/n)? y
expat-2.2.1-0. 100% |##########################################################| Time: 0:00:02 160.49 kB/s
libffi-3.2.1-3 100% |##########################################################| Time: 0:00:01 25.40 kB/s
pcre-8.39-0.ta 100% |##########################################################| Time: 0:00:05 147.95 kB/s
dbus-1.10.22-0 100% |##########################################################| Time: 0:00:03 529.08 kB/s
ffmpeg-3.2.4-1 100% |##########################################################| Time: 0:01:20 755.83 kB/s
hdf5-1.8.18-0. 100% |##########################################################| Time: 0:00:07 576.09 kB/s
libxml2-2.9.4- 100% |##########################################################| Time: 0:00:05 973.53 kB/s
gstreamer-1.8. 100% |##########################################################| Time: 0:00:02 1.19 MB/s
qt-5.6.2-3.tar 100% |##########################################################| Time: 0:00:58 803.06 kB/s
opencv-3.2.0-n 100% |##########################################################| Time: 0:00:31 833.80 kB/s
As you see, a bunch of additional packages needed to be installed. To check if the installation was successfull, you can try to print the version number.
(my_env_name) <my_prompt>$ python -c "import cv2; print(cv2.__version__)"
3.2.0
Matplotlib
Matplotlib is a plotting library, which module
matplotlib.pyplot
provides plotting functions similar to that of matlab.
First, we install it with conda and check its version number
(my_env_name) <my_prompt>$ conda install matplotlib
Fetching package metadata ...........
Solving package specifications: .
Package plan for installation in environment /home/oskrede/anaconda3/envs/inf4300_2017:
The following NEW packages will be INSTALLED:
cycler: 0.10.0-py35_0 conda-forge
matplotlib: 2.0.2-py35_2 conda-forge
pyparsing: 2.2.0-py35_0 conda-forge
pyqt: 5.6.0-py35_4 conda-forge
python-dateutil: 2.6.1-py35_0 conda-forge
pytz: 2017.2-py35_0 conda-forge
sip: 4.18-py35_1 conda-forge
six: 1.10.0-py35_1 conda-forge
tornado: 4.5.1-py35_0 conda-forge
Proceed ([y]/n)? y
pyparsing-2.2. 100% |##########################################################| Time: 0:00:01 92.71 kB/s
pytz-2017.2-py 100% |##########################################################| Time: 0:00:01 106.90 kB/s
sip-4.18-py35_ 100% |##########################################################| Time: 0:00:02 163.89 kB/s
six-1.10.0-py3 100% |##########################################################| Time: 0:00:01 145.58 kB/s
tornado-4.5.1- 100% |##########################################################| Time: 0:00:03 171.19 kB/s
python-dateuti 100% |##########################################################| Time: 0:00:02 109.02 kB/s
pyqt-5.6.0-py3 100% |##########################################################| Time: 0:00:09 592.33 kB/s
matplotlib-2.0 100% |##########################################################| Time: 0:00:11 847.56 kB/s
(my_env_name) <my_prompt>$ python -c "import matplotlib; print(matplotlib.__version__)"
2.0.2
For a simple 2D plot
import numpy as np
import matplotlib.pyplot as plt
# Create some points following a sine curve
x = np.arange(0, 4*np.pi, 0.1)
y = np.sin(x)
# Plot the points, and remember to call plt.show() at the end
plt.plot(x, y)
plt.show()
This should produce something like this
For a simple 2D plot with multiple graphs
import numpy as np
import matplotlib.pyplot as plt
# Create some points following sine curves with different phase
x = np.arange(0, 4*np.pi, 0.1)
y_1 = np.sin(x)
y_2 = np.sin(x - np.pi/2)
# Plot them
plt.plot(x, y_1)
plt.plot(x, y_2)
plt.xlabel('x axis label')
plt.ylabel('y axis label')
plt.title('Sine curves with different phases')
plt.legend(['Phase 1', r'Phase 1 - $\pi$/2'])
plt.show()
which should look like this
We can also specify multiple figures, which should result in different plot windows.
import numpy as np
import matplotlib.pyplot as plt
# Create some points following sine curves with different phase
x = np.arange(0, 4*np.pi, 0.1)
y_1 = np.sin(x)
y_2 = np.sin(x - np.pi/2)
# First
plt.figure(0)
plt.plot(x, y_1)
# Second
plt.figure(1)
plt.plot(x, y_2)
plt.show()
You can also get different plot graphs in the same figure
import numpy as np
import matplotlib.pyplot as plt
# Create some points following sine curves with different phase
x = np.arange(0, 4*np.pi, 0.1)
y_1 = np.sin(x)
y_2 = np.sin(x - np.pi/2)
# Create a subplot with height 1 and with 2 (meaning that you will have 2
# plots side by side), and specify that this is the first.
plt.subplot(1, 2, 1)
plt.plot(x, y_1)
plt.title('First plot')
# Specify the second one
plt.subplot(1, 2, 2)
plt.plot(x, y_2)
plt.title('Second plot')
plt.show()
Images
We will use openCV to read, manipulate, and write images, but use pyplot to plot them (even though openCV also provides this functionality).
import numpy as np
import matplotlib.pyplot as plt
import cv2
imagefile = './images/test_image.png' # Change this to something useful
# Read image as bgr color image (which is simply a rank 3 numpy array with shape
# (num_height_pixels x num_width_pixels x num_channels))
bgr_image = cv2.imread(imagefile, cv2.IMREAD_COLOR) # OpenCV store color images as bgr by default
print('Color image info:')
print('Type: ', type(bgr_image))
print('Data type: ', bgr_image.dtype)
print('Shape: ', bgr_image.shape)
print('Min val: ', np.min(bgr_image), '. Max val: ', np.max(bgr_image))
# Transform to rgb and plot both
blue, green, red = cv2.split(bgr_image)
rgb_image = cv2.merge([red, green, blue])
# Note that the same could be achieved with the colorspace conversion function cvtColor:
# rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB)
plt.figure(0)
plt.subplot(1, 2, 1)
plt.imshow(bgr_image)
plt.title('BGR')
plt.subplot(1, 2, 2)
plt.imshow(rgb_image)
plt.title('RGB')
# Read the same image in as a graylevel image, and plot it
gray_image = cv2.imread(imagefile, cv2.IMREAD_GRAYSCALE)
# As before, we could have used colorspace conversion for the same result
# gray_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2GRAY)
# gray_image = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2GRAY)
print('Graylevel image info:')
print('Type: ', type(gray_image))
print('Data type: ', gray_image.dtype)
print('Shape: ', gray_image.shape)
print('Min val: ', np.min(gray_image), '. Max val: ', np.max(gray_image))
plt.figure(1)
plt.imshow(gray_image, cmap='gray') # Note the colormap definition
plt.xticks([]) # Remove ticks on x axis
plt.yticks([]) # Remove ticks on y axis
plt.title('Graylevel image')
plt.show()
This script will produce the following output (in addition to the plots):
Color image info:
Type: <class 'numpy.ndarray'>
Data type: uint8
Shape: (576, 768, 3)
Min val: 0 . Max val: 255
Graylevel image info:
Type: <class 'numpy.ndarray'>
Data type: uint8
Shape: (576, 768)
Min val: 0 . Max val: 255
provided that you read in the test_image.png
from Images. The
plots will look like this.
You should now be equipped with the most basic tools for this course, but it is highly recommended that you spend some time experimenting on your own to get comfortable with the language and its tools.