Skip to content

Commit f3d413d

Browse files
authored
Merge branch 'gh-pages' into 181-style-polishes
2 parents 481cf9e + 8114024 commit f3d413d

File tree

8 files changed

+155
-37
lines changed

8 files changed

+155
-37
lines changed

episodes/01-introduction.md

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,48 @@ image analysis problems."
1818
objects in an image."
1919
---
2020

21-
We can use relatively simple image processing and computer vision techniques in
22-
Python, using [the skimage library](https://scikit-image.org/).
23-
With careful experimental design, a digital camera or a flatbed scanner,
24-
in conjunction with some Python code,
25-
can be a powerful instrument in answering many different kinds of problems.
26-
Consider the following problem that might be of interest to a scientist.
21+
22+
As computer systems have become faster and more powerful,
23+
and cameras and other imaging systems have become commonplace
24+
in many other areas of life,
25+
the need has grown for researchers to be able to
26+
process and analyse image data.
27+
Considering the large volumes of data that can be involved -
28+
high-resolution images that take up a lot of disk space/virtual memory,
29+
and/or collections of many images that must be processed together -
30+
and the time-consuming and error-prone nature of manual processing,
31+
it can be advantageous or even necessary for this processing and analysis
32+
to be automated as a computer program.
33+
34+
This lesson introduces an open source toolkit for processing image data:
35+
the Python programming language
36+
and [the _scikit-image_ (`skimage`) library](https://scikit-image.org/).
37+
With careful experimental design,
38+
Python code can be a powerful instrument in answering many different kinds of questions.
39+
40+
41+
## Uses of Image Processing in Research
42+
43+
Automated processing can be used to analyse many different properties of an image,
44+
including the distribution and change in colours in the image,
45+
the number, size, position, orientation, and shape of objects in the image,
46+
and even - when combined with machine learning techniques for object recognition -
47+
the type of objects in the image.
48+
49+
Some examples of image processing methods applied in research include:
50+
51+
- [imaging a Black Hole](https://iopscience.iop.org/article/10.3847/2041-8213/ab0e85)
52+
- [estimating the population of Emperor Penguins](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3325796/)
53+
- [the global-scale analysis of marine plankton diversity](https://www.cell.com/cell/fulltext/S0092-8674(19)31124-9)
54+
- [segmentation of liver and vessels from CT images](https://doi.org/10.1016/j.cmpb.2017.12.008)
55+
56+
With this lesson,
57+
we aim to provide a thorough grounding in the fundamental concepts and skills
58+
of working with image data in Python.
59+
Most of the examples used in this lesson focus on
60+
one particular class of image processing technique, _morphometrics_,
61+
but what you will learn can be used to solve a much wider range of problems.
62+
2763

2864
## Morphometrics
2965

@@ -72,10 +108,12 @@ resulting in an image like this:
72108
> research.
73109
{: .callout}
74110

75-
As we move through this workshop,
76-
we will learn image analysis methods useful for many different scientific problems.
77-
These will be linked together and applied to a real problem in
78-
the final end-of-workshop [capstone challenge]({{page.root}}{% link _episodes/09-challenges.md %}).
111+
112+
As we move through this workshop,
113+
we will learn image analysis methods useful for many different scientific problems.
114+
These will be linked together
115+
and applied to a real problem in the final end-of-workshop
116+
[capstone challenge]({{ page.root }}{% link _episodes/09-challenges.md %}).
79117

80118
Let's get started,
81119
by learning some basics about how images are represented and stored digitally.

episodes/02-image-basics.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,5 +958,6 @@ image formats:
958958
| | | | high quality | |
959959
| JPEG | Lossy | Yes | Universally viewable, | Detail may be lost |
960960
| | | | smaller file size | |
961+
| PNG | Lossless | [Yes](https://www.w3.org/TR/PNG/#11keywords) | Universally viewable, [open standard](https://www.w3.org/TR/PNG/), smaller file size | Metadata less flexible than TIFF, RGB only |
961962
| TIFF | None, lossy, | Yes | High quality or | Not universally viewable |
962963
| | or lossless | | smaller file size | |

episodes/06-blurring.md

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ A blur is a very common operation we need to perform before other tasks such as
3939
There are several different blurring functions in the `skimage.filters` module,
4040
so we will focus on just one here, the *Gaussian blur*.
4141

42+
4243
> ## Filters
4344
>
4445
> In the day-to-day, macroscopic world,
@@ -285,7 +286,14 @@ plt.show()
285286
286287
> ## Experimenting with sigma values (10 min)
287288
>
288-
> Try running the code above with a range of smaller and larger sigma values.
289+
> The size and shape of the kernel used to blur an image can have a
290+
> significant effect on the result of the blurring and any downstream analysis
291+
> carried out on the blurred image.
292+
> The next two exercises ask you to experiment with the sigma values of the kernel,
293+
> which is a good way to develop your understanding of how the choice of kernel
294+
> can influence the result of blurring.
295+
>
296+
> First, try running the code above with a range of smaller and larger sigma values.
289297
> Generally speaking, what effect does the sigma value have on the
290298
> blurred image?
291299
>
@@ -302,9 +310,9 @@ plt.show()
302310
303311
> ## Experimenting with kernel shape (10 min - optional, not included in timing)
304312
>
305-
> Now, try running the code above with different sigmas in the y and x direction.
313+
> Now, what is the effect of applying an asymmetric kernel to blurring an image?
314+
> Try running the code above with different sigmas in the y and x direction.
306315
> For example, a sigma of 1.0 in the y direction, and 6.0 in the x direction.
307-
> What is the effect on the blurred image?
308316
>
309317
> > ## Solution
310318
> >
@@ -320,9 +328,20 @@ plt.show()
320328
> > plt.show()
321329
> > ~~~
322330
> > {: .language-python}
331+
> >
323332
> > ![Rectangular kernel blurred image](../fig/rectangle-gaussian-blurred.png)
324-
> > This produces a kernel that is rectangular instead of square. Notice that the image
325-
> > is much more blurred in the x direction than the y direction.
333+
> >
334+
> > These unequal sigma values produce a kernel that is rectangular instead of square.
335+
> > The result is an image that is much more blurred in the x direction than the
336+
> > y direction.
337+
> > For most use cases, a uniform blurring effect is desirable and
338+
> > this kind of asymmetric blurring should be avoided.
339+
> > However, it can be helpful in specific circumstances e.g. when noise is present in
340+
> > your image in a particular pattern or orientation, such as vertical lines,
341+
> > or when you want to
342+
> > [remove uniform noise without blurring edges present in the image in a particular orientation](https://www.researchgate.net/publication/228567435_An_edge_detection_algorithm_based_on_rectangular_Gaussian_kernels_for_machine_vision_applications).
343+
> >
344+
> >
326345
> {: .solution}
327346
{: .challenge}
328347

episodes/07-thresholding.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,10 @@ Here, we want to turn "on" all pixels which have values smaller than the thresho
151151
so we use the less operator `<` to compare the `blurred_image` to the threshold `t`.
152152
The operator returns a mask, that we capture in the variable `binary_mask`.
153153
It has only one channel, and each of its values is either 0 or 1.
154-
The binary mask created by the thresholding operation can be shown with `plt.imshow`.
154+
The binary mask created by the thresholding operation can be shown with `plt.imshow`,
155+
where the `False` entries are shown as black pixels
156+
(0-valued) and the `True` entries are shown as white pixels
157+
(1-valued).
155158

156159
~~~
157160
# create a mask based on the threshold
@@ -200,8 +203,8 @@ What we are left with is only the coloured shapes from the original.
200203

201204
~~~
202205
# use the binary_mask to select the "interesting" part of the image
203-
selection = np.zeros_like(image)
204-
selection[binary_mask] = image[binary_mask]
206+
selection = image.copy()
207+
selection[~binary_mask] = 0
205208
206209
fig, ax = plt.subplots()
207210
plt.imshow(selection)
@@ -275,8 +278,8 @@ plt.show()
275278
> > And here are the commands to apply the mask and view the thresholded image
276279
> > ~~~
277280
> > image = skimage.io.imread("data/shapes-02.jpg")
278-
> > selection = np.zeros_like(image)
279-
> > selection[binary_mask] = image[binary_mask]
281+
> > selection = image.copy()
282+
> > selection[~binary_mask] = 0
280283
> >
281284
> > fig, ax = plt.subplots()
282285
> > plt.imshow(selection)
@@ -393,8 +396,8 @@ Finally, we use the mask to select the foreground:
393396
394397
~~~
395398
# apply the binary mask to select the foreground
396-
selection = np.zeros_like(image)
397-
selection[binary_mask] = image[binary_mask]
399+
selection = image.copy()
400+
selection[~binary_mask] = 0
398401

399402
fig, ax = plt.subplots()
400403
plt.imshow(selection)
@@ -625,10 +628,10 @@ data/trial-293.jpg,0.13607895611702128
625628
> > # blur before thresholding
626629
> > blurred_image = skimage.filters.gaussian(image, sigma=sigma)
627630
> >
628-
> > # perform inverse binary thresholding to mask the white label and circle
629-
> > binary_mask = blurred_image > 0.95
631+
> > # perform binary thresholding to mask the white label and circle
632+
> > binary_mask = blurred_image < 0.95
630633
> > # use the mask to remove the circle and label from the blurred image
631-
> > blurred_image[binary_mask] = 0
634+
> > blurred_image[~binary_mask] = 0
632635
> >
633636
> > # perform automatic thresholding to produce a binary image
634637
> > t = skimage.filters.threshold_otsu(blurred_image)

episodes/08-connected-components.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "Connected Component Analysis"
33
teaching: 70
4-
exercises: 45
4+
exercises: 55
55
questions:
66
- "How to extract separate objects from an image and describe these objects quantitatively."
77
objectives:
@@ -709,7 +709,7 @@ This will produce the output
709709
> {: .solution}
710710
{: .challenge}
711711
712-
> ## Colour objects by area (10 min)
712+
> ## Colour objects by area (optional, not included in timing)
713713
>
714714
> Finally, we would like to display the image with the objects coloured
715715
> according to the magnitude of their area.
@@ -742,5 +742,22 @@ This will produce the output
742742
> > {: .language-python}
743743
> >
744744
> > ![Objects colored by area](../fig/shapes-01-objects-coloured-by-area.png)
745+
> >
746+
> > > You may have noticed that in the solution, we have used the
747+
> > > `labeled_image` to index the array `object_areas`. This is an
748+
> > > example of [advanced indexing in
749+
> > > Numpy](https://numpy.org/doc/stable/user/basics.indexing.html#advanced-indexing)
750+
> > > The result is an array of the same shape as the `labeled_image`
751+
> > > whose pixel values are selected from `object_areas` according to
752+
> > > the object label. Hence the objects will be colored by area when
753+
> > > the result is displayed. Note that advanced indexing with an
754+
> > > integer array works slightly different than the indexing with a
755+
> > > Boolean array that we have used for masking. While Boolean array
756+
> > > indexing returns only the entries corresponding to the `True`
757+
> > > values of the index, integer array indexing returns an array
758+
> > > with the same shape as the index. You can read more about advanced
759+
> > > indexing in the [Numpy
760+
> > > documentation](https://numpy.org/doc/stable/user/basics.indexing.html#advanced-indexing).
761+
> > {: .callout}
745762
> {: .solution}
746763
{: .challenge}

fig/jupyter_overview.png

61.7 KB
Loading

index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ This lesson shows how to use Python and skimage to do basic image processing.
2323
> to be familiar with.
2424
{: .prereq}
2525

26+
Before following the lesson, please [make sure you have the software and data required]({{ page.root }}{% link setup.md %}).

setup.md

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,22 @@ title: Setup
44
permalink: /setup/
55
---
66

7-
## Setup instructions for the Image Processing workshop
7+
Before joining the workshop or following the lesson, please complete the data and software setup described in this page.
8+
9+
10+
## Data
11+
12+
The example images used in this lesson are available on [FigShare](https://figshare.com/).
13+
To download the data, please visit [the dataset page for this workshop][figshare-data]
14+
and click the "Download all" button.
15+
Unzip the downloaded file, and save the contents as a folder called `data` somewhere you will easily find it again,
16+
e.g. your Desktop or a folder you have created for using in this workshop.
17+
(The name `data` is optional but recommended, as this is the name we will use to refer to the folder throughout the lesson.)
18+
19+
[figshare-data]: https://figshare.com/articles/dataset/Data_Carpentry_Image_Processing_Data_beta_/19260677
20+
21+
22+
## Software
823

924
1. Download and install the latest [Anaconda
1025
distribution](https://www.anaconda.com/distribution/) for your
@@ -41,15 +56,32 @@ permalink: /setup/
4156
> package.
4257
{: .callout}
4358
44-
To test your environment, open a Jupyter notebook and copy the following lines into a cell:
59+
3. Open a Jupyter notebook:
60+
61+
> ## Instructions for Linux & Mac
62+
>
63+
> Open a terminal and type `jupyter lab`.
64+
{: .solution }
65+
66+
> ## Instructions for Windows
67+
>
68+
> Launch the Anaconda Prompt program and type `jupyter lab`.
69+
> (Running this command on the standard Command Prompt will return an error:
70+
> `'conda' is not recognized as an internal or external command, operable program or batch file.`)
71+
{: .solution }
72+
73+
After Jupyter Lab has launched, click the "Python 3" button under "Notebook" in the launcher window,
74+
or use the "File" menu, to open a new Python 3 notebook.
75+
76+
4. To test your environment, run the following lines in a cell of the notebook:
4577
~~~
4678
import skimage.io
4779
import matplotlib.pyplot as plt
4880
%matplotlib widget
49-
81+
5082
# load an image
51-
image = skimage.io.imread(fname='fig/00-colonies01.jpg')
52-
83+
image = skimage.io.imread(fname='data/colonies-01.tif')
84+
5385
# display the image
5486
fig, ax = plt.subplots()
5587
plt.imshow(image, cmap='gray')
@@ -58,8 +90,15 @@ permalink: /setup/
5890
{: .language-python}
5991
Upon execution of the cell, an image should be displayed in an interactive widget. When hovering over the image with the mouse pointer, the pixel coordinates and color values are displayed below the image.
6092
61-
3. The example image files are available through Figshare. Learners
62-
can download the images from [FIXME
63-
figshare](https://figshare.com/). We recommend to create a
64-
directory for the Jupyter notebooks/code created during the
65-
lesson. The images should be located in a subfolder named `images/`.
93+
> ## Running Cells in a Notebook
94+
>
95+
>
96+
> ![Overview of the Jupyter Notebook graphical user interface](../fig/jupyter_overview.png)
97+
> To run Python code in a Jupyter notebook cell, click on a cell in the notebook
98+
> (or add a new one by clicking the `+` button in the toolbar),
99+
> make sure that the cell type is set to "Code" (check the dropdown in the toolbar),
100+
> and add the Python code in that cell.
101+
> After you have added the code,
102+
> you can run the cell by selecting "Run" -> "Run selected cell" in the top menu,
103+
> or pressing <kbd>Shift</kbd>+<kbd>Enter</kbd>.
104+
{: .solution }

0 commit comments

Comments
 (0)