diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c46743eb..0a0a4f54 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,6 +14,10 @@ your change proposal as promptly as we can, and help you become a member of our community. Everyone involved in [The Carpentries][cp-site] agrees to abide by our [code of conduct](CODE_OF_CONDUCT.md). +### Who Should Contribute? + +Contributions to this lesson are welcome from anyone with an interest in the project. + ### How to Contribute The easiest way to get started is to file an issue to tell us about a spelling @@ -43,7 +47,7 @@ documentation][template-doc]. to [The Workbench documentation][template-doc]. -### What to Contribute +### What to Contribute (General) There are many ways to contribute, from writing new exercises and improving existing ones to updating or filling in the documentation and submitting [bug @@ -58,7 +62,66 @@ are particularly valuable**: it's easy for people who have been using these lessons for a while to forget how impenetrable some of this material can be, so fresh eyes are always welcome. -### What *Not* to Contribute +### What to Contribute (This Lesson) + +Any contributions are welcome, particularly ideas for how the existing content could be +improved or updated, and/or errors that need to be corrected. Comments on existing issues +and reviews of pull requests are similarly welcome. + +If you plan to submit a pull request, please open an issue +(or comment on an existing thread) first to ensure that effort is not duplicated +or spent making a change that will not be accepted by the Maintainers. + +#### Content / style guidelines + +- If you add an image / figure that was generated from Python code, please include this + code in your PR under `episodes/fig/source`. + +- If you add a new image or figure, verify that it displays correctly in the lesson’s dark mode. A color-inversion filter is applied [by Varnish to all images by default in dark mode](https://github.com/carpentries/varnish/issues/181), which may cause some images to appear incorrectly or become unreadable. If your image is affected, include an additional version of the same image with a `-dark` suffix in its filename. + +- Use the terms in the table below, when referring to Python libraries within the lesson. + The table gives two terms for each library: `Term for descriptive text` which should be + used when discussing the library in plain English / full sentences and `Term for code` + which should be used when referring to code (and within code). + + | Python library | Term for descriptive text | Term for code | + | :------------- | :------------- | :------------- | + | [scikit-image](https://scikit-image.org/) | scikit-image | `skimage` | + | [NumPy](https://numpy.org/) | NumPy | `numpy` | + | [Matplotlib](https://matplotlib.org/) | Matplotlib | `matplotlib` | + | [imageio](https://imageio.readthedocs.io/en/stable/index.html) | imageio | `imageio` | + + +- When importing scikit-image use: + ```python + import skimage as ski + ``` + Therefore, to access specific functions, you need to use their submodule name. For example: + + ```python + import skimage as ski + + rr, cc = ski.draw.rectangle(start=(357, 44), end=(740, 720)) + ``` + +- For reading and writing images, use the [imageio](https://imageio.readthedocs.io/en/stable/index.html) + library and avoid use of `skimage.io`. For example: + ```python + import imageio.v3 as iio + + chair = iio.imread(uri="data/chair.jpg") # read an image + iio.imwrite(uri="data/chair.tif", image=chair) # write an image + ``` + +- Comments providing an overall description of a code snippet should use triple quotes `"""`, e.g., + ```python + """Python script to load a colour image in grayscale""" + + chair = iio.imread(uri="data/chair.jpg") + gray_chair = ski.color.rgb2gray(chair) + ``` + +### What *Not* to Contribute (General) Our lessons already contain more material than we can cover in a typical workshop, so we are usually *not* looking for more concepts or tools to add to @@ -72,6 +135,23 @@ platform. Our workshops typically contain a mixture of Windows, macOS, and Linux users; in order to be usable, our lessons must run equally well on all three. +### What *Not* to Contribute (This Lesson) + +Although most contributions will be welcome at this stage of the curriculum's development, +the time available to deliver the content in a training event is strictly limited +and needs to be accounted for when considering the addition of any new content. +If you want to suggest the addition of new content, especially whole new sections or episodes, +please open an issue to discuss this with the Maintainers first and provide the following +information alongside a summary of the content to be added: + +1. A suggested location for the new content. +2. An estimate of how much time you estimate the new content would require in training + (teaching + exercises). +3. The [learning objective(s)][cldt-lo] of this new content. +4. (optional, but strongly preferred) + A suggestion of which of the currently-used learning objectives could be + removed from the curriculum to make space for the new content. + ### Using GitHub If you choose to contribute via GitHub, you may want to look at [How to @@ -92,6 +172,14 @@ Each lesson has a team of maintainers who review issues and pull requests or encourage others to do so. The maintainers are community volunteers, and have final say over what gets merged into the lesson. +#### Merging Policy + +Pull requests made to the default branch of this repository +(from which the lesson site is built) +can only be merged after at least one approving review from a Maintainer. +Any Maintainer can merge a pull request that has received at least one approval, +but they may prefer to wait for further input from others before merging. + ### Other Resources The Carpentries is a global organisation with volunteers and learners all over @@ -102,6 +190,7 @@ media, slack, newsletters, and email lists. You can also [reach us by email][contact]. [repo]: https://github.com/datacarpentry/image-processing +[cldt-lo]: https://carpentries.github.io/lesson-development-training/05-objectives.html#learning-objectives [contact]: mailto:team@carpentries.org [cp-site]: https://carpentries.org/ [dc-issues]: https://github.com/issues?q=user%3Adatacarpentry diff --git a/README.md b/README.md index 46a1fae0..2fb0fd12 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,10 @@ The original ideas and discussions in our first in-person workshop has been arch Make a suggestion or correct an error by [raising an Issue](https://github.com/carpentries-incubator/bioimage-analysis-python/issues). +Please see the [CONTRIBUTING.md file](CONTRIBUTING.md) for contributing guidelines and details on how to get involved with +this project. Some specific guidelines for content / style are provided in the +['What to Contribute (This Lesson)' section](CONTRIBUTING.md#what-to-contribute-this-lesson). + ## Code of Conduct All participants should agree to abide by the [The Carpentries Code of Conduct](https://carpentrieshandbook.readthedocs.io/en/latest/topic_folders/policies/code-of-conduct.html). diff --git a/config.yaml b/config.yaml index bc742c9d..31349a66 100644 --- a/config.yaml +++ b/config.yaml @@ -71,7 +71,12 @@ episodes: - 10-challenges.md # Information for Learners -learners: +learners: +- prereqs.md +- discuss.md +- reference.md +- further-reading.md +- edge-detection.md # Information for Instructors instructors: diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index 70a3c4cc..5851794b 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -114,7 +114,7 @@ As we move through this workshop, we will learn image analysis methods useful for many different scientific problems. These will be linked together and applied to a real problem in the final end-of-workshop -[capstone challenge](09-challenges.md). +[capstone challenge](10-challenges.md). Let's get started, by learning some basics about how images are represented and stored digitally. diff --git a/episodes/03-reading-images.md b/episodes/03-reading-images.md index 81b9031d..be73be20 100644 --- a/episodes/03-reading-images.md +++ b/episodes/03-reading-images.md @@ -240,14 +240,14 @@ Suppose we are interested in this maize root cluster image. We want to be able to focus our program's attention on the roots themselves, while ignoring the black background. -![](data/maize-root-cluster.jpg){alt='Root cluster image'} +![](fig/maize-root-cluster.jpg){alt='Root cluster image'} Since the image is stored as an array of numbers, we can simply look through the array for pixel colour values that are less than some threshold value. This process is called *thresholding*, and we will see more powerful methods to perform the thresholding task in -[the *Thresholding* episode](07-thresholding.md). +[the *Thresholding* episode](06-processing-segmentation.md). Here, though, we will look at a simple and elegant NumPy method for thresholding. Let us develop a program that keeps only the pixel colour values in an image that have value greater than or equal to 128. @@ -379,7 +379,7 @@ the low intensity pixels while changing the high intensity ones. The file `data/sudoku.png` is an RGB image of a sudoku puzzle: -![](data/sudoku.png){alt='Su-Do-Ku puzzle'} +![](fig/sudoku.png){alt='Su-Do-Ku puzzle'} Your task is to load the image in grayscale format and turn all of the bright pixels in the image to a @@ -465,7 +465,7 @@ Consider this image of a whiteboard, and suppose that we want to create a sub-image with just the portion that says "odd + even = odd," along with the red box that is drawn around the words. -![](data/board.jpg){alt='Whiteboard image'} +![](fig/board.jpg){alt='Whiteboard image'} Using `matplotlib.pyplot.imshow` we can determine the coordinates of the corners of the area we wish to extract diff --git a/episodes/04-drawing.md b/episodes/04-drawing.md index a5c4eebc..ae1c4446 100644 --- a/episodes/04-drawing.md +++ b/episodes/04-drawing.md @@ -393,7 +393,7 @@ Copy that image to your computer, write some code to make a mask, and apply it to select the part of the image containing your object. For example, here is an image of a remote control: -![](data/remote-control.jpg){alt='Remote control image'} +![](fig/remote-control.jpg){alt='Remote control image'} And, here is the end result of a program masking out everything but the remote: @@ -446,7 +446,7 @@ fig, ax = plt.subplots() ax.imshow(wellplate) ``` -![](data/wellplate-01.jpg){alt='96-well plate'} +![](fig/wellplate-01.jpg){alt='96-well plate'} Suppose that we are interested in the colours of the solutions in each of the wells. We *do not* care about the colour of the rest of the image, diff --git a/episodes/05-creating-histograms.md b/episodes/05-creating-histograms.md index d0e1e259..9d68c5b6 100644 --- a/episodes/05-creating-histograms.md +++ b/episodes/05-creating-histograms.md @@ -52,7 +52,7 @@ and histograms are also quite handy as a preparatory step before performing We will start with grayscale images, and then move on to colour images. We will use this image of a plant seedling as an example: -![](data/plant-seedling.jpg){alt='Plant seedling'} +![](fig/plant-seedling.jpg){alt='Plant seedling'} Here we load the image in grayscale instead of full colour, and display it: diff --git a/episodes/06-blurring.md b/episodes/06-blurring.md index beaeef21..6aec0815 100644 --- a/episodes/06-blurring.md +++ b/episodes/06-blurring.md @@ -276,7 +276,7 @@ fig, ax = plt.subplots() ax.imshow(image) ``` -![](data/gaussian-original.png){alt='Original image'} +![](fig/gaussian-original.png){alt='Original image'} Next, we apply the gaussian blur: @@ -331,8 +331,8 @@ ax.imshow(blurred) ## Visualising Blurring -Somebody said once "an image is worth a thousand words". -What is actually happening to the image pixels when we apply blurring may be +Somebody said once "an image is worth a thousand words". +What is actually happening to the image pixels when we apply blurring may be difficult to grasp. Let's now visualise the effects of blurring from a different perspective. @@ -430,18 +430,18 @@ but can be viewed by following the links in the captions. ![ -A 3D plot of pixel intensities across the whole Petri dish image before blurring. -[Explore how this plot was created with matplotlib](https://gist.github.com/chbrandt/63ba38142630a0586ba2a13eabedf94b). +A 3D plot of pixel intensities across the whole Petri dish image before blurring. +[Explore how this plot was created with matplotlib](https://gist.github.com/chbrandt/63ba38142630a0586ba2a13eabedf94b). Image credit: [Carlos H Brandt](https://github.com/chbrandt/). ](fig/3D_petri_before_blurring.png){ alt='3D surface plot showing pixel intensities across the whole example Petri dish image before blurring' } ![ -A 3D plot of pixel intensities after Gaussian blurring of the Petri dish image. -Note the 'smoothing' effect on the pixel intensities of the colonies in the image, -and the 'flattening' of the background noise at relatively low pixel intensities throughout the image. -[Explore how this plot was created with matplotlib](https://gist.github.com/chbrandt/63ba38142630a0586ba2a13eabedf94b). +A 3D plot of pixel intensities after Gaussian blurring of the Petri dish image. +Note the 'smoothing' effect on the pixel intensities of the colonies in the image, +and the 'flattening' of the background noise at relatively low pixel intensities throughout the image. +[Explore how this plot was created with matplotlib](https://gist.github.com/chbrandt/63ba38142630a0586ba2a13eabedf94b). Image credit: [Carlos H Brandt](https://github.com/chbrandt/). ](fig/3D_petri_after_blurring.png){ alt='3D surface plot illustrating the smoothing effect on pixel intensities across the whole example Petri dish image after blurring' diff --git a/episodes/06-processing-segmentation.md b/episodes/06-processing-segmentation.md index a2c92a07..88f3727a 100644 --- a/episodes/06-processing-segmentation.md +++ b/episodes/06-processing-segmentation.md @@ -34,7 +34,7 @@ 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 *Working with scikit-image* episode](03-skimage-images.md). +[the *Working with scikit-image* episode](03-reading-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 scikit-image functions to perform thresholding. @@ -68,7 +68,7 @@ fig, ax = plt.subplots() ax.imshow(shapes01) ``` -![](data/shapes-01.jpg){alt='Image with geometric shapes on white background' .image-with-shadow} +![](fig/shapes-01.jpg){alt='Image with geometric shapes on white background' .image-with-shadow} 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," @@ -187,7 +187,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 *Working with scikit-image* episode](03-skimage-images.md). +[the *Working with scikit-image* episode](03-reading-images.md). :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -214,7 +214,7 @@ ax.imshow(selection) Now, it is your turn to practice. Suppose we want to use simple thresholding to select only the coloured shapes (in this particular case we consider grayish to be a colour, too) from the image `data/shapes-02.jpg`: -![](data/shapes-02.jpg){alt='Another image with geometric shapes on white background'} +![](fig/shapes-02.jpg){alt='Another image with geometric shapes on white background'} First, plot the grayscale histogram as in the [Creating Histogram](05-creating-histograms.md) episode and @@ -315,7 +315,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 *Working with scikit-image* episode](03-skimage-images.md). +[the *Working with scikit-image* episode](03-reading-images.md). ```python maize_roots = iio.imread(uri="data/maize-root-cluster.jpg") @@ -324,7 +324,7 @@ fig, ax = plt.subplots() ax.imshow(maize_roots) ``` -![](data/maize-root-cluster.jpg){alt='Image of a maize root'} +![](fig/maize-root-cluster.jpg){alt='Image of a maize root'} We use Gaussian blur with a sigma of 1.0 to denoise the root image. Let us look at the grayscale histogram of the denoised image. @@ -383,7 +383,7 @@ print("Found automatic threshold t = {}.".format(t)) ``` ```output -Found automatic threshold t = 0.4172454549881862. +Found automatic threshold t = 0.4116003928683858. ``` For this root image and a Gaussian blur with the chosen sigma of 1.0, @@ -512,7 +512,7 @@ measure_root_mass(filename="data/trial-016.jpg", sigma=1.5) ``` ```output -0.0482436835106383` +0.04907247340425532 ``` Now we can use the function to process the series of four images shown above. @@ -525,7 +525,7 @@ and the filenames all start with the **trial-** prefix and end with the **.jpg** suffix. ```python -all_files = glob.glob("data/trial-*.jpg") +all_files = sorted(glob.glob("data/trial-*.jpg")) for filename in all_files: density = measure_root_mass(filename=filename, sigma=1.5) # output in format suitable for .csv @@ -533,12 +533,20 @@ for filename in all_files: ``` ```output -data/trial-016.jpg,0.0482436835106383 -data/trial-020.jpg,0.06346941489361702 -data/trial-216.jpg,0.14073969414893617 -data/trial-293.jpg,0.13607895611702128 +data/trial-016.jpg,0.04907247340425532 +data/trial-020.jpg,0.06381366356382978 +data/trial-216.jpg,0.14205152925531914 +data/trial-293.jpg,0.13665791223404256 ``` +::::::::::::::::::::::::::::::::::::::::: callout + +Compare your results with the values above. Do they match exactly? You may find that certain decimal values differ slightly, even when using identical input parameters. + +This variation often stems from the specific versions of your installed packages (such as `numpy` or `scikit-image`). As these libraries evolve, updates can introduce subtle changes in numerical handling, underlying algorithms, or rounding logic. This highlights why reproducible environments, as well as reproducible code, are essential for consistent scientific computing. + +::::::::::::::::::::::::::::::::::::::::: + ::::::::::::::::::::::::::::::::::::::: challenge ## Ignoring more of the images -- brainstorming (10 min) @@ -650,7 +658,7 @@ def enhanced_root_mass(filename, sigma): return density -all_files = glob.glob("data/trial-*.jpg") +all_files = sorted(glob.glob("data/trial-*.jpg")) for filename in all_files: density = enhanced_root_mass(filename=filename, sigma=1.5) # output in format suitable for .csv @@ -661,10 +669,10 @@ The output of the improved program does illustrate that the white circles and labels were skewing our root mass ratios: ```output -data/trial-016.jpg,0.046250166223404256 -data/trial-020.jpg,0.05886968085106383 -data/trial-216.jpg,0.13712117686170214 -data/trial-293.jpg,0.13190342420212767 +data/trial-016.jpg,0.046261136968085106 +data/trial-020.jpg,0.05887167553191489 +data/trial-216.jpg,0.13712067819148935 +data/trial-293.jpg,0.1319044215425532 ``` :::::::::::::::::::::::::::::::::::::::::: spoiler diff --git a/episodes/07-postprocessing.md b/episodes/07-postprocessing.md index 0d0ce099..0c05b266 100644 --- a/episodes/07-postprocessing.md +++ b/episodes/07-postprocessing.md @@ -18,12 +18,12 @@ exercises: 55 ## Objects -In [the *Thresholding* episode](07-thresholding.md) +In [the *Thresholding* episode](06-processing-segmentation.md) we have covered dividing an image into foreground and background pixels. In the shapes example image, we considered the coloured shapes as foreground *objects* on a white background. -![](data/shapes-01.jpg){alt='Original shapes image' .image-with-shadow} +![](fig/shapes-01.jpg){alt='Original shapes image' .image-with-shadow} In thresholding we went from the original image to this version: @@ -250,7 +250,7 @@ def connected_components(filename, sigma=1.0, t=0.5, connectivity=2): ``` The first four lines of code are familiar from -[the *Thresholding* episode](07-thresholding.md). +[the *Thresholding* episode](06-processing-segmentation.md). @@ -489,7 +489,7 @@ So we could use a minimum area as a criterion for when an object should be detec To apply such a criterion, we need a way to calculate the area of objects found by connected components. Recall how we determined the root mass in -[the *Thresholding* episode](07-thresholding.md) +[the *Thresholding* episode](06-processing-segmentation.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 scikit-image library provides the function `ski.measure.regionprops` @@ -519,7 +519,7 @@ This will produce the output ## Plot a histogram of the object area distribution (10 min) Similar to how we determined a "good" threshold in -[the *Thresholding* episode](07-thresholding.md), +[the *Thresholding* episode](06-processing-segmentation.md), it is often helpful to inspect the histogram of an object property. For example, we want to look at the distribution of the object areas. diff --git a/episodes/10-challenges.md b/episodes/10-challenges.md index 1c805fd3..d8cd3669 100644 --- a/episodes/10-challenges.md +++ b/episodes/10-challenges.md @@ -52,8 +52,7 @@ The image should look similar to this one: Additionally, print out the number of colonies for each image. Use what you have learnt about [histograms](05-creating-histograms.md), -[thresholding](07-thresholding.md) and -[connected component analysis](08-connected-components.md). +[thresholding and connected component analysis](06-processing-segmentation.md). Try to put your code into a re-usable function, so that it can be applied conveniently to any image file. @@ -188,7 +187,7 @@ You could expand this solution to, for example, use an automatically determined threshold for each image, which may fit each better. Also, you could filter out colonies below a certain size -(as we did in [the *Connected Component Analysis* episode](08-connected-components.md)). +(as we did in [the *Connected Component Analysis* episode](06-processing-segmentation.md)). You'll also see that some touching colonies are merged into one big colony. This could be fixed with more complicated segmentation methods (outside of the scope of this lesson) like @@ -247,3 +246,12 @@ def count_colonies_enhanced(image_filename, sigma=1.0, min_colony_size=10, conne - These methods are useful for many scientific problems, especially those involving morphometrics. :::::::::::::::::::::::::::::::::::::::::::::::::: + + +:::::::::::::::::::::::::::::::::::::::: discussion + +## Where to go from here? + +Take a look at our [curated list of resources](further-reading.md) for further publicly available courses, resources and scientific literature around image processing and more. + +:::::::::::::::::::::::::::::::::::::::::::::::::: \ No newline at end of file diff --git a/episodes/fig/3D_petri_after_blurring-dark.png b/episodes/fig/3D_petri_after_blurring-dark.png new file mode 100644 index 00000000..5583cd82 Binary files /dev/null and b/episodes/fig/3D_petri_after_blurring-dark.png differ diff --git a/episodes/fig/3D_petri_before_blurring-dark.png b/episodes/fig/3D_petri_before_blurring-dark.png new file mode 100644 index 00000000..7811232a Binary files /dev/null and b/episodes/fig/3D_petri_before_blurring-dark.png differ diff --git a/episodes/fig/Gaussian_2D-dark.png b/episodes/fig/Gaussian_2D-dark.png new file mode 100644 index 00000000..da7ffecf Binary files /dev/null and b/episodes/fig/Gaussian_2D-dark.png differ diff --git a/episodes/fig/beads-canny-ui-dark.png b/episodes/fig/beads-canny-ui-dark.png new file mode 100644 index 00000000..ca6f6a75 Binary files /dev/null and b/episodes/fig/beads-canny-ui-dark.png differ diff --git a/episodes/fig/beads-dark.jpg b/episodes/fig/beads-dark.jpg new file mode 100644 index 00000000..4a585f9f Binary files /dev/null and b/episodes/fig/beads-dark.jpg differ diff --git a/episodes/fig/beads-out-dark.png b/episodes/fig/beads-out-dark.png new file mode 100644 index 00000000..e6cd9242 Binary files /dev/null and b/episodes/fig/beads-out-dark.png differ diff --git a/episodes/fig/beads.jpg b/episodes/fig/beads.jpg new file mode 100644 index 00000000..4a585f9f Binary files /dev/null and b/episodes/fig/beads.jpg differ diff --git a/episodes/fig/black-and-white-dark.jpg b/episodes/fig/black-and-white-dark.jpg new file mode 100644 index 00000000..393a772c Binary files /dev/null and b/episodes/fig/black-and-white-dark.jpg differ diff --git a/episodes/fig/black-and-white-edge-pixels-dark.jpg b/episodes/fig/black-and-white-edge-pixels-dark.jpg new file mode 100644 index 00000000..c5f04a5c Binary files /dev/null and b/episodes/fig/black-and-white-edge-pixels-dark.jpg differ diff --git a/episodes/fig/black-and-white-gradient-dark.png b/episodes/fig/black-and-white-gradient-dark.png new file mode 100644 index 00000000..de1d9c43 Binary files /dev/null and b/episodes/fig/black-and-white-gradient-dark.png differ diff --git a/episodes/fig/blur-demo-dark.gif b/episodes/fig/blur-demo-dark.gif new file mode 100644 index 00000000..5e8bd4ce Binary files /dev/null and b/episodes/fig/blur-demo-dark.gif differ diff --git a/episodes/fig/board-coordinates-dark.jpg b/episodes/fig/board-coordinates-dark.jpg new file mode 100644 index 00000000..be691f00 Binary files /dev/null and b/episodes/fig/board-coordinates-dark.jpg differ diff --git a/episodes/fig/board-dark.jpg b/episodes/fig/board-dark.jpg new file mode 100644 index 00000000..9b61e4e9 Binary files /dev/null and b/episodes/fig/board-dark.jpg differ diff --git a/episodes/fig/board-final-dark.jpg b/episodes/fig/board-final-dark.jpg new file mode 100644 index 00000000..53545a2f Binary files /dev/null and b/episodes/fig/board-final-dark.jpg differ diff --git a/episodes/fig/board.jpg b/episodes/fig/board.jpg new file mode 100644 index 00000000..9b61e4e9 Binary files /dev/null and b/episodes/fig/board.jpg differ diff --git a/episodes/fig/cartesian-coordinates-dark.png b/episodes/fig/cartesian-coordinates-dark.png new file mode 100644 index 00000000..218b3e6b Binary files /dev/null and b/episodes/fig/cartesian-coordinates-dark.png differ diff --git a/episodes/fig/cat-corner-blue-dark.png b/episodes/fig/cat-corner-blue-dark.png new file mode 100644 index 00000000..5f89e1b9 Binary files /dev/null and b/episodes/fig/cat-corner-blue-dark.png differ diff --git a/episodes/fig/cat-dark.jpg b/episodes/fig/cat-dark.jpg new file mode 100644 index 00000000..4f3f969c Binary files /dev/null and b/episodes/fig/cat-dark.jpg differ diff --git a/episodes/fig/cat-eye-pixels-dark.jpg b/episodes/fig/cat-eye-pixels-dark.jpg new file mode 100644 index 00000000..1f34da18 Binary files /dev/null and b/episodes/fig/cat-eye-pixels-dark.jpg differ diff --git a/episodes/fig/chair-layers-rgb.png b/episodes/fig/chair-layers-rgb.png deleted file mode 100644 index cdf53142..00000000 Binary files a/episodes/fig/chair-layers-rgb.png and /dev/null differ diff --git a/episodes/fig/chair-original.jpg b/episodes/fig/chair-original.jpg deleted file mode 100644 index 8977bd71..00000000 Binary files a/episodes/fig/chair-original.jpg and /dev/null differ diff --git a/episodes/fig/checkerboard-blue-channel-dark.png b/episodes/fig/checkerboard-blue-channel-dark.png new file mode 100644 index 00000000..7a411abd Binary files /dev/null and b/episodes/fig/checkerboard-blue-channel-dark.png differ diff --git a/episodes/fig/checkerboard-dark.png b/episodes/fig/checkerboard-dark.png new file mode 100644 index 00000000..417874a8 Binary files /dev/null and b/episodes/fig/checkerboard-dark.png differ diff --git a/episodes/fig/checkerboard-green-channel-dark.png b/episodes/fig/checkerboard-green-channel-dark.png new file mode 100644 index 00000000..505b1957 Binary files /dev/null and b/episodes/fig/checkerboard-green-channel-dark.png differ diff --git a/episodes/fig/checkerboard-red-channel-dark.png b/episodes/fig/checkerboard-red-channel-dark.png new file mode 100644 index 00000000..e6a8f1ae Binary files /dev/null and b/episodes/fig/checkerboard-red-channel-dark.png differ diff --git a/episodes/fig/colonies-01-dark.jpg b/episodes/fig/colonies-01-dark.jpg new file mode 100644 index 00000000..31440c05 Binary files /dev/null and b/episodes/fig/colonies-01-dark.jpg differ diff --git a/episodes/fig/colonies-01-gray-dark.png b/episodes/fig/colonies-01-gray-dark.png new file mode 100644 index 00000000..50179219 Binary files /dev/null and b/episodes/fig/colonies-01-gray-dark.png differ diff --git a/episodes/fig/colonies-01-mask-dark.png b/episodes/fig/colonies-01-mask-dark.png new file mode 100644 index 00000000..f51dc69f Binary files /dev/null and b/episodes/fig/colonies-01-mask-dark.png differ diff --git a/episodes/fig/colonies-01-summary-dark.png b/episodes/fig/colonies-01-summary-dark.png new file mode 100644 index 00000000..8cb89ea0 Binary files /dev/null and b/episodes/fig/colonies-01-summary-dark.png differ diff --git a/episodes/fig/colonies-02-dark.jpg b/episodes/fig/colonies-02-dark.jpg new file mode 100644 index 00000000..4bbd2a68 Binary files /dev/null and b/episodes/fig/colonies-02-dark.jpg differ diff --git a/episodes/fig/colonies-02-summary-dark.png b/episodes/fig/colonies-02-summary-dark.png new file mode 100644 index 00000000..a2c8834b Binary files /dev/null and b/episodes/fig/colonies-02-summary-dark.png differ diff --git a/episodes/fig/colonies-03-dark.jpg b/episodes/fig/colonies-03-dark.jpg new file mode 100644 index 00000000..949be722 Binary files /dev/null and b/episodes/fig/colonies-03-dark.jpg differ diff --git a/episodes/fig/colonies-03-summary-dark.png b/episodes/fig/colonies-03-summary-dark.png new file mode 100644 index 00000000..3c3f652c Binary files /dev/null and b/episodes/fig/colonies-03-summary-dark.png differ diff --git a/episodes/fig/colonies01.png b/episodes/fig/colonies01.png deleted file mode 100644 index 21bf6c58..00000000 Binary files a/episodes/fig/colonies01.png and /dev/null differ diff --git a/episodes/fig/colony-mask-dark.png b/episodes/fig/colony-mask-dark.png new file mode 100644 index 00000000..d4ea8e2a Binary files /dev/null and b/episodes/fig/colony-mask-dark.png differ diff --git a/episodes/fig/colour-table-dark.png b/episodes/fig/colour-table-dark.png new file mode 100644 index 00000000..27372fd2 Binary files /dev/null and b/episodes/fig/colour-table-dark.png differ diff --git a/episodes/fig/combination-dark.png b/episodes/fig/combination-dark.png new file mode 100644 index 00000000..2d35980a Binary files /dev/null and b/episodes/fig/combination-dark.png differ diff --git a/episodes/fig/drawing-practice-dark.jpg b/episodes/fig/drawing-practice-dark.jpg new file mode 100644 index 00000000..588d56cb Binary files /dev/null and b/episodes/fig/drawing-practice-dark.jpg differ diff --git a/episodes/fig/eight-dark.png b/episodes/fig/eight-dark.png new file mode 100644 index 00000000..99b69f00 Binary files /dev/null and b/episodes/fig/eight-dark.png differ diff --git a/episodes/fig/five-dark.png b/episodes/fig/five-dark.png new file mode 100644 index 00000000..0832c5b8 Binary files /dev/null and b/episodes/fig/five-dark.png differ diff --git a/episodes/fig/four-maize-roots-binary-dark.jpg b/episodes/fig/four-maize-roots-binary-dark.jpg new file mode 100644 index 00000000..4d90220f Binary files /dev/null and b/episodes/fig/four-maize-roots-binary-dark.jpg differ diff --git a/episodes/fig/four-maize-roots-binary-improved-dark.jpg b/episodes/fig/four-maize-roots-binary-improved-dark.jpg new file mode 100644 index 00000000..6bbf1b4a Binary files /dev/null and b/episodes/fig/four-maize-roots-binary-improved-dark.jpg differ diff --git a/episodes/fig/four-maize-roots-dark.jpg b/episodes/fig/four-maize-roots-dark.jpg new file mode 100644 index 00000000..2e5d365e Binary files /dev/null and b/episodes/fig/four-maize-roots-dark.jpg differ diff --git a/episodes/fig/gaussian-blurred-dark.png b/episodes/fig/gaussian-blurred-dark.png new file mode 100644 index 00000000..c8c86830 Binary files /dev/null and b/episodes/fig/gaussian-blurred-dark.png differ diff --git a/episodes/fig/gaussian-kernel-dark.png b/episodes/fig/gaussian-kernel-dark.png new file mode 100644 index 00000000..6ac11047 Binary files /dev/null and b/episodes/fig/gaussian-kernel-dark.png differ diff --git a/episodes/fig/gaussian-original-dark.png b/episodes/fig/gaussian-original-dark.png new file mode 100644 index 00000000..7eceeb1c Binary files /dev/null and b/episodes/fig/gaussian-original-dark.png differ diff --git a/episodes/fig/gaussian-original.png b/episodes/fig/gaussian-original.png new file mode 100644 index 00000000..7eceeb1c Binary files /dev/null and b/episodes/fig/gaussian-original.png differ diff --git a/episodes/fig/grayscale-dark.png b/episodes/fig/grayscale-dark.png new file mode 100644 index 00000000..76037a5f Binary files /dev/null and b/episodes/fig/grayscale-dark.png differ diff --git a/episodes/fig/image-coordinates-dark.png b/episodes/fig/image-coordinates-dark.png new file mode 100644 index 00000000..db8e7bf6 Binary files /dev/null and b/episodes/fig/image-coordinates-dark.png differ diff --git a/episodes/fig/left-hand-coordinates-dark.png b/episodes/fig/left-hand-coordinates-dark.png new file mode 100644 index 00000000..a16e1837 Binary files /dev/null and b/episodes/fig/left-hand-coordinates-dark.png differ diff --git a/episodes/fig/maize-root-cluster-dark.jpg b/episodes/fig/maize-root-cluster-dark.jpg new file mode 100644 index 00000000..ac9b56ee Binary files /dev/null and b/episodes/fig/maize-root-cluster-dark.jpg differ diff --git a/episodes/fig/maize-root-cluster-mask-dark.png b/episodes/fig/maize-root-cluster-mask-dark.png new file mode 100644 index 00000000..2ecee5c4 Binary files /dev/null and b/episodes/fig/maize-root-cluster-mask-dark.png differ diff --git a/episodes/fig/maize-root-cluster-selected-dark.png b/episodes/fig/maize-root-cluster-selected-dark.png new file mode 100644 index 00000000..c0a2f243 Binary files /dev/null and b/episodes/fig/maize-root-cluster-selected-dark.png differ diff --git a/episodes/fig/maize-root-cluster-threshold-dark.jpg b/episodes/fig/maize-root-cluster-threshold-dark.jpg new file mode 100644 index 00000000..4ddb086f Binary files /dev/null and b/episodes/fig/maize-root-cluster-threshold-dark.jpg differ diff --git a/episodes/fig/maize-root-cluster.jpg b/episodes/fig/maize-root-cluster.jpg new file mode 100644 index 00000000..ac9b56ee Binary files /dev/null and b/episodes/fig/maize-root-cluster.jpg differ diff --git a/episodes/fig/maize-roots-grayscale-dark.jpg b/episodes/fig/maize-roots-grayscale-dark.jpg new file mode 100644 index 00000000..dc5a0817 Binary files /dev/null and b/episodes/fig/maize-roots-grayscale-dark.jpg differ diff --git a/episodes/fig/maize-roots-grayscale.jpg b/episodes/fig/maize-roots-grayscale.jpg new file mode 100644 index 00000000..dc5a0817 Binary files /dev/null and b/episodes/fig/maize-roots-grayscale.jpg differ diff --git a/episodes/fig/maize-roots-threshold-dark.png b/episodes/fig/maize-roots-threshold-dark.png new file mode 100644 index 00000000..ccd20ae3 Binary files /dev/null and b/episodes/fig/maize-roots-threshold-dark.png differ diff --git a/episodes/fig/maize-seedling-enlarged-dark.jpg b/episodes/fig/maize-seedling-enlarged-dark.jpg new file mode 100644 index 00000000..bef67872 Binary files /dev/null and b/episodes/fig/maize-seedling-enlarged-dark.jpg differ diff --git a/episodes/fig/maize-seedling-original-dark.jpg b/episodes/fig/maize-seedling-original-dark.jpg new file mode 100644 index 00000000..ee5d36ea Binary files /dev/null and b/episodes/fig/maize-seedling-original-dark.jpg differ diff --git a/episodes/fig/maize-seedlings-dark.jpg b/episodes/fig/maize-seedlings-dark.jpg new file mode 100644 index 00000000..b6599d44 Binary files /dev/null and b/episodes/fig/maize-seedlings-dark.jpg differ diff --git a/episodes/fig/maize-seedlings-mask-dark.png b/episodes/fig/maize-seedlings-mask-dark.png new file mode 100644 index 00000000..d29a28aa Binary files /dev/null and b/episodes/fig/maize-seedlings-mask-dark.png differ diff --git a/episodes/fig/maize-seedlings-masked-dark.jpg b/episodes/fig/maize-seedlings-masked-dark.jpg new file mode 100644 index 00000000..2bec2bd6 Binary files /dev/null and b/episodes/fig/maize-seedlings-masked-dark.jpg differ diff --git a/episodes/fig/petri-blurred-intensities-plot-dark.png b/episodes/fig/petri-blurred-intensities-plot-dark.png new file mode 100644 index 00000000..bbb4df43 Binary files /dev/null and b/episodes/fig/petri-blurred-intensities-plot-dark.png differ diff --git a/episodes/fig/petri-dish-dark.png b/episodes/fig/petri-dish-dark.png new file mode 100644 index 00000000..422a5257 Binary files /dev/null and b/episodes/fig/petri-dish-dark.png differ diff --git a/episodes/fig/petri-original-intensities-plot-dark.png b/episodes/fig/petri-original-intensities-plot-dark.png new file mode 100644 index 00000000..c78b5072 Binary files /dev/null and b/episodes/fig/petri-original-intensities-plot-dark.png differ diff --git a/episodes/fig/petri-selected-pixels-marker-dark.png b/episodes/fig/petri-selected-pixels-marker-dark.png new file mode 100644 index 00000000..097c59e2 Binary files /dev/null and b/episodes/fig/petri-selected-pixels-marker-dark.png differ diff --git a/episodes/fig/plant-seedling-colour-histogram-dark.png b/episodes/fig/plant-seedling-colour-histogram-dark.png new file mode 100644 index 00000000..a73d84a6 Binary files /dev/null and b/episodes/fig/plant-seedling-colour-histogram-dark.png differ diff --git a/episodes/fig/plant-seedling-dark.jpg b/episodes/fig/plant-seedling-dark.jpg new file mode 100644 index 00000000..6dd51ad1 Binary files /dev/null and b/episodes/fig/plant-seedling-dark.jpg differ diff --git a/episodes/fig/plant-seedling-grayscale-dark.png b/episodes/fig/plant-seedling-grayscale-dark.png new file mode 100644 index 00000000..cf8fd28b Binary files /dev/null and b/episodes/fig/plant-seedling-grayscale-dark.png differ diff --git a/episodes/fig/plant-seedling-grayscale-histogram-dark.png b/episodes/fig/plant-seedling-grayscale-histogram-dark.png new file mode 100644 index 00000000..5bbb1feb Binary files /dev/null and b/episodes/fig/plant-seedling-grayscale-histogram-dark.png differ diff --git a/episodes/fig/plant-seedling-grayscale-histogram-mask-dark.png b/episodes/fig/plant-seedling-grayscale-histogram-mask-dark.png new file mode 100644 index 00000000..bb543278 Binary files /dev/null and b/episodes/fig/plant-seedling-grayscale-histogram-mask-dark.png differ diff --git a/episodes/fig/plant-seedling.jpg b/episodes/fig/plant-seedling.jpg new file mode 100644 index 00000000..6dd51ad1 Binary files /dev/null and b/episodes/fig/plant-seedling.jpg differ diff --git a/episodes/fig/quality-histogram-dark.jpg b/episodes/fig/quality-histogram-dark.jpg new file mode 100644 index 00000000..20e142b7 Binary files /dev/null and b/episodes/fig/quality-histogram-dark.jpg differ diff --git a/episodes/fig/quality-jpg-dark.jpg b/episodes/fig/quality-jpg-dark.jpg new file mode 100644 index 00000000..4687e370 Binary files /dev/null and b/episodes/fig/quality-jpg-dark.jpg differ diff --git a/episodes/fig/quality-original-dark.jpg b/episodes/fig/quality-original-dark.jpg new file mode 100644 index 00000000..e169be00 Binary files /dev/null and b/episodes/fig/quality-original-dark.jpg differ diff --git a/episodes/fig/quality-tif-dark.jpg b/episodes/fig/quality-tif-dark.jpg new file mode 100644 index 00000000..fcead57c Binary files /dev/null and b/episodes/fig/quality-tif-dark.jpg differ diff --git a/episodes/fig/rectangle-gaussian-blurred-dark.png b/episodes/fig/rectangle-gaussian-blurred-dark.png new file mode 100644 index 00000000..61b3f8b8 Binary files /dev/null and b/episodes/fig/rectangle-gaussian-blurred-dark.png differ diff --git a/episodes/fig/remote-control-dark.jpg b/episodes/fig/remote-control-dark.jpg new file mode 100644 index 00000000..dfe33abd Binary files /dev/null and b/episodes/fig/remote-control-dark.jpg differ diff --git a/episodes/fig/remote-control-masked-dark.jpg b/episodes/fig/remote-control-masked-dark.jpg new file mode 100644 index 00000000..61881f44 Binary files /dev/null and b/episodes/fig/remote-control-masked-dark.jpg differ diff --git a/episodes/fig/remote-control.jpg b/episodes/fig/remote-control.jpg new file mode 100644 index 00000000..dfe33abd Binary files /dev/null and b/episodes/fig/remote-control.jpg differ diff --git a/episodes/fig/shapes-01-canny-edge-output-dark.png b/episodes/fig/shapes-01-canny-edge-output-dark.png new file mode 100644 index 00000000..36deb877 Binary files /dev/null and b/episodes/fig/shapes-01-canny-edge-output-dark.png differ diff --git a/episodes/fig/shapes-01-canny-edges-dark.png b/episodes/fig/shapes-01-canny-edges-dark.png new file mode 100644 index 00000000..c9272d6a Binary files /dev/null and b/episodes/fig/shapes-01-canny-edges-dark.png differ diff --git a/episodes/fig/shapes-01-canny-track-edges-dark.png b/episodes/fig/shapes-01-canny-track-edges-dark.png new file mode 100644 index 00000000..40dc580e Binary files /dev/null and b/episodes/fig/shapes-01-canny-track-edges-dark.png differ diff --git a/episodes/fig/shapes-01-cca-detail-dark.png b/episodes/fig/shapes-01-cca-detail-dark.png new file mode 100644 index 00000000..5fd9041d Binary files /dev/null and b/episodes/fig/shapes-01-cca-detail-dark.png differ diff --git a/episodes/fig/shapes-01-dark.jpg b/episodes/fig/shapes-01-dark.jpg new file mode 100644 index 00000000..6b2707ad Binary files /dev/null and b/episodes/fig/shapes-01-dark.jpg differ diff --git a/episodes/fig/shapes-01-filtered-objects-dark.png b/episodes/fig/shapes-01-filtered-objects-dark.png new file mode 100644 index 00000000..3d13ca04 Binary files /dev/null and b/episodes/fig/shapes-01-filtered-objects-dark.png differ diff --git a/episodes/fig/shapes-01-grayscale-dark.png b/episodes/fig/shapes-01-grayscale-dark.png new file mode 100644 index 00000000..25a6cfa5 Binary files /dev/null and b/episodes/fig/shapes-01-grayscale-dark.png differ diff --git a/episodes/fig/shapes-01-labeled-dark.png b/episodes/fig/shapes-01-labeled-dark.png new file mode 100644 index 00000000..5311ecdc Binary files /dev/null and b/episodes/fig/shapes-01-labeled-dark.png differ diff --git a/episodes/fig/shapes-01-mask-dark.png b/episodes/fig/shapes-01-mask-dark.png new file mode 100644 index 00000000..0c9f1a59 Binary files /dev/null and b/episodes/fig/shapes-01-mask-dark.png differ diff --git a/episodes/fig/shapes-01-objects-coloured-by-area-dark.png b/episodes/fig/shapes-01-objects-coloured-by-area-dark.png new file mode 100644 index 00000000..e3da4ec3 Binary files /dev/null and b/episodes/fig/shapes-01-objects-coloured-by-area-dark.png differ diff --git a/episodes/fig/shapes-01-objects-coloured-by-area.png b/episodes/fig/shapes-01-objects-coloured-by-area.png index b70ec8ff..e3da4ec3 100644 Binary files a/episodes/fig/shapes-01-objects-coloured-by-area.png and b/episodes/fig/shapes-01-objects-coloured-by-area.png differ diff --git a/episodes/fig/shapes-01-selected-dark.png b/episodes/fig/shapes-01-selected-dark.png new file mode 100644 index 00000000..fd50ed96 Binary files /dev/null and b/episodes/fig/shapes-01-selected-dark.png differ diff --git a/episodes/fig/shapes-01.jpg b/episodes/fig/shapes-01.jpg new file mode 100644 index 00000000..6b2707ad Binary files /dev/null and b/episodes/fig/shapes-01.jpg differ diff --git a/episodes/fig/shapes-02-dark.jpg b/episodes/fig/shapes-02-dark.jpg new file mode 100644 index 00000000..5553492e Binary files /dev/null and b/episodes/fig/shapes-02-dark.jpg differ diff --git a/episodes/fig/shapes-02-mask-dark.png b/episodes/fig/shapes-02-mask-dark.png new file mode 100644 index 00000000..3d49ac5c Binary files /dev/null and b/episodes/fig/shapes-02-mask-dark.png differ diff --git a/episodes/fig/shapes-02-selected-dark.png b/episodes/fig/shapes-02-selected-dark.png new file mode 100644 index 00000000..eb5b6e91 Binary files /dev/null and b/episodes/fig/shapes-02-selected-dark.png differ diff --git a/episodes/fig/shapes-02.jpg b/episodes/fig/shapes-02.jpg new file mode 100644 index 00000000..5553492e Binary files /dev/null and b/episodes/fig/shapes-02.jpg differ diff --git a/episodes/fig/sudoku-dark.png b/episodes/fig/sudoku-dark.png new file mode 100644 index 00000000..e6262cf4 Binary files /dev/null and b/episodes/fig/sudoku-dark.png differ diff --git a/episodes/fig/sudoku-gray-dark.png b/episodes/fig/sudoku-gray-dark.png new file mode 100644 index 00000000..4565e282 Binary files /dev/null and b/episodes/fig/sudoku-gray-dark.png differ diff --git a/episodes/fig/sudoku.png b/episodes/fig/sudoku.png new file mode 100644 index 00000000..e6262cf4 Binary files /dev/null and b/episodes/fig/sudoku.png differ diff --git a/episodes/fig/three-colours-dark.png b/episodes/fig/three-colours-dark.png new file mode 100644 index 00000000..466b949f Binary files /dev/null and b/episodes/fig/three-colours-dark.png differ diff --git a/episodes/fig/wellplate-01-dark.jpg b/episodes/fig/wellplate-01-dark.jpg new file mode 100644 index 00000000..6cf02f4d Binary files /dev/null and b/episodes/fig/wellplate-01-dark.jpg differ diff --git a/episodes/fig/wellplate-01-masked-dark.jpg b/episodes/fig/wellplate-01-masked-dark.jpg new file mode 100644 index 00000000..8b3d918d Binary files /dev/null and b/episodes/fig/wellplate-01-masked-dark.jpg differ diff --git a/episodes/fig/wellplate-01.jpg b/episodes/fig/wellplate-01.jpg new file mode 100644 index 00000000..6cf02f4d Binary files /dev/null and b/episodes/fig/wellplate-01.jpg differ diff --git a/episodes/fig/wellplate-02-dark.jpg b/episodes/fig/wellplate-02-dark.jpg new file mode 100644 index 00000000..fc2cbf42 Binary files /dev/null and b/episodes/fig/wellplate-02-dark.jpg differ diff --git a/episodes/fig/wellplate-02-histogram-dark.png b/episodes/fig/wellplate-02-histogram-dark.png new file mode 100644 index 00000000..ac109122 Binary files /dev/null and b/episodes/fig/wellplate-02-histogram-dark.png differ diff --git a/episodes/fig/wellplate-02-masked-dark.jpg b/episodes/fig/wellplate-02-masked-dark.jpg new file mode 100644 index 00000000..bbd2797b Binary files /dev/null and b/episodes/fig/wellplate-02-masked-dark.jpg differ diff --git a/episodes/fig/zero-dark.png b/episodes/fig/zero-dark.png new file mode 100644 index 00000000..44ead028 Binary files /dev/null and b/episodes/fig/zero-dark.png differ diff --git a/episodes/files/environment.yml b/episodes/files/environment.yml new file mode 100644 index 00000000..bb1b8049 --- /dev/null +++ b/episodes/files/environment.yml @@ -0,0 +1,11 @@ +name: dc-image +channels: + - conda-forge +dependencies: + - python>=3.11 + - jupyterlab + - numpy + - matplotlib + - scikit-image + - ipympl + - imageio diff --git a/learners/edge-detection.md b/learners/edge-detection.md index 0486e50a..b0cf3f73 100644 --- a/learners/edge-detection.md +++ b/learners/edge-detection.md @@ -35,7 +35,7 @@ For example, once we have found the edges of the objects in the image (or once we have converted the image to binary using thresholding), we can use that information to find the image *contours*, which we will learn about in -[the *Connected Component Analysis* episode](../episodes/08-connected-components.md). +[the *Connected Component Analysis* episode](../episodes/06-processing-segmentation.md). With the contours, 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. @@ -126,9 +126,9 @@ The following program illustrates how the `skimage.feature.canny()` method can be used to detect the edges in an image. We will execute the program on the `data/shapes-01.jpg` image, which we used before in -[the *Thresholding* episode](../episodes/07-thresholding.md): +[the *Thresholding* episode](../episodes/06-processing-segmentation.md): -![](data/shapes-01.jpg){alt='coloured shapes'} +![](fig/shapes-01.jpg){alt='coloured shapes'} We are interested in finding the edges of the shapes in the image, and so the colours are not important. @@ -225,7 +225,7 @@ based on the contents of the image(s) to be processed. Here is an image of some glass beads that we can use as input into a Canny edge detection program: -![](data/beads.jpg){alt='Beads image'} +![](fig/beads.jpg){alt='Beads image'} We could use the `code/edge-detection/CannyEdge.py` program above to find edges in this image. @@ -394,7 +394,7 @@ Consider this image of a collection of maize seedlings, and suppose we wish to use simple fixed-level thresholding to mask out everything that is not part of one of the plants. -![](data/maize-roots-grayscale.jpg){alt='Maize roots image'} +![](fig/maize-roots-grayscale.jpg){alt='Maize roots image'} To perform the thresholding, we could first create a histogram, then examine it, and select an appropriate threshold value. diff --git a/learners/further-reading.md b/learners/further-reading.md new file mode 100644 index 00000000..52eb196c --- /dev/null +++ b/learners/further-reading.md @@ -0,0 +1,29 @@ +--- +title: Further Reading +permalink: /reading/ +--- + +## Where to go from here + +- [Scikit-image YouTube tutorials](https://www.youtube.com/playlist?list=PLBKcU7Ik-ir9Fi_hM_A6_U2UTpm7ACUtl) +- [Principles of Scientific Imaging](https://imagej.net/imaging/principles) +- [Data Handling and Management Training](https://carpentries-incubator.github.io/Data-Management-Training/) +- [Introduction to Bioimage Analysis by Pete Bankhead](https://bioimagebook.github.io/index.html) +- [Bio-image Analysis Notebooks by Robert Haase](https://haesleinhuepf.github.io/BioImageAnalysisNotebooks/intro.html) +- [Introduction to artificial neural networks in Python](https://carpentries-incubator.github.io/machine-learning-neural-python/index.html) +- [Building Better Research Software](https://carpentries-incubator.github.io/better-research-software/) + +## Where to find more help + +- [Image.sc Forum](https://image.sc/) +- [NFDI4BioImage Training Materials collection](https://nfdi4bioimage.github.io/training/readme.html) +- [Curated list of image analysis resources by EPFL Center for Imaging](https://github.com/EPFL-Center-for-Imaging/awesome-scientific-image-analysis) + +## Scientific Literature + +- [Digital Image Processing](https://www.imageprocessingplace.com), Textbook by Rafael C. Gonzalez and Richard E. Woods +- [Checklist for publishing images and analyses ](https://www.nature.com/articles/s41592-023-01987-9) +- [REMBI: Recommended Metadata for Biological Images](https://www.nature.com/articles/s41592-021-01166-8) +- ["Twenty questions": a schema for a set of questions to guide analyses](https://www.nature.com/articles/s41592-023-01919-7) +- [From cells to pixels: A decision tree for designing bioimage analysis pipelines](https://onlinelibrary.wiley.com/doi/10.1111/jmi.70021) + diff --git a/learners/reference.md b/learners/reference.md index 54efca24..6c4e4f65 100644 --- a/learners/reference.md +++ b/learners/reference.md @@ -1,5 +1,5 @@ --- -title: 'Reference' +title: 'Glossary' --- ## Glossary diff --git a/learners/setup.md b/learners/setup.md index a12264ae..43f49f29 100644 --- a/learners/setup.md +++ b/learners/setup.md @@ -7,39 +7,31 @@ Before joining the workshop or following the lesson, please complete the data an ## Data -The example images used in this lesson are available on [FigShare](https://figshare.com/). +The example images and a description of the Python environment used in this lesson are available on [FigShare](https://figshare.com/). To download the data, please visit [the dataset page for this workshop][figshare-data] and click the "Download all" button. -Unzip the downloaded file, and save the contents as a folder called `data` somewhere you will easily find it again, +Unzip the downloaded file, and save the contents as a folder called `data` somewhere you will easily find it again, e.g. your Desktop or a folder you have created for using in this workshop. (The name `data` is optional but recommended, as this is the name we will use to refer to the folder throughout the lesson.) ## Software -1. Download and install the latest [Anaconda - distribution](https://www.anaconda.com/download/) for your - operating system. Make sure to choose the Python 3 version (as - 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. +1. Download and install the latest [Miniforge distribution of Python](https://conda-forge.org/download/) for your operating system. + ([See more detailed instructions from The Carpentries](https://carpentries.github.io/workshop-template/#python-1).) + If you already have a Python 3 setup that you are happy with, you can continue to use that (we recommend that you make sure your Python version is current). + The next step assumes that `conda` is available to manage your Python environment. +2. Set up an environment to work in during the lesson. + In a terminal (Linux/Mac) or the MiniForge Prompt application (Windows), navigate to the location where you saved the unzipped data for the lesson and run the following command: - ::::::::::::::::::::::::::::::::::::::::: callout - - ## Updating scikit-image in an existing Anaconda distribution - - ```shell - conda upgrade -y scikit-image + ```bash + conda env create -f environment.yml ``` - :::::::::::::::::::::::::::::::::::::::::::::::::: - -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 + If prompted, allow `conda` to install the required libraries. +3. Activate the new environment you just created: - ```shell - conda install -c conda-forge ipympl + ```bash + conda activate dc-image ``` ::::::::::::::::::::::::::::::::::::::::: callout @@ -83,9 +75,9 @@ e.g. your Desktop or a folder you have created for using in this workshop. ## Instructions for Windows - Launch the Anaconda Prompt program and type `jupyter lab`. + Launch the Miniforge 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.`) + `'jupyter' is not recognized as an internal or external command, operable program or batch file.`) :::::::::::::::::::::::::