From 84d1adaade01b584292bf55121ecdfab2d25a73e Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Wed, 19 Jul 2023 21:26:02 +0200 Subject: [PATCH 1/5] use scikit-image to refer to the library --- episodes/01-introduction.md | 10 ++--- episodes/02-image-basics.md | 62 ++++++++++++++--------------- episodes/03-skimage-images.md | 30 +++++++------- episodes/04-drawing.md | 26 ++++++------ episodes/05-creating-histograms.md | 4 +- episodes/06-blurring.md | 18 ++++----- episodes/07-thresholding.md | 16 ++++---- episodes/08-connected-components.md | 14 +++---- episodes/09-challenges.md | 4 +- 9 files changed, 83 insertions(+), 101 deletions(-) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index 96146380d..c012354b3 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -84,7 +84,7 @@ shown in the morphometric example above. Why should we learn how to write a Python program to do a task we could easily perform with our own eyes? There are at least two reasons to learn how to perform tasks like these -with Python and skimage: +with Python and scikit-image: 1. What if there are many more bacteria colonies in the Petri dish? For example, suppose the image looked like this: @@ -92,13 +92,13 @@ with Python and skimage: ![](fig/colonies-03.jpg){alt='Bacteria colony'} Manually counting the colonies in that image would present more of a challenge. -A Python program using skimage could count the number of colonies more accurately, +A Python program using scikit-image could count the number of colonies more accurately, and much more quickly, than a human could. 2. What if you have hundreds, or thousands, of images to consider? Imagine having to manually count colonies on several thousand images like those above. - A Python program using skimage could move through all of the images in seconds; + A Python program using scikit-image could move through all of the images in seconds; how long would a graduate student require to do the task? Which process would be more accurate and repeatable? @@ -120,9 +120,7 @@ by learning some basics about how images are represented and stored digitally. :::::::::::::::::::::::::::::::::::::::: keypoints -- Simple Python and skimage (scikit-image) techniques can be used to solve genuine image analysis problems. +- Simple Python and scikit-image techniques can be used to solve genuine image analysis problems. - Morphometric problems involve the number, shape, and / or size of the objects in an image. :::::::::::::::::::::::::::::::::::::::::::::::::: - - diff --git a/episodes/02-image-basics.md b/episodes/02-image-basics.md index aba8162e9..aba89fca4 100644 --- a/episodes/02-image-basics.md +++ b/episodes/02-image-basics.md @@ -8,11 +8,11 @@ exercises: 5 - Define the terms bit, byte, kilobyte, megabyte, etc. - Explain how a digital image is composed of pixels. -- Recommend using imageio (resp. skimage) for I/O (resp. image processing) tasks. +- Recommend using imageio (resp. scikit-image) for I/O (resp. image processing) tasks. - Explain how images are stored in NumPy arrays. - Explain the left-hand coordinate system used in digital images. - Explain the RGB additive colour model used in digital images. -- Explain the order of the three colour values in skimage images. +- Explain the order of the three colour values in scikit-image images. - Explain the characteristics of the BMP, JPEG, and TIFF image formats. - Explain the difference between lossy and lossless compression. - Explain the advantages and disadvantages of compressed image formats. @@ -111,7 +111,7 @@ Additional functionality can be loaded as a single function or object, a module defining several of these, or a library containing many modules. You will encounter several different forms of `import` statement. -```python +```python import skimage # form 1, load whole skimage library import skimage.draw # form 2, load skimage.draw module only from skimage.draw import disk # form 3, load only the disk function @@ -122,7 +122,7 @@ import numpy as np # form 4, load all of numpy into an object called ## Further Explanation -In the example above, form 1 loads the entire `skimage` library into the +In the example above, form 1 loads the entire scikit-image library into the program as an object. Individual modules of the library are then available within that object, e.g., to access the `disk` function used in [the drawing episode](04-drawing.md), @@ -131,7 +131,7 @@ you would write `skimage.draw.disk()`. Form 2 loads only the `draw` module of `skimage` into the program. When we run the code, the program will take less time and use less memory -because we will not load the whole `skimage` library. +because we will not load the whole scikit-image library. The syntax needed to use the module remains unchanged: to access the `disk` function, we would use the same function call as given for form 1. @@ -182,7 +182,7 @@ natively (think of volumes, movies). ## Why not use `skimage.io.imread()` -The `skimage` library has its own function to read an image, +The scikit-image library has its own function to read an image, so you might be asking why we don't use it here. Actually, `skimage.io.imread()` uses `iio.imread()` internally when loading an image into Python. It is certainly something you may use as you see fit in your own code. @@ -226,7 +226,7 @@ print(eight.shape) print(eight) ``` -```output +```output (5, 3) [[0. 0. 0.] [0. 1. 0.] @@ -262,7 +262,7 @@ plt.imshow(zero) print(zero) ``` -```output +```output [[0. 0. 0.] [0. 1. 0.] [0. 1. 0.] @@ -337,7 +337,7 @@ plt.imshow(five) print(five) ``` -```output +```output [[0. 0. 0.] [0. 1. 1.] [0. 0. 0.] @@ -447,7 +447,7 @@ plt.imshow(checkerboard) print(checkerboard) ``` -```output +```output [[[116 85 57] [128 109 94] [214 44 62] @@ -658,11 +658,11 @@ There are several image formats we might encounter, and we should know the basics of at least of few of them. Some formats we might encounter, and their file extensions, are shown in this table: -| Format | Extension | +| Format | Extension | | :-------------------------------------- | :------------ | -| Device-Independent Bitmap (BMP) | .bmp | -| Joint Photographic Experts Group (JPEG) | .jpg or .jpeg | -| Tagged Image File Format (TIFF) | .tif or .tiff | +| Device-Independent Bitmap (BMP) | .bmp | +| Joint Photographic Experts Group (JPEG) | .jpg or .jpeg | +| Tagged Image File Format (TIFF) | .tif or .tiff | ## BMP @@ -742,12 +742,12 @@ The amount of memory (RAM) and drive space our computers have is quantified by terms like Megabytes (MB), Gigabytes (GB), and Terabytes (TB). The following table provides more formal definitions for these terms. -| Unit | Abbreviation | Size | +| Unit | Abbreviation | Size | | :-------------------------------------- | ------------- | :--------- | -| Kilobyte | KB | 1024 bytes | -| Megabyte | MB | 1024 KB | -| Gigabyte | GB | 1024 MB | -| Terabyte | TB | 1024 GB | +| Kilobyte | KB | 1024 bytes | +| Megabyte | MB | 1024 KB | +| Gigabyte | GB | 1024 MB | +| Terabyte | TB | 1024 GB | :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -1025,7 +1025,7 @@ metadata = iio.immeta(uri="data/eight.tif") metadata ``` -```output +```output {'is_fluoview': False, 'is_nih': False, 'is_micromanager': False, @@ -1060,23 +1060,23 @@ the metadata of your images. The following table summarises the characteristics of the BMP, JPEG, and TIFF image formats: -| Format | Compression | Metadata | Advantages | Disadvantages | +| Format | Compression | Metadata | Advantages | Disadvantages | | :-------------------------------------- | :------------ | :--------- | :--------------------- | :----------------------------------------- | -| BMP | None | None | Universally viewable, | Large file sizes | -| | | | high quality | | -| JPEG | Lossy | Yes | Universally viewable, | Detail may be lost | -| | | | smaller file size | | -| 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 | -| TIFF | None, lossy, | Yes | High quality or | Not universally viewable | -| | or lossless | | smaller file size | | +| BMP | None | None | Universally viewable, | Large file sizes | +| | | | high quality | | +| JPEG | Lossy | Yes | Universally viewable, | Detail may be lost | +| | | | smaller file size | | +| 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 | +| TIFF | None, lossy, | Yes | High quality or | Not universally viewable | +| | or lossless | | smaller file size | | :::::::::::::::::::::::::::::::::::::::: keypoints - Digital images are represented as rectangular arrays of square pixels. - Digital images use a left-hand coordinate system, with the origin in the upper left corner, the x-axis running to the right, and the y-axis running down. Some learners may prefer to think in terms of counting down rows for the y-axis and across columns for the x-axis. Thus, we will make an effort to allow for both approaches in our lesson presentation. - Most frequently, digital images use an additive RGB model, with eight bits for the red, green, and blue channels. -- skimage images are stored as multi-dimensional NumPy arrays. -- In skimage images, the red channel is specified first, then the green, then the blue, i.e., RGB. +- scikit-image images are stored as multi-dimensional NumPy arrays. +- In scikit-image images, the red channel is specified first, then the green, then the blue, i.e., RGB. - Lossless compression retains all the details in an image, but lossy compression results in loss of some of the original image detail. - BMP images are uncompressed, meaning they have high quality but also that their file sizes are large. - JPEG images use lossy compression, meaning that their file sizes are smaller, but image quality may suffer. @@ -1084,5 +1084,3 @@ image formats: - Depending on the camera or sensor, various useful pieces of information may be stored in an image file, in the image metadata. :::::::::::::::::::::::::::::::::::::::::::::::::: - - diff --git a/episodes/03-skimage-images.md b/episodes/03-skimage-images.md index 0f41c1da0..f631e4aa5 100644 --- a/episodes/03-skimage-images.md +++ b/episodes/03-skimage-images.md @@ -1,5 +1,5 @@ --- -title: Working with skimage +title: Working with scikit-image teaching: 70 exercises: 50 --- @@ -8,7 +8,7 @@ exercises: 50 - Read and save images with imageio. - Display images with matplotlib. -- Resize images with skimage. +- Resize images with scikit-image. - Perform simple image thresholding with NumPy array operations. - Extract sub-images using array slicing. @@ -16,7 +16,7 @@ exercises: 50 :::::::::::::::::::::::::::::::::::::::: questions -- How can the skimage Python computer vision library be used to work with images? +- How can the scikit-image Python computer vision library be used to work with images? :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -172,7 +172,7 @@ the dimensions we want the new image to have, `new_shape`. Note that the pixel values in the new image are an approximation of the original values and should not be confused with actual, observed -data. This is because `skimage` interpolates the pixel values when +data. This is because scikit-image interpolates the pixel values when reducing or increasing the size of an image. `skimage.transform.resize` has a number of optional parameters that allow the user to control this interpolation. You @@ -317,10 +317,10 @@ the result is an image in which the extraneous background detail has been remove It is often easier to work with grayscale images, which have a single channel, instead of colour images, which have three channels. -Skimage offers the function `skimage.color.rgb2gray()` to achieve this. +scikit-image offers the function `skimage.color.rgb2gray()` to achieve this. This function adds up the three colour channels in a way that matches human colour perception, -see [the skimage documentation for details](https://scikit-image.org/docs/dev/api/skimage.color.html#skimage.color.rgb2gray). +see [the scikit-image documentation for details](https://scikit-image.org/docs/dev/api/skimage.color.html#skimage.color.rgb2gray). It returns a grayscale image with floating point values in the range from 0 to 1. We can use the function `skimage.util.img_as_ubyte()` in order to convert it back to the original data type and the data range back 0 to 255. @@ -333,7 +333,7 @@ because using floating point numbers is numerically more stable. The Carpentries generally prefers UK English spelling, which is why we use "colour" in the explanatory text of this lesson. -However, `skimage` contains many modules and functions that include +However, scikit-image contains many modules and functions that include the US English spelling, `color`. The exact spelling matters here, e.g. you will encounter an error if you try to run `skimage.colour.rgb2gray()`. @@ -388,7 +388,7 @@ pass `plugin="pillow"`. If the backend is not specified explicitly, `iio.imread( ## Loading images with `imageio`: Pixel type and depth -When loading an image with `mode="L"`, the pixel values are stored as 8-bit integer numbers that can take values in the range 0-255. However, pixel values may also be stored with other types and ranges. For example, some `skimage` functions return the pixel values as floating point numbers in the range 0-1. The type and range of the pixel values are important for the colorscale when plotting, and for masking and thresholding images as we will see later in the lesson. If you are unsure about the type of the pixel values, you can inspect it with `print(image.dtype)`. For the example above, you should find that it is `dtype('uint8')` indicating 8-bit integer numbers. +When loading an image with `mode="L"`, the pixel values are stored as 8-bit integer numbers that can take values in the range 0-255. However, pixel values may also be stored with other types and ranges. For example, some scikit-image functions return the pixel values as floating point numbers in the range 0-1. The type and range of the pixel values are important for the colorscale when plotting, and for masking and thresholding images as we will see later in the lesson. If you are unsure about the type of the pixel values, you can inspect it with `print(image.dtype)`. For the example above, you should find that it is `dtype('uint8')` indicating 8-bit integer numbers. :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -397,7 +397,7 @@ When loading an image with `mode="L"`, the pixel values are stored as 8-bit inte ## Keeping only low intensity pixels (10 min) -A little earlier, we showed how we could use Python and skimage to turn +A little earlier, we showed how we could use Python and scikit-image to turn on only the high intensity pixels from an image, while turning all the low intensity pixels off. Now, you can practice doing the opposite - keeping all @@ -423,14 +423,14 @@ range 0-255 of an 8-bit pixel). The results should look like this: First, load the image file `data/sudoku.png` as a grayscale image. Remember that we use `image = np.array(image)` to create a copy of the image array because `imageio` returns a non-writeable image. -```python +```python sudoku = iio.imread(uri="data/sudoku.png") ``` Then change all bright pixel values greater than 192 to 192: -```python +```python sudoku = sudoku.copy() sudoku[sudoku > 125] = 125 ``` @@ -474,7 +474,7 @@ the `vmax` parameter from the sudoku challenge solution and see what happens. ## Access via slicing -As noted in the previous lesson skimage images are stored as NumPy arrays, +As noted in the previous lesson scikit-image images are stored as NumPy arrays, so we can use array slicing to select rectangular areas of an image. Then, we can save the selection as a new image, change the pixels in the image, and so on. @@ -499,7 +499,7 @@ as shown in this version of the whiteboard picture: ![](fig/board-coordinates.jpg){alt='Whiteboard coordinates'} Note that the coordinates in the preceding image are specified in *(cx, ry)* order. -Now if our entire whiteboard image is stored as an skimage image named `image`, +Now if our entire whiteboard image is stored as an scikit-image image named `image`, we can create a new image of the selected region with a statement like this: `clip = image[60:151, 135:481, :]` @@ -611,8 +611,6 @@ iio.imwrite(uri="data/clipped_maize.jpg", image=clipped_maize) - We can resize images with the `skimage.transform.resize()` function. - NumPy array commands, such as `image[image < 128] = 0`, can be used to manipulate the pixels of an image. - Array slicing can be used to extract sub-images or modify areas of images, e.g., `clip = image[60:150, 135:480, :]`. -- Metadata is not retained when images are loaded as skimage images. +- Metadata is not retained when images are loaded as scikit-image images. :::::::::::::::::::::::::::::::::::::::::::::::::: - - diff --git a/episodes/04-drawing.md b/episodes/04-drawing.md index 2b466f526..274950f46 100644 --- a/episodes/04-drawing.md +++ b/episodes/04-drawing.md @@ -6,8 +6,8 @@ exercises: 45 ::::::::::::::::::::::::::::::::::::::: objectives -- Create a blank, black skimage image. -- Draw rectangles and other shapes on skimage images. +- Create a blank, black scikit-image image. +- Draw rectangles and other shapes on scikit-image images. - Explain how a white shape on a black background can be used as a mask to select specific parts of an image. - Use bitwise operations to apply a mask to an image. @@ -15,11 +15,11 @@ exercises: 45 :::::::::::::::::::::::::::::::::::::::: questions -- How can we draw on skimage images and use bitwise operations and masks to select certain parts of an image? +- How can we draw on scikit-image images and use bitwise operations and masks to select certain parts of an image? :::::::::::::::::::::::::::::::::::::::::::::::::: -The next series of episodes covers a basic toolkit of skimage operators. +The next series of episodes covers a basic toolkit of scikit-image operators. With these tools, we will be able to create programs to perform simple analyses of images based on changes in colour or shape. @@ -44,7 +44,7 @@ from earlier in the lesson. Often we wish to select only a portion of an image to analyze, and ignore the rest. Creating a rectangular sub-image with slicing, -as we did in [the *Image Representation in skimage* episode](03-skimage-images.md) +as we did in [the *Working with scikit-image* episode](03-skimage-images.md) is one option for simple cases. Another option is to create another special image, of the same size as the original, @@ -53,7 +53,7 @@ Such an image is called a *mask*. In preparing a mask, we sometimes need to be able to draw a shape - a circle or a rectangle, say - on a black image. -skimage provides tools to do that. +scikit-image provides tools to do that. Consider this image of maize seedlings: @@ -133,12 +133,12 @@ The function returns the rectangle as row (`rr`) and column (`cc`) coordinate ar ## Check the documentation! -When using an skimage function for the first time - or the fifth time - +When using an scikit-image function for the first time - or the fifth time - it is wise to check how the function is used, via -[the skimage documentation](https://scikit-image.org/docs/dev/user_guide) +[the scikit-image documentation](https://scikit-image.org/docs/dev/user_guide) or other usage examples on programming-related sites such as [Stack Overflow](https://stackoverflow.com/). -Basic information about skimage functions can be found interactively in Python, +Basic information about scikit-image functions can be found interactively in Python, via commands like `help(skimage)` or `help(skimage.draw.rectangle)`. Take notes in your lab notebook. And, it is always wise to run some test code to verify @@ -189,8 +189,8 @@ which takes four parameters: the (ry, cx) coordinate of one end of the line, and the (ry, cx) coordinate of the other end of the line. -Other drawing functions supported by skimage can be found in -[the skimage reference pages](https://scikit-image.org/docs/dev/api/skimage.draw.html?highlight=draw#module-skimage.draw). +Other drawing functions supported by scikit-image can be found in +[the scikit-image reference pages](https://scikit-image.org/docs/dev/api/skimage.draw.html?highlight=draw#module-skimage.draw). First let's make an empty, black image with a size of 800x600 pixels. Recall that a colour image has three channels for the colours red, green, and blue @@ -575,9 +575,7 @@ plt.imshow(wellplate) :::::::::::::::::::::::::::::::::::::::: keypoints - We can use the NumPy `zeros()` function to create a blank, black image. -- We can draw on skimage images with functions such as `skimage.draw.rectangle()`, `skimage.draw.disk()`, `skimage.draw.line()`, and more. +- We can draw on scikit-image images with functions such as `skimage.draw.rectangle()`, `skimage.draw.disk()`, `skimage.draw.line()`, and more. - The drawing functions return indices to pixels that can be set directly. :::::::::::::::::::::::::::::::::::::::::::::::::: - - diff --git a/episodes/05-creating-histograms.md b/episodes/05-creating-histograms.md index 107c25843..ec7f21557 100644 --- a/episodes/05-creating-histograms.md +++ b/episodes/05-creating-histograms.md @@ -19,7 +19,7 @@ exercises: 40 :::::::::::::::::::::::::::::::::::::::::::::::::: -In this episode, we will learn how to use skimage functions to create and +In this episode, we will learn how to use scikit-image functions to create and display histograms for images. ## First, import the packages needed for this episode @@ -450,5 +450,3 @@ plt.ylabel("pixel count") - We can display histograms using the `matplotlib pyplot` `figure()`, `title()`, `xlabel()`, `ylabel()`, `xlim()`, `plot()`, and `show()` functions. :::::::::::::::::::::::::::::::::::::::::::::::::: - - diff --git a/episodes/06-blurring.md b/episodes/06-blurring.md index 9879fbc30..c757a6eb6 100644 --- a/episodes/06-blurring.md +++ b/episodes/06-blurring.md @@ -7,7 +7,7 @@ exercises: 25 ::::::::::::::::::::::::::::::::::::::: objectives - Explain why applying a low-pass blurring filter to an image is beneficial. -- Apply a Gaussian blur filter to an image using skimage. +- Apply a Gaussian blur filter to an image using scikit-image. :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -17,7 +17,7 @@ exercises: 25 :::::::::::::::::::::::::::::::::::::::::::::::::: -In this episode, we will learn how to use skimage functions to blur images. +In this episode, we will learn how to use scikit-image functions to blur images. When processing an image, we are often interested in identifying objects represented within it so that we can perform some further analysis of these @@ -181,7 +181,7 @@ next pixel in the image. ## Terminology about image boundaries Take care to avoid mixing up the term "edge" to describe the edges of objects -*within* an image and the outer boundaries of the images themselves. +*within* an image and the outer boundaries of the images themselves. Lack of a clear distinction here may be confusing for learners. ::::::::::::::::::::::::::::::::::::::::::::::::::: @@ -243,7 +243,7 @@ are missing from the kernel. A similar process would be used to fill in all of the other missing pixels from the kernel. Other *border modes* are available; you can learn more about them -in [the skimage documentation](https://scikit-image.org/docs/dev/user_guide). +in [the scikit-image documentation](https://scikit-image.org/docs/dev/user_guide). :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -252,9 +252,9 @@ order to calculate the colour channel values for the blurred image. ![](fig/blur-demo.gif){alt='Blur demo animation'} -skimage has built-in functions to perform blurring for us, so we do not have to +scikit-image has built-in functions to perform blurring for us, so we do not have to perform all of these mathematical operations ourselves. Let's work through -an example of blurring an image with the skimage Gaussian blur function. +an example of blurring an image with the scikit-image Gaussian blur function. First, import the packages needed for this episode @@ -315,7 +315,7 @@ image has three dimensions: print(image.ndim) ``` -```output +```output 3 ``` @@ -402,7 +402,7 @@ or when you want to ## Other methods of blurring -The Gaussian blur is a way to apply a low-pass filter in skimage. +The Gaussian blur is a way to apply a low-pass filter in scikit-image. It is often used to remove Gaussian (i. e., random) noise from the image. For other kinds of noise, e.g. "salt and pepper", a median filter is typically used. @@ -417,5 +417,3 @@ for a list of available filters. - Larger sigma values may remove more noise, but they will also remove detail from an image. :::::::::::::::::::::::::::::::::::::::::::::::::: - - diff --git a/episodes/07-thresholding.md b/episodes/07-thresholding.md index c3509d010..a3265e597 100644 --- a/episodes/07-thresholding.md +++ b/episodes/07-thresholding.md @@ -23,7 +23,7 @@ exercises: 50 :::::::::::::::::::::::::::::::::::::::::::::::::: -In this episode, we will learn how to use skimage functions to apply +In this episode, we will learn how to use scikit-image functions to apply thresholding to an image. Thresholding is a type of *image segmentation*, where we change the pixels of an image to make the image easier to analyze. @@ -34,10 +34,10 @@ we use thresholding as a way to select areas of interest of an image, while ignoring the parts we are not concerned with. We have already done some simple thresholding, in the "Manipulating pixels" section of -[the *Image Representation in skimage* episode](03-skimage-images.md). +[the *Working with scikit-image* episode](03-skimage-images.md). In that case, we used a simple NumPy array manipulation to separate the pixels belonging to the root system of a plant from the black background. -In this episode, we will learn how to use skimage functions to perform thresholding. +In this episode, we will learn how to use scikit-image functions to perform thresholding. Then, we will use the masks returned by these functions to select the parts of an image we are interested in. @@ -73,7 +73,7 @@ Now suppose we want to select only the shapes from the image. In other words, we want to leave the pixels belonging to the shapes "on," while turning the rest of the pixels "off," by setting their colour channel values to zeros. -The skimage library has several different methods of thresholding. +The scikit-image library has several different methods of thresholding. We will start with the simplest version, which involves an important step of human input. Specifically, in this simple, *fixed-level thresholding*, @@ -186,7 +186,7 @@ It is worth noting that the principle for simple and automatic thresholding can also be used for images with pixel ranges other than [0\.0, 1.0]. For example, we could perform thresholding on pixel intensity values in the range [0, 255] as we have already seen in -[the *Image Representation in skimage* episode](03-skimage-images.md). +[the *Working with scikit-image* episode](03-skimage-images.md). :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -313,7 +313,7 @@ thresholding, which can be done with one of the methods from Consider the image `data/maize-root-cluster.jpg` of a maize root system which we have seen before in -[the *Image Representation in skimage* episode](03-skimage-images.md). +[the *Working with scikit-image* episode](03-skimage-images.md). ```python maize_roots = iio.imread(uri="data/maize-root-cluster.jpg") @@ -350,7 +350,7 @@ The histogram has a significant peak around 0.2, and a second, smaller peak very near 1.0. Thus, this image is a good candidate for thresholding with Otsu's method. The mathematical details of how this works are complicated (see -[the skimage documentation](https://scikit-image.org/docs/dev/api/skimage.filters.html#threshold-otsu) +[the scikit-image documentation](https://scikit-image.org/docs/dev/api/skimage.filters.html#threshold-otsu) if you are interested), but the outcome is that Otsu's method finds a threshold value between the two peaks of a grayscale histogram. @@ -744,5 +744,3 @@ dish in the top right is affected by the choice of the threshold. - Thresholding can be used to create masks that select only the interesting parts of an image, or as the first step before edge detection or finding contours. :::::::::::::::::::::::::::::::::::::::::::::::::: - - diff --git a/episodes/08-connected-components.md b/episodes/08-connected-components.md index 99ca71151..8e36a4ba9 100644 --- a/episodes/08-connected-components.md +++ b/episodes/08-connected-components.md @@ -218,7 +218,7 @@ Such an image can be produced, e.g., with thresholding. Given a thresholded image, the connected component analysis produces a new *labeled* image with integer pixel values. Pixels with the same value, belong to the same object. -Skimage provides connected component analysis in the function `skimage.measure.label()`. +scikit-image provides connected component analysis in the function `skimage.measure.label()`. Let us add this function to the already familiar steps of thresholding an image. First, import the packages needed for this episode @@ -324,7 +324,7 @@ plt.axis("off"); :::::::::::::: {.empty-div style="margin-bottom: 50px"} :::::::::::::: - + :::::::::::::: solution ## Color mappings @@ -367,7 +367,7 @@ When showing this image in the viewer, it squeezes the complete range into 256 gray values. Therefore, the range of our numbers does not produce any visible change. -Fortunately, the skimage library has tools to cope with this situation. +Fortunately, the scikit-image library has tools to cope with this situation. ::::::::::::::::::::::::: @@ -487,12 +487,12 @@ Recall how we determined the root mass in [the *Thresholding* episode](07-thresholding.md) by counting the pixels in the binary mask. But here we want to calculate the area of several objects in the labeled image. -The skimage library provides the function `skimage.measure.regionprops` +The scikit-image library provides the function `skimage.measure.regionprops` to measure the properties of labeled regions. It returns a list of `RegionProperties` that describe each connected region in the images. The properties can be accessed using the attributes of the `RegionProperties` data type. Here we will use the properties `"area"` and `"label"`. -You can explore the skimage documentation to learn about other properties available. +You can explore the scikit-image documentation to learn about other properties available. We can get a list of areas of the labeled objects as follows: @@ -709,7 +709,7 @@ labeled_image, n = skimage.measure.label(object_mask, connectivity=connectivity, return_num=True) ``` -Using the `skimage` features, we can implement +Using the scikit-image features, we can implement the `enhanced_connected_component` as follows: ```python @@ -825,5 +825,3 @@ documentation](https://numpy.org/doc/stable/user/basics.indexing.html#advanced-i - We can display the labeled image to view the objects coloured by label. :::::::::::::::::::::::::::::::::::::::::::::::::: - - diff --git a/episodes/09-challenges.md b/episodes/09-challenges.md index 58c0e466d..6bedd389f 100644 --- a/episodes/09-challenges.md +++ b/episodes/09-challenges.md @@ -41,7 +41,7 @@ and `data/colonies-03.tif`. ## Morphometrics for bacterial colonies -Write a Python program that uses skimage to +Write a Python program that uses scikit-image to count the number of bacteria colonies in each image, and for each, produce a new image that highlights the colonies. The image should look similar to this one: @@ -205,5 +205,3 @@ This could be fixed with more complicated segmentation methods - These methods are useful for many scientific problems, especially those involving morphometrics. :::::::::::::::::::::::::::::::::::::::::::::::::: - - From 90cbf69a0bb46247c70f39f69fd12d858b06c05f Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Wed, 19 Jul 2023 21:26:15 +0200 Subject: [PATCH 2/5] use scikit-image to refer to the library --- learners/edge-detection.md | 26 +++++++------- learners/setup.md | 73 ++++++++++++++++++-------------------- 2 files changed, 47 insertions(+), 52 deletions(-) diff --git a/learners/edge-detection.md b/learners/edge-detection.md index 81ef3e144..9282610dd 100644 --- a/learners/edge-detection.md +++ b/learners/edge-detection.md @@ -6,8 +6,8 @@ questions: How can we automatically detect the edges of the objects in an image? objectives: - Apply Canny edge detection to an image. - Explain how we can use sliders to expedite finding appropriate parameter values - for our skimage function calls. -- Create skimage windows with sliders and associated callback functions. + for our scikit-image function calls. +- Create scikit-image windows with sliders and associated callback functions. keypoints: - The `skimage.viewer.ImageViewer` is extended using a `skimage.viewer.plugins.Plugin`. - We supply a filter function callback when creating a Plugin. @@ -15,7 +15,7 @@ keypoints: with the `skimage.viewer.widgets.slider()` function and adding them to the plugin. --- -In this episode, we will learn how to use skimage functions to apply *edge +In this episode, we will learn how to use scikit-image functions to apply *edge detection* to an image. In edge detection, we find the boundaries or edges of objects in an image, by determining where the brightness of the image changes dramatically. @@ -37,7 +37,7 @@ we can do things like counting the number of objects in the image, measure the size of the objects, classify the shapes of the objects, and so on. As was the case for blurring and thresholding, -there are several different methods in skimage that can be used for edge detection, +there are several different methods in scikit-image that can be used for edge detection, so we will examine only one in detail. ## Introduction to edge detection @@ -70,7 +70,7 @@ for forty pixels spanning the transition from black to white. ![](fig/black-and-white-gradient.png){alt='Gradient near transition'} It is obvious that the "edge" here is not so sudden! -So, any skimage method to detect edges in an image must be able to +So, any scikit-image method to detect edges in an image must be able to decide where the edge is, and place appropriately-coloured pixels in that location. ## Canny edge detection @@ -78,7 +78,7 @@ decide where the edge is, and place appropriately-coloured pixels in that locati Our edge detection method in this workshop is *Canny edge detection*, created by John Canny in 1986. This method uses a series of steps, some incorporating other types of edge detection. -The skimage `skimage.feature.canny()` function performs the following steps: +The `skimage.feature.canny()` function performs the following steps: 1. A Gaussian blur (that is characterised by the `sigma` parameter, @@ -203,11 +203,11 @@ with sigma value 2.0, low threshold value 0.1 and high threshold value 0.3: ![](fig/shapes-01-canny-edges.png){alt='Output file of Canny edge detection'} -Note that the edge output shown in an skimage window may look significantly +Note that the edge output shown in a scikit-image window may look significantly worse than the image would look if it were saved to a file due to resampling artefacts in the interactive image viewer. The image above is the edges of the junk image, saved in a PNG file. -Here is how the same image looks when displayed in an skimage output window: +Here is how the same image looks when displayed in a scikit-image output window: ![](fig/shapes-01-canny-edge-output.png){alt='Output window of Canny edge detection'} @@ -232,7 +232,7 @@ trying different threshold values and examining the resulting image, until we find a combination of parameters that works best for the image. *Or*, we can write a Python program and -create a viewer plugin that uses skimage *sliders*, +create a viewer plugin that uses scikit-image *sliders*, that allow us to vary the function parameters while the program is running. In other words, we can write a program that presents us with a window like this: @@ -297,7 +297,7 @@ canny_plugin.name = "Canny Filter Plugin" ``` We want to interactively modify the parameters of the filter function interactively. -Skimage allows us to further enrich the plugin by adding widgets, like +scikit-image allows us to further enrich the plugin by adding widgets, like `skimage.viewer.widgets.Slider`, `skimage.viewer.widgets.CheckBox`, `skimage.viewer.widgets.ComboBox`. @@ -468,13 +468,13 @@ blurring with a sigma of 1.5 and a threshold value of 0.45: Keep this plugin technique in your image processing "toolbox." You can use sliders (or other interactive elements, -see [the skimage documentation](https://scikit-image.org/docs/dev/api/skimage.viewer.widgets.html)) +see [the scikit-image documentation](https://scikit-image.org/docs/dev/api/skimage.viewer.widgets.html)) to vary other kinds of parameters, such as sigma for blurring, binary thresholding values, and so on. A few minutes developing a program to tweak parameters like this can save you the hassle of repeatedly running a program from the command line with different parameter values. -Furthermore, skimage already comes with a few viewer plugins that you can +Furthermore, scikit-image already comes with a few viewer plugins that you can check out in [the documentation](https://scikit-image.org/docs/dev/api/skimage.viewer.plugins.html). ## Other edge detection functions @@ -483,5 +483,3 @@ As with blurring, there are other options for finding edges in skimage. These include `skimage.filters.sobel()`, which you will recognise as part of the Canny method. Another choice is `skimage.filters.laplace()`. - - diff --git a/learners/setup.md b/learners/setup.md index 5869473a5..53fff0131 100644 --- a/learners/setup.md +++ b/learners/setup.md @@ -22,50 +22,50 @@ e.g. your Desktop or a folder you have created for using in this workshop. opposed to the one with Python 2). If you wish to use an existing installation, be sure to upgrade your scikit-image to at least 0.19. You can upgrade to the latest scikit-image using the shell command that follows. - + ::::::::::::::::::::::::::::::::::::::::: callout - + ## Updating scikit-image in an existing Anaconda distribution - + ```shell conda upgrade -y scikit-image ``` - + :::::::::::::::::::::::::::::::::::::::::::::::::: 2. This lesson uses Matplotlib features to display images, and some interactive features will be valuable. To enable the interactive tools in JupyterLab, the `ipympl` package is required. The package can be installed with the command - + ```shell conda install -c conda-forge ipympl ``` - + ::::::::::::::::::::::::::::::::::::::::: callout - + ## Enabling the `ipympl` backend in Jupyter notebooks - + The `ipympl` backend can be enabled with the `%matplotlib` Jupyter magic. Put the following command in a cell in your notebooks (e.g., at the top) and execute the cell before any plotting commands. - + ```python %matplotlib widget ``` - + :::::::::::::::::::::::::::::::::::::::::::::::::: - + ::::::::::::::::::::::::::::::::::::::::: callout - + ## Older JupyterLab versions - + If you are using an older version of JupyterLab, you may also need to install the labextensions manually, as explained in the [README file](https://github.com/matplotlib/ipympl#readme) for the `ipympl` package. - - + + :::::::::::::::::::::::::::::::::::::::::::::::::: 3. Open a Jupyter notebook: @@ -75,58 +75,58 @@ e.g. your Desktop or a folder you have created for using in this workshop. :::::::::::::: :::::::::::::: solution - + ## Instructions for Linux \& Mac - + Open a terminal and type `jupyter lab`. - - + + ::::::::::::::::::::::::: - + :::::::::::::: solution - + ## Instructions for Windows - + Launch the Anaconda Prompt program and type `jupyter lab`. (Running this command on the standard Command Prompt will return an error: `'conda' is not recognized as an internal or external command, operable program or batch file.`) - - + + ::::::::::::::::::::::::: - + After Jupyter Lab has launched, click the "Python 3" button under "Notebook" in the launcher window, or use the "File" menu, to open a new Python 3 notebook. 4. To test your environment, run the following lines in a cell of the notebook: - + ```python import imageio.v3 as iio from skimage import transform import matplotlib.pyplot as plt %matplotlib widget - + # load an image image = iio.imread(uri='data/colonies-01.tif') - + # rotate it by 45 degrees rotated = transform.rotate(image=image, angle=45) - + # display the original image and its rotated version side by side fig, ax = plt.subplots(1, 2) ax[0].imshow(image) ax[1].imshow(rotated) ``` - + Upon execution of the cell, a figure with two images should be displayed in an interactive widget. When hovering over the images with the mouse pointer, the pixel coordinates and colour values are displayed below the image. - + :::::::::::::: {.empty-div style="margin-bottom: 50px"} :::::::::::::: :::::::::::::: solution - + ## Running Cells in a Notebook - + ![](fig/jupyter_overview.png){alt='Overview of the Jupyter Notebook graphical user interface'} To run Python code in a Jupyter notebook cell, click on a cell in the notebook (or add a new one by clicking the `+` button in the toolbar), @@ -135,11 +135,8 @@ e.g. your Desktop or a folder you have created for using in this workshop. After you have added the code, you can run the cell by selecting "Run" -> "Run selected cell" in the top menu, or pressing Shift\+Enter. - - - ::::::::::::::::::::::::: - -[figshare-data]: https://figshare.com/articles/dataset/Data_Carpentry_Image_Processing_Data_beta_/19260677 + ::::::::::::::::::::::::: +[figshare-data]: https://figshare.com/articles/dataset/Data_Carpentry_Image_Processing_Data_beta_/19260677 From 196e9b784926135de9672fbbe3b5541cb984daef Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Wed, 19 Jul 2023 21:29:29 +0200 Subject: [PATCH 3/5] use Matplotlib to refer to the library --- episodes/03-skimage-images.md | 10 +++++----- episodes/05-creating-histograms.md | 4 ++-- learners/discuss.md | 4 +--- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/episodes/03-skimage-images.md b/episodes/03-skimage-images.md index f631e4aa5..7b75015ac 100644 --- a/episodes/03-skimage-images.md +++ b/episodes/03-skimage-images.md @@ -7,7 +7,7 @@ exercises: 50 ::::::::::::::::::::::::::::::::::::::: objectives - Read and save images with imageio. -- Display images with matplotlib. +- Display images with Matplotlib. - Resize images with scikit-image. - Perform simple image thresholding with NumPy array operations. - Extract sub-images using array slicing. @@ -452,14 +452,14 @@ plt.imshow(sudoku, cmap="gray", vmin=0, vmax=1) Compared to a colour image, a grayscale image contains only a single intensity value per pixel. When we plot such an image with `plt.imshow`, -matplotlib uses a colour map, to assign each intensity value a colour. +Matplotlib uses a colour map, to assign each intensity value a colour. The default colour map is called "viridis" and maps low values to purple -and high values to yellow. We can instruct matplotlib to map low values +and high values to yellow. We can instruct Matplotlib to map low values to black and high values to white instead, by calling `plt.imshow` with `cmap="gray"`. [The documentation contains an overview of pre-defined colour maps](https://matplotlib.org/stable/gallery/color/colormap_reference.html). -Furthermore, matplotlib determines the minimum and maximum values of +Furthermore, Matplotlib determines the minimum and maximum values of the colour map dynamically from the image, by default. That means that in an image where the minimum is 64 and the maximum is 192, those values will be mapped to black and white respectively (and not dark gray and light @@ -606,7 +606,7 @@ iio.imwrite(uri="data/clipped_maize.jpg", image=clipped_maize) :::::::::::::::::::::::::::::::::::::::: keypoints - Images are read from disk with the `iio.imread()` function. -- We create a window that automatically scales the displayed image with matplotlib and calling `show()` on the global figure object. +- We create a window that automatically scales the displayed image with Matplotlib and calling `show()` on the global figure object. - Colour images can be transformed to grayscale using `skimage.color.rgb2gray()` or, in many cases, be read as grayscale directly by passing the argument `mode="L"` to `iio.imread()`. - We can resize images with the `skimage.transform.resize()` function. - NumPy array commands, such as `image[image < 128] = 0`, can be used to manipulate the pixels of an image. diff --git a/episodes/05-creating-histograms.md b/episodes/05-creating-histograms.md index ec7f21557..e2a25b2c4 100644 --- a/episodes/05-creating-histograms.md +++ b/episodes/05-creating-histograms.md @@ -108,7 +108,7 @@ For the last bin, the array also has to contain the stop, so it has one more element, than the histogram. Next, we turn our attention to displaying the histogram, -by taking advantage of the plotting facilities of the `matplotlib` library. +by taking advantage of the plotting facilities of the Matplotlib library. ```python # configure and draw the histogram figure @@ -155,7 +155,7 @@ it produces this histogram: ::::::::::::::::::::::::::::::::::::::::: callout -## Histograms in matplotlib +## Histograms in Matplotlib Matplotlib provides a dedicated function to compute and display histograms: `plt.hist()`. diff --git a/learners/discuss.md b/learners/discuss.md index c4e82490e..fbfd8b030 100644 --- a/learners/discuss.md +++ b/learners/discuss.md @@ -28,7 +28,7 @@ instructions, and the backend can be enabled using the `%matplotlib widget` magi The maintainers discussed the possibility of using [napari](https://napari.org/) as an image viewer in the lesson, acknowledging its growing popularity -and some of the advantages it holds over the `matplotlib`\-based +and some of the advantages it holds over the Matplotlib-based approach, especially for working with image data in more than two dimensions. However, at the time of discussion, napari was still in an alpha state of development, and could not be relied on for easy and @@ -38,5 +38,3 @@ well-suited to use in an official Data Carpentry curriculum. The lesson Maintainers and/or Curriculum Advisory Committee (when it exists) will monitor the progress of napari and other image viewers, and may opt to adopt a new platform in future. - - From b1c0261a03c605a909d0eebb5e94e654cf05a318 Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Wed, 19 Jul 2023 21:34:00 +0200 Subject: [PATCH 4/5] use NumPy to refer to the library --- episodes/02-image-basics.md | 8 ++++---- episodes/04-drawing.md | 2 +- episodes/05-creating-histograms.md | 2 +- episodes/07-thresholding.md | 10 +++++----- episodes/08-connected-components.md | 20 ++++++++++---------- learners/prereqs.md | 6 ++---- 6 files changed, 23 insertions(+), 25 deletions(-) diff --git a/episodes/02-image-basics.md b/episodes/02-image-basics.md index aba89fca4..639bd09fe 100644 --- a/episodes/02-image-basics.md +++ b/episodes/02-image-basics.md @@ -72,7 +72,7 @@ The **matrix** is mathematical concept - numbers evenly arranged in a rectangle. like the shape of the screen you're looking at now. Or it could be a three dimensional equivalent, a cuboid, or have even more dimensions, but always keeping the evenly spaced arrangement of numbers. In computing, **array** refers to a structure in the computer's memory where data is stored in evenly-spaced **elements**. This is strongly analogous -to a matrix. A `numpy` array is a **type** of variable (a simpler example of a type is an integer). For our purposes, +to a matrix. A NumPy array is a **type** of variable (a simpler example of a type is an integer). For our purposes, the distinction between matrices and arrays is not important, we don't really care how the computer arranges our data in its memory. The important thing is that the computer stores values describing the pixels in images, as arrays. And the terms matrix and array can be used interchangeably. @@ -237,8 +237,8 @@ print(eight) Thus if we have tools that will allow us to manipulate these arrays of numbers, we can manipulate the image. -The `numpy` library can be particularly useful here, -so let's try that out using `numpy` array slicing. +The NumPy library can be particularly useful here, +so let's try that out using NumPy array slicing. Notice that the default behavior of the `imshow` function appended row and column numbers that will be helpful to us as we try to address individual or groups of pixels. @@ -433,7 +433,7 @@ key to certain techniques explored in later chapters of this lesson. To get started let's see an example of how different dimensions of information combine to produce a set of pixels using a 4 X 4 matrix with 3 dimensions for the colours red, green, and blue. -Rather than loading it from a file, we will generate this example using numpy. +Rather than loading it from a file, we will generate this example using NumPy. ```python # set the random seed so we all get the same matrix diff --git a/episodes/04-drawing.md b/episodes/04-drawing.md index 274950f46..3d5f9444f 100644 --- a/episodes/04-drawing.md +++ b/episodes/04-drawing.md @@ -363,7 +363,7 @@ rr, cc = skimage.draw.rectangle(start=(357, 44), end=(740, 720)) mask[rr, cc] = False ``` -Then, we use numpy indexing to remove the portions of the image, +Then, we use NumPy indexing to remove the portions of the image, where the mask is `True`: ```python diff --git a/episodes/05-creating-histograms.md b/episodes/05-creating-histograms.md index e2a25b2c4..604d8fa22 100644 --- a/episodes/05-creating-histograms.md +++ b/episodes/05-creating-histograms.md @@ -167,7 +167,7 @@ Here, you could use it by calling `plt.hist(image.flatten(), bins=256, range=(0, 1))` instead of `np.histogram()` and `plt.plot()` -(`*.flatten()` is a numpy function that converts our two-dimensional +(`*.flatten()` is a NumPy function that converts our two-dimensional image into a one-dimensional array). :::::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/episodes/07-thresholding.md b/episodes/07-thresholding.md index a3265e597..86037c6d0 100644 --- a/episodes/07-thresholding.md +++ b/episodes/07-thresholding.md @@ -9,7 +9,7 @@ exercises: 50 - Explain what thresholding is and how it can be used. - Use histograms to determine appropriate threshold values to use for the thresholding process. - Apply simple, fixed-level binary thresholding to an image. -- Explain the difference between using the operator `>` or the operator `<` to threshold an image represented by a numpy array. +- Explain the difference between using the operator `>` or the operator `<` to threshold an image represented by a NumPy array. - Describe the shape of a binary image produced by thresholding via `>` or `<`. - Explain when Otsu's method for automatic thresholding is appropriate. - Apply automatic thresholding to an image using Otsu's method. @@ -138,7 +138,7 @@ turn pixels above that value "off". Let us choose `t=0.8`. To apply the threshold `t`, -we can use the numpy comparison operators to create a mask. +we can use the NumPy comparison operators to create a mask. Here, we want to turn "on" all pixels which have values smaller than the threshold, so we use the less operator `<` to compare the `blurred_image` to the threshold `t`. The operator returns a mask, that we capture in the variable `binary_mask`. @@ -357,7 +357,7 @@ the two peaks of a grayscale histogram. The `skimage.filters.threshold_otsu()` function can be used to determine the threshold automatically via Otsu's method. -Then numpy comparison operators can be used to apply it as before. +Then NumPy comparison operators can be used to apply it as before. Here are the Python commands to determine the threshold `t` with Otsu's method. ```python @@ -482,10 +482,10 @@ The final part of the function determines the root mass ratio in the image. Recall that in the `binary_mask`, every pixel has either a value of zero (black/background) or one (white/foreground). We want to count the number of white pixels, -which can be accomplished with a call to the numpy function `np.count_nonzero`. +which can be accomplished with a call to the NumPy function `np.count_nonzero`. Then we determine the width and height of the image by using the elements of `binary_mask.shape` -(that is, the dimensions of the numpy array that stores the image). +(that is, the dimensions of the NumPy array that stores the image). Finally, the density ratio is calculated by dividing the number of white pixels by the total number of pixels `w*h` in the image. The function returns then root density of the image. diff --git a/episodes/08-connected-components.md b/episodes/08-connected-components.md index 8e36a4ba9..fb5ea8fd8 100644 --- a/episodes/08-connected-components.md +++ b/episodes/08-connected-components.md @@ -425,7 +425,7 @@ the first object gets the value `1`, the second object the value `2`, and so on. This means that by finding the object with the maximum value, we also know how many objects there are in the image. -We can thus use the `np.max` function from Numpy to +We can thus use the `np.max` function from NumPy to find the maximum value that equals the number of found objects: ```python @@ -594,7 +594,7 @@ for objf in object_features: print("Found", len(large_objects), "objects!") ``` -Another option is to use Numpy arrays to create the list of large objects. +Another option is to use NumPy arrays to create the list of large objects. We first create an array `object_areas` containing the object areas, and an array `object_labels` containing the object labels. The labels of the objects are also returned by `skimage.measure.regionprops`. @@ -611,11 +611,11 @@ large_objects = object_labels[object_areas > min_area] print("Found", len(large_objects), "objects!") ``` -The advantage of using Numpy arrays is that +The advantage of using NumPy arrays is that `for` loops and `if` statements in Python can be slow, and in practice the first approach may not be feasible if the image contains a large number of objects. -In that case, Numpy array functions turn out to be very useful because +In that case, NumPy array functions turn out to be very useful because they are much faster. In this example, we can also use the `np.count_nonzero` function @@ -638,9 +638,9 @@ expected count of 7 objects. ::::::::::::::::::::::::::::::::::::::::: callout -## Using functions from Numpy and other Python packages +## Using functions from NumPy and other Python packages -Functions from Python packages such as Numpy are often more efficient and +Functions from Python packages such as NumPy are often more efficient and require less code to write. It is a good idea to browse the reference pages of `numpy` and `skimage` to look for an availabe function that can solve a given task. @@ -675,11 +675,11 @@ for object_id, objf in enumerate(object_features, start=1): labeled_image[labeled_image == objf["label"]] = 0 ``` -Here Numpy functions can also be used to eliminate +Here NumPy functions can also be used to eliminate `for` loops and `if` statements. Like above, we can create an array of the small object labels with the comparison `object_areas < min_area`. -We can use another Numpy function, `np.isin`, +We can use another NumPy function, `np.isin`, to set the pixels of all small objects to 0. `np.isin` takes two arrays and returns a boolean array with values `True` if the entry of the first array is found in the second array, @@ -795,7 +795,7 @@ plt.axis("off"); You may have noticed that in the solution, we have used the `labeled_image` to index the array `object_areas`. This is an example of [advanced indexing in -Numpy](https://numpy.org/doc/stable/user/basics.indexing.html#advanced-indexing) +NumPy](https://numpy.org/doc/stable/user/basics.indexing.html#advanced-indexing) The result is an array of the same shape as the `labeled_image` whose pixel values are selected from `object_areas` according to the object label. Hence the objects will be colored by area when @@ -805,7 +805,7 @@ Boolean array that we have used for masking. While Boolean array indexing returns only the entries corresponding to the `True` values of the index, integer array indexing returns an array with the same shape as the index. You can read more about advanced -indexing in the [Numpy +indexing in the [NumPy documentation](https://numpy.org/doc/stable/user/basics.indexing.html#advanced-indexing). diff --git a/learners/prereqs.md b/learners/prereqs.md index a8e190f31..1a5043d86 100644 --- a/learners/prereqs.md +++ b/learners/prereqs.md @@ -35,7 +35,7 @@ Be able to: - Perform basic arithmetic operations (e.g. addition, subtraction) on variables. - Convert strings to ints or floats where appropriate. - Create a `list` and alter lists by appending, inserting, or removing values. -- Use indexing and slicing to access elements of strings, lists, and Numpy arrays. +- Use indexing and slicing to access elements of strings, lists, and NumPy arrays. - Use good coding practices to comment your code and choose appropriate variable names. - Write a `for` loop that increments a variable. - Write conditional statements using `if`, `elif`, and `else`. @@ -46,10 +46,8 @@ Be able to: The following skills are useful, but not required: -- Apply a function to an entire Numpy array or to a single array axis. +- Apply a function to an entire NumPy array or to a single array axis. - Write a user-defined function. If you are signed up, or considering signing up for a workshop, and aren't sure whether you meet these reqirements, please get in touch with the workshop instructors or host. - - From e3eee95476c77cbb730cd79f13e1483ee995d6fb Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Wed, 19 Jul 2023 21:35:21 +0200 Subject: [PATCH 5/5] use scikit-image as library name on landing pages --- README.md | 2 -- index.md | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 457c744da..faba46dd1 100644 --- a/README.md +++ b/README.md @@ -32,5 +32,3 @@ The Image Processing with Python lesson is currently being maintained by: - [Toby Hodges](https://github.com/tobyhodges) The lesson is built on content originally developed by [Mark Meysenburg](https://github.com/mmeysenburg), [Tessa Durham Brooks](https://github.com/tessalea), [Dominik Kutra](https://github.com/k-dominik), [Constantin Pape](https://github.com/constantinpape), and [Erin Becker](https://github.com/ebecker). - - diff --git a/index.md b/index.md index 64d301123..b7a9af673 100644 --- a/index.md +++ b/index.md @@ -2,7 +2,7 @@ site: sandpaper::sandpaper_site --- -This lesson shows how to use Python and skimage to do basic image processing. +This lesson shows how to use Python and scikit-image to do basic image processing. :::::::::::::::::::::::::::::::::::::::::: prereq @@ -22,5 +22,3 @@ to be familiar with. :::::::::::::::::::::::::::::::::::::::::::::::::: Before following the lesson, please [make sure you have the software and data required](learners/setup.md). - -