From 4dd3f8cf006bf80f3489d8d4f8a43e271d3da874 Mon Sep 17 00:00:00 2001 From: "Candace Makeda Moore, MD" <31033601+drcandacemakedamoore@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:17:00 +0100 Subject: [PATCH 1/7] no variable named image in episode 2 --- _episodes/02-image-basics.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/_episodes/02-image-basics.md b/_episodes/02-image-basics.md index e407849f2..28b19127c 100644 --- a/_episodes/02-image-basics.md +++ b/_episodes/02-image-basics.md @@ -199,8 +199,8 @@ natively (think of volumes, movies). {: .callout} ~~~ -image = iio.imread(uri="data/eight.tif") -plt.imshow(image) +eight_tiff = iio.imread(uri="data/eight.tif") +plt.imshow(eight_tiff) ~~~ {: .language-python} @@ -229,8 +229,8 @@ and see the matrix by printing our image variable to the screen. ~~~ -print(image.shape) -print(image) +print(eight_tiff.shape) +print(eight_tiff) ~~~ {: .language-python} From 09fa87aa810505d004a520b4ca27045b964b3061 Mon Sep 17 00:00:00 2001 From: "Candace Makeda Moore, MD" <31033601+drcandacemakedamoore@users.noreply.github.com> Date: Tue, 14 Mar 2023 17:11:13 +0100 Subject: [PATCH 2/7] take all image named variables out of episode 3 --- _episodes/03-skimage-images.md | 70 +++++++++++++++++----------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/_episodes/03-skimage-images.md b/_episodes/03-skimage-images.md index 55636b94f..b03533e76 100644 --- a/_episodes/03-skimage-images.md +++ b/_episodes/03-skimage-images.md @@ -61,7 +61,7 @@ Here are the first few lines: * """ # read image -image = iio.imread(uri="data/chair.jpg") +chair_jpg = iio.imread(uri="data/chair.jpg") ~~~ {: .language-python} @@ -73,7 +73,7 @@ Next, we will do something with the image: ~~~ fig, ax = plt.subplots() -plt.imshow(image) +plt.imshow(chair_jpg) ~~~ {: .language-python} @@ -86,11 +86,11 @@ Now, we will save the image in another format: ~~~ # save a new version in .tif format -iio.imwrite(uri="data/chair.tif", image=image) +iio.imwrite(uri="data/chair.tif", image=chair_jpg) ~~~ {: .language-python} -The final statement in the program, `iio.imwrite(uri="data/chair.tif", image=image)`, +The final statement in the program, `iio.imwrite(uri="data/chair.tif", image=chair_jpg)`, writes the image to a file named `chair.tif` in the `data/` directory. The `imwrite()` function automatically determines the type of the file, based on the file extension we provide. @@ -150,19 +150,19 @@ In this case, the `.tif` extension causes the image to be saved as a TIFF. > > Add `import skimage.transform` and `import skimage.util` to your list of imports. > Using the `chair.jpg` image located in the data folder, -> write a Python script to read your image into a variable named `image`. +> write a Python script to read your image into a variable named `chair_jpg`. > Then, resize the image to 10 percent of its current size using these lines of code: > > ~~~ -> new_shape = (image.shape[0] // 10, image.shape[1] // 10, image.shape[2]) -> small = skimage.transform.resize(image=image, output_shape=new_shape) +> new_shape = (chair_jpg.shape[0] // 10, chair_jpg.shape[1] // 10, chair_jpg.shape[2]) +> small = skimage.transform.resize(image=chair_jpg, output_shape=new_shape) > small = skimage.util.img_as_ubyte(small) > ~~~ > {: .language-python} > > As it is used here, > the parameters to the `skimage.transform.resize()` function are -> the image to transform, `image`, +> the image to transform, `chair_jpg`, > the dimensions we want the new image to have, `new_shape`. > > > Note that the pixel values in the new image are an approximation of @@ -207,11 +207,11 @@ In this case, the `.tif` extension causes the image to be saved as a TIFF. > > """ > > > > # read in image -> > image = iio.imread(uri="data/chair.jpg") +> > chair_jpg = iio.imread(uri="data/chair.jpg") > > > > # resize the image -> > new_shape = (image.shape[0] // 10, image.shape[1] // 10, image.shape[2]) -> > small = skimage.transform.resize(image=image, output_shape=new_shape) +> > new_shape = (chair_jpg.shape[0] // 10, chair_jpg.shape[1] // 10, chair_jpg.shape[2]) +> > small = skimage.transform.resize(image=chair_jpg, output_shape=new_shape) > > small = skimage.util.img_as_ubyte(small) > > > > # write out image @@ -219,7 +219,7 @@ In this case, the `.tif` extension causes the image to be saved as a TIFF. > > > > # display images > > fig, ax = plt.subplots() -> > plt.imshow(image) +> > plt.imshow(chair_jpg) > > fig, ax = plt.subplots() > > plt.imshow(small) > > ~~~ @@ -269,12 +269,11 @@ When loading an image with `imageio`, in certain situations the image is stored """ # read input image -image = iio.imread(uri="data/maize-root-cluster.jpg") -image = np.array(image) +roots = iio.imread(uri="data/maize-root-cluster.jpg") # display original image fig, ax = plt.subplots() -plt.imshow(image) +plt.imshow(roots) ~~~ {: .language-python} @@ -283,15 +282,15 @@ Now we can threshold the image and display the result. ~~~ # keep only high-intensity pixels -image[image < 128] = 0 +roots[roots < 128] = 0 # display modified image fig, ax = plt.subplots() -plt.imshow(image) +plt.imshow(roots) ~~~ {: .language-python} -The NumPy command to ignore all low-intensity pixels is `image[image < 128] = 0`. +The NumPy command to ignore all low-intensity pixels is `roots[roots < 128] = 0`. Every pixel colour value in the whole 3-dimensional array with a value less that 128 is set to zero. In this case, @@ -334,14 +333,14 @@ because using floating point numbers is numerically more stable. """ # read input image -image = iio.imread(uri="data/chair.jpg") +chair_jpg = iio.imread(uri="data/chair.jpg") # display original image fig, ax = plt.subplots() -plt.imshow(image) +plt.imshow(chair_jpg) # convert to grayscale and display -gray_image = skimage.color.rgb2gray(image) +gray_image = skimage.color.rgb2gray(chair_jpg) fig, ax = plt.subplots() plt.imshow(gray_image, cmap="gray") ~~~ @@ -357,11 +356,11 @@ passing the argument `mode="L"` to `iio.imread()`. """ # read input image, based on filename parameter -image = iio.imread(uri="data/chair.jpg", mode="L") +chair_jpg_l = iio.imread(uri="data/chair.jpg", mode="L") # display grayscale image fig, ax = plt.subplots() -plt.imshow(image, cmap="gray") +plt.imshow(chair_jpg_l, cmap="gray") ~~~ {: .language-python} @@ -401,15 +400,14 @@ pass `plugin="pillow"`. If the backend is not specified explicitly, `iio.imread( > > > > ~~~ > > -> > image = iio.imread(uri="data/sudoku.png", mode="L") -> > image = np.array(image) +> > sodoku = iio.imread(uri="data/sudoku.jpg", mode="L") > > ~~~ > > {: .language-python } > > > > Then change all bright pixel values greater than 192 to 192: > > > > ~~~ -> > image[image > 192] = 192 +> > sodoku[sodoku > 0.75] = 0.75 > > ~~~ > > {: .language-python } > > @@ -417,7 +415,7 @@ pass `plugin="pillow"`. If the backend is not specified explicitly, `iio.imread( > > > > ~~~ > > fig, ax = plt.subplots() -> > plt.imshow(image, cmap="gray", vmin=0, vmax=255) +> > plt.imshow(sodoku, cmap="gray", vmin=0, vmax=1) > > ~~~ > > {: .language-python} > {: .solution} @@ -493,9 +491,9 @@ A script to create the subimage would start by loading the image: """ # load and display original image -image = iio.imread(uri="data/board.jpg") +board = iio.imread(uri="data/board.jpg") fig, ax = plt.subplots() -plt.imshow(image) +plt.imshow(board) ~~~ {: .language-python} @@ -504,7 +502,7 @@ create a new image with our selected area and then display the new image. ~~~ # extract, display, and save sub-image -clip = image[60:151, 135:481, :] +clip = board[60:151, 135:481, :] fig, ax = plt.subplots() plt.imshow(clip) iio.imwrite(uri="data/clip.tif", image=clip) @@ -515,10 +513,10 @@ We can also change the values in an image, as shown next. ~~~ # replace clipped area with sampled color -color = image[330, 90] -image[60:151, 135:481] = color +color = board[330, 90] +board[60:151, 135:481] = color fig, ax = plt.subplots() -plt.imshow(image) +plt.imshow(board) ~~~ {: .language-python} @@ -555,13 +553,13 @@ as shown in the final image produced by the program: > > """ > > > > # load and display original image -> > image = iio.imread(uri="data/maize-root-cluster.jpg") +> > root = iio.imread(uri="data/maize-root-cluster.jpg") > > fig, ax = plt.subplots() -> > plt.imshow(image) +> > plt.imshow(root) > > > > # extract, display, and save sub-image > > # WRITE YOUR CODE TO SELECT THE SUBIMAGE NAME clip HERE: -> > clip = image[0:400, 275:550, :] +> > clip = root[0:400, 275:550, :] > > fig, ax = plt.subplots() > > plt.imshow(clip) > > From 4de059fb7066068d7e9d0ee96bdc8e9d09d1589e Mon Sep 17 00:00:00 2001 From: "Candace Makeda Moore, MD" <31033601+drcandacemakedamoore@users.noreply.github.com> Date: Wed, 15 Mar 2023 08:09:58 +0100 Subject: [PATCH 3/7] add picture.copy where needed, correct for sudoku being a png --- _episodes/03-skimage-images.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/_episodes/03-skimage-images.md b/_episodes/03-skimage-images.md index b03533e76..b21816600 100644 --- a/_episodes/03-skimage-images.md +++ b/_episodes/03-skimage-images.md @@ -281,6 +281,8 @@ plt.imshow(roots) Now we can threshold the image and display the result. ~~~ +# copy the image so it can be manipulated +roots = roots.copy() # keep only high-intensity pixels roots[roots < 128] = 0 @@ -400,14 +402,15 @@ pass `plugin="pillow"`. If the backend is not specified explicitly, `iio.imread( > > > > ~~~ > > -> > sodoku = iio.imread(uri="data/sudoku.jpg", mode="L") +> > sodoku = iio.imread(uri="data/sudoku.png") > > ~~~ > > {: .language-python } > > > > Then change all bright pixel values greater than 192 to 192: > > > > ~~~ -> > sodoku[sodoku > 0.75] = 0.75 +> > sodoku = sodoku.copy() +> > sodoku[sodoku > 125] = 125 > > ~~~ > > {: .language-python } > > @@ -513,6 +516,7 @@ We can also change the values in an image, as shown next. ~~~ # replace clipped area with sampled color +board = board.copy() color = board[330, 90] board[60:151, 135:481] = color fig, ax = plt.subplots() From aa007511b4cbff6cc5892bf63e9c0e1dd7cb17b3 Mon Sep 17 00:00:00 2001 From: Ulf Schiller Date: Thu, 13 Apr 2023 16:54:22 -0400 Subject: [PATCH 4/7] Update image variables in episode 2 and 3 --- _episodes/02-image-basics.md | 8 ++-- _episodes/03-skimage-images.md | 83 +++++++++++++++++----------------- 2 files changed, 45 insertions(+), 46 deletions(-) diff --git a/_episodes/02-image-basics.md b/_episodes/02-image-basics.md index 28b19127c..08ea01822 100644 --- a/_episodes/02-image-basics.md +++ b/_episodes/02-image-basics.md @@ -199,8 +199,8 @@ natively (think of volumes, movies). {: .callout} ~~~ -eight_tiff = iio.imread(uri="data/eight.tif") -plt.imshow(eight_tiff) +eight = iio.imread(uri="data/eight.tif") +plt.imshow(eight) ~~~ {: .language-python} @@ -229,8 +229,8 @@ and see the matrix by printing our image variable to the screen. ~~~ -print(eight_tiff.shape) -print(eight_tiff) +print(eight.shape) +print(eight) ~~~ {: .language-python} diff --git a/_episodes/03-skimage-images.md b/_episodes/03-skimage-images.md index b21816600..107005f95 100644 --- a/_episodes/03-skimage-images.md +++ b/_episodes/03-skimage-images.md @@ -61,7 +61,7 @@ Here are the first few lines: * """ # read image -chair_jpg = iio.imread(uri="data/chair.jpg") +chair = iio.imread(uri="data/chair.jpg") ~~~ {: .language-python} @@ -73,7 +73,7 @@ Next, we will do something with the image: ~~~ fig, ax = plt.subplots() -plt.imshow(chair_jpg) +plt.imshow(chair) ~~~ {: .language-python} @@ -86,11 +86,11 @@ Now, we will save the image in another format: ~~~ # save a new version in .tif format -iio.imwrite(uri="data/chair.tif", image=chair_jpg) +iio.imwrite(uri="data/chair.tif", image=chair) ~~~ {: .language-python} -The final statement in the program, `iio.imwrite(uri="data/chair.tif", image=chair_jpg)`, +The final statement in the program, `iio.imwrite(uri="data/chair.tif", image=chair)`, writes the image to a file named `chair.tif` in the `data/` directory. The `imwrite()` function automatically determines the type of the file, based on the file extension we provide. @@ -150,19 +150,19 @@ In this case, the `.tif` extension causes the image to be saved as a TIFF. > > Add `import skimage.transform` and `import skimage.util` to your list of imports. > Using the `chair.jpg` image located in the data folder, -> write a Python script to read your image into a variable named `chair_jpg`. +> write a Python script to read your image into a variable named `chair`. > Then, resize the image to 10 percent of its current size using these lines of code: > > ~~~ -> new_shape = (chair_jpg.shape[0] // 10, chair_jpg.shape[1] // 10, chair_jpg.shape[2]) -> small = skimage.transform.resize(image=chair_jpg, output_shape=new_shape) -> small = skimage.util.img_as_ubyte(small) +> new_shape = (chair.shape[0] // 10, chair.shape[1] // 10, chair.shape[2]) +> resized_chair = skimage.transform.resize(image=chair, output_shape=new_shape) +> resized_chair = skimage.util.img_as_ubyte(resized_chair) > ~~~ > {: .language-python} > > As it is used here, > the parameters to the `skimage.transform.resize()` function are -> the image to transform, `chair_jpg`, +> the image to transform, `chair`, > the dimensions we want the new image to have, `new_shape`. > > > Note that the pixel values in the new image are an approximation of @@ -207,26 +207,26 @@ In this case, the `.tif` extension causes the image to be saved as a TIFF. > > """ > > > > # read in image -> > chair_jpg = iio.imread(uri="data/chair.jpg") +> > chair = iio.imread(uri="data/chair.jpg") > > > > # resize the image -> > new_shape = (chair_jpg.shape[0] // 10, chair_jpg.shape[1] // 10, chair_jpg.shape[2]) -> > small = skimage.transform.resize(image=chair_jpg, output_shape=new_shape) -> > small = skimage.util.img_as_ubyte(small) +> > new_shape = (chair.shape[0] // 10, chair.shape[1] // 10, chair.shape[2]) +> > resized_chair = skimage.transform.resize(image=chair, output_shape=new_shape) +> > resized_chair = skimage.util.img_as_ubyte(resized_chair) > > > > # write out image -> > iio.imwrite(uri="data/resized.jpg", image=small) +> > iio.imwrite(uri="data/resized_chair.jpg", image=resized_chair) > > > > # display images > > fig, ax = plt.subplots() -> > plt.imshow(chair_jpg) +> > plt.imshow(chair) > > fig, ax = plt.subplots() -> > plt.imshow(small) +> > plt.imshow(resized_chair) > > ~~~ > > {: .language-python} > > > > The script resizes the `data/chair.jpg` image by a factor of 10 in both dimensions, -> > saves the result to the `data/resized.jpg` file, +> > saves the result to the `data/resized_chair.jpg` file, > > and displays original and resized for comparision. > {: .solution} {: .challenge} @@ -269,11 +269,12 @@ When loading an image with `imageio`, in certain situations the image is stored """ # read input image -roots = iio.imread(uri="data/maize-root-cluster.jpg") +maize_roots = iio.imread(uri="data/maize-root-cluster.jpg") +maize_roots = np.array(maize_roots) # display original image fig, ax = plt.subplots() -plt.imshow(roots) +plt.imshow(maize_roots) ~~~ {: .language-python} @@ -281,14 +282,12 @@ plt.imshow(roots) Now we can threshold the image and display the result. ~~~ -# copy the image so it can be manipulated -roots = roots.copy() # keep only high-intensity pixels -roots[roots < 128] = 0 +maize_roots[maize_roots < 128] = 0 # display modified image fig, ax = plt.subplots() -plt.imshow(roots) +plt.imshow(maize_roots) ~~~ {: .language-python} @@ -335,16 +334,16 @@ because using floating point numbers is numerically more stable. """ # read input image -chair_jpg = iio.imread(uri="data/chair.jpg") +chair = iio.imread(uri="data/chair.jpg") # display original image fig, ax = plt.subplots() -plt.imshow(chair_jpg) +plt.imshow(chair) # convert to grayscale and display -gray_image = skimage.color.rgb2gray(chair_jpg) +gray_chair = skimage.color.rgb2gray(chair) fig, ax = plt.subplots() -plt.imshow(gray_image, cmap="gray") +plt.imshow(gray_chair, cmap="gray") ~~~ {: .language-python} @@ -358,11 +357,11 @@ passing the argument `mode="L"` to `iio.imread()`. """ # read input image, based on filename parameter -chair_jpg_l = iio.imread(uri="data/chair.jpg", mode="L") +gray_chair = iio.imread(uri="data/chair.jpg", mode="L") # display grayscale image fig, ax = plt.subplots() -plt.imshow(chair_jpg_l, cmap="gray") +plt.imshow(gray_chair, cmap="gray") ~~~ {: .language-python} @@ -402,15 +401,15 @@ pass `plugin="pillow"`. If the backend is not specified explicitly, `iio.imread( > > > > ~~~ > > -> > sodoku = iio.imread(uri="data/sudoku.png") +> > sudoku = iio.imread(uri="data/sudoku.png") > > ~~~ > > {: .language-python } > > > > Then change all bright pixel values greater than 192 to 192: > > > > ~~~ -> > sodoku = sodoku.copy() -> > sodoku[sodoku > 125] = 125 +> > sudoku = sudoku.copy() +> > sudoku[sudoku > 125] = 125 > > ~~~ > > {: .language-python } > > @@ -418,7 +417,7 @@ pass `plugin="pillow"`. If the backend is not specified explicitly, `iio.imread( > > > > ~~~ > > fig, ax = plt.subplots() -> > plt.imshow(sodoku, cmap="gray", vmin=0, vmax=1) +> > plt.imshow(sudoku, cmap="gray", vmin=0, vmax=1) > > ~~~ > > {: .language-python} > {: .solution} @@ -495,6 +494,7 @@ A script to create the subimage would start by loading the image: # load and display original image board = iio.imread(uri="data/board.jpg") +board = np.array(board) fig, ax = plt.subplots() plt.imshow(board) ~~~ @@ -505,10 +505,10 @@ create a new image with our selected area and then display the new image. ~~~ # extract, display, and save sub-image -clip = board[60:151, 135:481, :] +clipped_board = board[60:151, 135:481, :] fig, ax = plt.subplots() -plt.imshow(clip) -iio.imwrite(uri="data/clip.tif", image=clip) +plt.imshow(clipped_board) +iio.imwrite(uri="data/clipped_board.tif", image=clipped_board) ~~~ {: .language-python} @@ -516,7 +516,6 @@ We can also change the values in an image, as shown next. ~~~ # replace clipped area with sampled color -board = board.copy() color = board[330, 90] board[60:151, 135:481] = color fig, ax = plt.subplots() @@ -557,19 +556,19 @@ as shown in the final image produced by the program: > > """ > > > > # load and display original image -> > root = iio.imread(uri="data/maize-root-cluster.jpg") +> > maize_roots = iio.imread(uri="data/maize-root-cluster.jpg") > > fig, ax = plt.subplots() -> > plt.imshow(root) +> > plt.imshow(maize_roots) > > > > # extract, display, and save sub-image > > # WRITE YOUR CODE TO SELECT THE SUBIMAGE NAME clip HERE: -> > clip = root[0:400, 275:550, :] +> > clipped_maize = maize_roots[0:400, 275:550, :] > > fig, ax = plt.subplots() -> > plt.imshow(clip) +> > plt.imshow(clipped_maize) > > > > > > # WRITE YOUR CODE TO SAVE clip HERE -> > iio.imwrite(uri="data/clip.jpg", image=clip) +> > iio.imwrite(uri="data/clipped_maize.jpg", image=clipped_maize) > > ~~~ > > {: .language-python} > {: .solution} From a76c86e98c06831ced4d4b7b9aa3fc576c0a0d22 Mon Sep 17 00:00:00 2001 From: Ulf Schiller Date: Thu, 13 Apr 2023 17:03:08 -0400 Subject: [PATCH 5/7] Update image variable names in episode 4 --- _episodes/04-drawing.md | 79 +++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/_episodes/04-drawing.md b/_episodes/04-drawing.md index c8855a926..446a22ec9 100644 --- a/_episodes/04-drawing.md +++ b/_episodes/04-drawing.md @@ -76,10 +76,10 @@ image: ~~~ # Load and display the original image -image = iio.imread(uri="data/maize-seedlings.tif") +maize_seedlings = iio.imread(uri="data/maize-seedlings.tif") fig, ax = plt.subplots() -plt.imshow(image) +plt.imshow(maize_seedlings) ~~~ {: .language-python} @@ -96,7 +96,7 @@ The next section of code shows how: ~~~ # Create the basic mask -mask = np.ones(shape=image.shape[0:2], dtype="bool") +mask = np.ones(shape=maize_seedlings.shape[0:2], dtype="bool") ~~~ {: .language-python} @@ -193,7 +193,7 @@ The function returns the rectangle as row (`rr`) and column (`cc`) coordinate ar > > ~~~ > # create the black canvas -> image = np.zeros(shape=(600, 800, 3), dtype="uint8") +> canvas = np.zeros(shape=(600, 800, 3), dtype="uint8") > ~~~ > {: .language-python} > @@ -207,8 +207,8 @@ The function returns the rectangle as row (`rr`) and column (`cc`) coordinate ar > > > > ~~~ > > # Draw a blue circle with centre (200, 300) in (ry, cx) coordinates, and radius 100 -> > rr, cc = skimage.draw.disk(center=(200, 300), radius=100, shape=image.shape[0:2]) -> > image[rr, cc] = (0, 0, 255) +> > rr, cc = skimage.draw.disk(center=(200, 300), radius=100, shape=canvas.shape[0:2]) +> > canvas[rr, cc] = (0, 0, 255) > > ~~~ > > {: .language-python} > > @@ -217,14 +217,14 @@ The function returns the rectangle as row (`rr`) and column (`cc`) coordinate ar > > ~~~ > > # Draw a green line from (400, 200) to (500, 700) in (ry, cx) coordinates > > rr, cc = skimage.draw.line(r0=400, c0=200, r1=500, c1=700) -> > image[rr, cc] = (0, 255, 0) +> > canvas[rr, cc] = (0, 255, 0) > > ~~~ > > {: .language-python} > > > > ~~~ > > # Display the image > > fig, ax = plt.subplots() -> > plt.imshow(image) +> > plt.imshow(canvas) > > ~~~ > > {: .language-python} > > @@ -240,7 +240,7 @@ The function returns the rectangle as row (`rr`) and column (`cc`) coordinate ar > > import random > > > > # create the black canvas -> > image = np.zeros(shape=(600, 800, 3), dtype="uint8") +> > canvas = np.zeros(shape=(600, 800, 3), dtype="uint8") > > > > # draw a blue circle at a random location 15 times > > for i in range(15): @@ -248,13 +248,13 @@ The function returns the rectangle as row (`rr`) and column (`cc`) coordinate ar > > random.randrange(600), > > random.randrange(800)), > > radius=50, -> > shape=image.shape[0:2], +> > shape=canvas.shape[0:2], > > ) -> > image[rr, cc] = (0, 0, 255) +> > canvas[rr, cc] = (0, 0, 255) > > > > # display the results > > fig, ax = plt.subplots() -> > plt.imshow(image) +> > plt.imshow(canvas) > > ~~~ > > {: .language-python} > > @@ -278,7 +278,7 @@ The function returns the rectangle as row (`rr`) and column (`cc`) coordinate ar > > random.randrange(600), > > random.randrange(800)), > > radius=50, -> > shape=image.shape[0:2], +> > shape=canvas.shape[0:2], > > ) > > color = (0, 0, 255) > > elif x < 0.66: @@ -295,15 +295,15 @@ The function returns the rectangle as row (`rr`) and column (`cc`) coordinate ar > > rr, cc = skimage.draw.rectangle( > > start=(random.randrange(600), random.randrange(800)), > > extent=(50, 50), -> > shape=image.shape[0:2], +> > shape=canvas.shape[0:2], > > ) > > color = (255, 0, 0) > > -> > image[rr, cc] = color +> > canvas[rr, cc] = color > > > > # display the results > > fig, ax = plt.subplots() -> > plt.imshow(image) +> > plt.imshow(canvas) > > ~~~ > > {: .language-python} > {: .solution} @@ -340,10 +340,10 @@ We load the original image and create the mask in the same way as before: ~~~ # Load the original image -image = iio.imread(uri="data/maize-seedlings.tif") +maize_seedlings = iio.imread(uri="data/maize-seedlings.tif") # Create the basic mask -mask = np.ones(shape=image.shape[0:2], dtype="bool") +mask = np.ones(shape=maize_seedlings.shape[0:2], dtype="bool") # Draw a filled rectangle on the mask image rr, cc = skimage.draw.rectangle(start=(357, 44), end=(740, 720)) @@ -356,7 +356,7 @@ where the mask is `True`: ~~~ # Apply the mask -image[mask] = 0 +maize_seedlings[mask] = 0 ~~~ {: .language-python} @@ -364,7 +364,7 @@ Then, we display the masked image. ~~~ fig, ax = plt.subplots() -plt.imshow(image) +plt.imshow(maize_seedlings) ~~~ {: .language-python} @@ -395,22 +395,22 @@ The resulting masked image should look like this: > > > > ~~~ > > # Load the image -> > image = iio.imread(uri="data/remote-control.jpg") -> > image = np.array(image) +> > remote = iio.imread(uri="data/remote-control.jpg") +> > remote = np.array(remote) > > > > # Create the basic mask -> > mask = np.ones(shape=image.shape[0:2], dtype="bool") +> > mask = np.ones(shape=remote.shape[0:2], dtype="bool") > > > > # Draw a filled rectangle on the mask image > > rr, cc = skimage.draw.rectangle(start=(93, 1107), end=(1821, 1668)) > > mask[rr, cc] = False > > > > # Apply the mask -> > image[mask] = 0 +> > remote[mask] = 0 > > > > # Display the result > > fig, ax = plt.subplots() -> > plt.imshow(image) +> > plt.imshow(remote) > > ~~~ > > {: .language-python} > {: .solution} @@ -422,11 +422,12 @@ The resulting masked image should look like this: > > ~~~ > # Load the image -> image = iio.imread(uri="data/wellplate-01.jpg") +> wellplate = iio.imread(uri="data/wellplate-01.jpg") +> wellplate = np.array(wellplate) > > # Display the image > fig, ax = plt.subplots() -> plt.imshow(image) +> plt.imshow(wellplate) > ~~~ > {: .language-python} > @@ -450,11 +451,11 @@ The resulting masked image should look like this: > > > > ~~~ > > # read in original image -> > image = iio.imread(uri="data/wellplate-01.jpg") -> > image = np.array(image) +> > wellplate = iio.imread(uri="data/wellplate-01.jpg") +> > wellplate = np.array(wellplate) > > > > # create the mask image -> > mask = np.ones(shape=image.shape[0:2], dtype="bool") +> > mask = np.ones(shape=wellplate.shape[0:2], dtype="bool") > > > > # open and iterate through the centers file... > > with open("data/centers.txt", "r") as center_file: @@ -465,15 +466,15 @@ The resulting masked image should look like this: > > ry = int(coordinates[1]) > > > > # ... and drawing a circle on the mask -> > rr, cc = skimage.draw.disk(center=(ry, cx), radius=16, shape=image.shape[0:2]) +> > rr, cc = skimage.draw.disk(center=(ry, cx), radius=16, shape=wellplate.shape[0:2]) > > mask[rr, cc] = False > > > > # apply the mask -> > image[mask] = 0 +> > wellplate[mask] = 0 > > > > # display the result > > fig, ax = plt.subplots() -> > plt.imshow(image) +> > plt.imshow(wellplate) > > ~~~ > > {: .language-python} > > @@ -507,11 +508,11 @@ The resulting masked image should look like this: > > > > ~~~ > > # read in original image -> > image = iio.imread(uri="data/wellplate-01.jpg") -> > image = np.array(image) +> > wellplate = iio.imread(uri="data/wellplate-01.jpg") +> > wellplate = np.array(wellplate) > > > > # create the mask image -> > mask = np.ones(shape=image.shape[0:2], dtype="bool") +> > mask = np.ones(shape=wellplate.shape[0:2], dtype="bool") > > > > # upper left well coordinates > > cx0 = 91 @@ -531,18 +532,18 @@ The resulting masked image should look like this: > > for col in range(8): > > > > # ... and drawing a circle on the mask -> > rr, cc = skimage.draw.disk(center=(ry, cx), radius=16, shape=image.shape[0:2]) +> > rr, cc = skimage.draw.disk(center=(ry, cx), radius=16, shape=wellplate.shape[0:2]) > > mask[rr, cc] = False > > cx += deltaCX > > # after one complete row, move to next row > > ry += deltaRY > > > > # apply the mask -> > image[mask] = 0 +> > wellplate[mask] = 0 > > > > # display the result > > fig, ax = plt.subplots() -> > plt.imshow(image) +> > plt.imshow(wellplate) > > ~~~ > > {: .language-python} > {: .solution} From f341e4e7191a12ccd199525dc080afbb85fc866d Mon Sep 17 00:00:00 2001 From: Ulf Schiller Date: Thu, 13 Apr 2023 17:28:33 -0400 Subject: [PATCH 6/7] Update image variable names in episodes 5 and 7 --- _episodes/05-creating-histograms.md | 34 +++++++++++++------------- _episodes/07-thresholding.md | 38 ++++++++++++++--------------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/_episodes/05-creating-histograms.md b/_episodes/05-creating-histograms.md index 20e3eab5a..b2d960e6d 100644 --- a/_episodes/05-creating-histograms.md +++ b/_episodes/05-creating-histograms.md @@ -59,14 +59,14 @@ Here we load the image in grayscale instead of full colour, and display it: ~~~ # read the image of a plant seedling as grayscale from the outset -image = iio.imread(uri="data/plant-seedling.jpg", mode="L") +plant_seedling = iio.imread(uri="data/plant-seedling.jpg", mode="L") # convert the image to float dtype with a value range from 0 to 1 -image = skimage.util.img_as_float(image) +plant_seedling = skimage.util.img_as_float(plant_seedling) # display the image fig, ax = plt.subplots() -plt.imshow(image, cmap="gray") +plt.imshow(plant_seedling, cmap="gray") ~~~ {: .language-python} @@ -83,7 +83,7 @@ which, after all, is a NumPy array: ~~~ # create the histogram -histogram, bin_edges = np.histogram(image, bins=256, range=(0, 1)) +histogram, bin_edges = np.histogram(plant_seedling, bins=256, range=(0, 1)) ~~~ {: .language-python} @@ -193,14 +193,14 @@ it produces this histogram: > > ~~~ > > > > # read the image as grayscale from the outset -> > image = iio.imread(uri="data/plant-seedling.jpg", mode="L") +> > plant_seedling = iio.imread(uri="data/plant-seedling.jpg", mode="L") > > > > # display the image > > fig, ax = plt.subplots() -> > plt.imshow(image, cmap="gray") +> > plt.imshow(plant_seedling, cmap="gray") > > > > # create mask here, using np.zeros() and skimage.draw.rectangle() -> > mask = np.zeros(shape=image.shape, dtype="bool") +> > mask = np.zeros(shape=plant_seedling.shape, dtype="bool") > > rr, cc = skimage.draw.rectangle(start=(199, 410), end=(384, 485)) > > mask[rr, cc] = True > > @@ -209,7 +209,7 @@ it produces this histogram: > > plt.imshow(mask, cmap="gray") > > > > # mask the image and create the new histogram -> > histogram, bin_edges = np.histogram(image[mask], bins=256, range=(0.0, 1.0)) +> > histogram, bin_edges = np.histogram(plant_seedling[mask], bins=256, range=(0.0, 1.0)) > > > > # configure and draw the histogram figure > > plt.figure() @@ -240,11 +240,11 @@ A program to create colour histograms starts in a familiar way: ~~~ # read original image, in full color -image = iio.imread(uri="data/plant-seedling.jpg") +plant_seedling = iio.imread(uri="data/plant-seedling.jpg") # display the image fig, ax = plt.subplots() -plt.imshow(image) +plt.imshow(plant_seedling) ~~~ {: .language-python} @@ -266,7 +266,7 @@ plt.figure() plt.xlim([0, 256]) for channel_id, color in enumerate(colors): histogram, bin_edges = np.histogram( - image[:, :, channel_id], bins=256, range=(0, 256) + plant_seedling[:, :, channel_id], bins=256, range=(0, 256) ) plt.plot(bin_edges[0:-1], histogram, color=color) @@ -362,11 +362,11 @@ Finally we label our axes and display the histogram, shown here: > > ~~~ > # read the image -> image = iio.imread(uri="data/wellplate-02.tif") +> wellplate = iio.imread(uri="data/wellplate-02.tif") > > # display the image > fig, ax = plt.subplots() -> plt.imshow(image) +> plt.imshow(wellplate) > ~~~ > {: .language-python} > ![Well plate image](../fig/wellplate-02.jpg) @@ -393,14 +393,14 @@ Finally we label our axes and display the histogram, shown here: > > > > ~~~ > > # create a circular mask to select the 7th well in the first row -> > mask = np.zeros(shape=image.shape[0:2], dtype="bool") -> > circle = skimage.draw.disk(center=(240, 1053), radius=49, shape=image.shape[0:2]) +> > mask = np.zeros(shape=wellplate.shape[0:2], dtype="bool") +> > circle = skimage.draw.disk(center=(240, 1053), radius=49, shape=wellplate.shape[0:2]) > > mask[circle] = 1 > > > > # just for display: > > # make a copy of the image, call it masked_image, and > > # use np.logical_not() and indexing to apply the mask to it -> > masked_img = np.array(image) +> > masked_img = wellplate[:] > > masked_img[np.logical_not(mask)] = 0 > > > > # create a new figure and display masked_img, to verify the @@ -419,7 +419,7 @@ Finally we label our axes and display the histogram, shown here: > > # use your circular mask to apply the histogram > > # operation to the 7th well of the first row > > histogram, bin_edges = np.histogram( -> > image[:, :, channel_id][mask], bins=256, range=(0, 256) +> > wellplate[:, :, channel_id][mask], bins=256, range=(0, 256) > > ) > > > > plt.plot(histogram, color=color) diff --git a/_episodes/07-thresholding.md b/_episodes/07-thresholding.md index 6e5cb5f36..969adb58b 100644 --- a/_episodes/07-thresholding.md +++ b/_episodes/07-thresholding.md @@ -67,10 +67,10 @@ crudely cut shapes set against a white background. ~~~ # load the image -image = iio.imread(uri="data/shapes-01.jpg") +shapes01 = iio.imread(uri="data/shapes-01.jpg") fig, ax = plt.subplots() -plt.imshow(image) +plt.imshow(shapes01) ~~~ {: .language-python} @@ -93,13 +93,13 @@ and de-noise it as in [the _Blurring Images_ episode]({{ page.root }}{% link _ep ~~~ # convert the image to grayscale -gray_image = skimage.color.rgb2gray(image) +gray_shapes = skimage.color.rgb2gray(shapes01) # blur the image to denoise -blurred_image = skimage.filters.gaussian(gray_image, sigma=1.0) +blurred_shapes = skimage.filters.gaussian(gray_shapes, sigma=1.0) fig, ax = plt.subplots() -plt.imshow(blurred_image, cmap="gray") +plt.imshow(blurred_shapes, cmap="gray") ~~~ {: .language-python} @@ -124,7 +124,7 @@ The histogram for the shapes image shown above can be produced as in ~~~ # create a histogram of the blurred grayscale image -histogram, bin_edges = np.histogram(blurred_image, bins=256, range=(0.0, 1.0)) +histogram, bin_edges = np.histogram(blurred_shapes, bins=256, range=(0.0, 1.0)) fig, ax = plt.subplots() plt.plot(bin_edges[0:-1], histogram) @@ -162,7 +162,7 @@ where the `False` entries are shown as black pixels ~~~ # create a mask based on the threshold t = 0.8 -binary_mask = blurred_image < t +binary_mask = blurred_shapes < t fig, ax = plt.subplots() plt.imshow(binary_mask, cmap="gray") @@ -205,7 +205,7 @@ What we are left with is only the coloured shapes from the original. ~~~ # use the binary_mask to select the "interesting" part of the image -selection = image.copy() +selection = shapes01.copy() selection[~binary_mask] = 0 fig, ax = plt.subplots() @@ -232,8 +232,8 @@ plt.imshow(selection) > > The histogram for the `data/shapes-02.jpg` image can be shown with > > > > ~~~ -> > gray_image = iio.imread(uri="data/shapes-02.jpg", mode="L") -> > histogram, bin_edges = np.histogram(gray_image, bins=256, range=(0.0, 1.0)) +> > gray_shapes = iio.imread(uri="data/shapes-02.jpg", mode="L") +> > histogram, bin_edges = np.histogram(gray_shapes, bins=256, range=(0.0, 1.0)) > > > > fig, ax = plt.subplots() > > plt.plot(bin_edges[0:-1], histogram) @@ -265,7 +265,7 @@ plt.imshow(selection) > > Here are the commands to create and view the binary mask > > ~~~ > > t = 0.5 -> > binary_mask = gray_image > t +> > binary_mask = gray_shapes > t > > > > fig, ax = plt.subplots() > > plt.imshow(binary_mask, cmap="gray") @@ -276,8 +276,8 @@ plt.imshow(selection) > > > > And here are the commands to apply the mask and view the thresholded image > > ~~~ -> > image = iio.imread(uri="data/shapes-02.jpg") -> > selection = image.copy() +> > shapes02 = iio.imread(uri="data/shapes-02.jpg") +> > selection = shapes02.copy() > > selection[~binary_mask] = 0 > > > > fig, ax = plt.subplots() @@ -312,10 +312,10 @@ we have seen before in [the _Image Representation in skimage_ episode]({{ page.root }}{% link _episodes/03-skimage-images.md %}). ~~~ -image = iio.imread(uri="data/maize-root-cluster.jpg") +maize_roots = iio.imread(uri="data/maize-root-cluster.jpg") fig, ax = plt.subplots() -plt.imshow(image) +plt.imshow(maize_roots) ~~~ {: .language-python} @@ -326,7 +326,7 @@ Let us look at the grayscale histogram of the denoised image. ~~~ # convert the image to grayscale -gray_image = skimage.color.rgb2gray(image) +gray_image = skimage.color.rgb2gray(maize_roots) # blur the image to denoise blurred_image = skimage.filters.gaussian(gray_image, sigma=1.0) @@ -391,7 +391,7 @@ Finally, we use the mask to select the foreground: ~~~ # apply the binary mask to select the foreground -selection = image.copy() +selection = maize_roots.copy() selection[~binary_mask] = 0 fig, ax = plt.subplots() @@ -687,8 +687,8 @@ data/trial-293.jpg,0.13607895611702128 > > ## Solution > > Here is the code to create the grayscale histogram: > > ~~~ -> > image = iio.imread(uri="data/colonies-01.tif") -> > gray_image = skimage.color.rgb2gray(image) +> > bacteria = iio.imread(uri="data/colonies-01.tif") +> > gray_image = skimage.color.rgb2gray(bacteria) > > blurred_image = skimage.filters.gaussian(gray_image, sigma=1.0) > > histogram, bin_edges = np.histogram(blurred_image, bins=256, range=(0.0, 1.0)) > > fig, ax = plt.subplots() From ad3d083f079a408c7ef75ee36cf1136247442e88 Mon Sep 17 00:00:00 2001 From: Ulf Schiller Date: Thu, 13 Apr 2023 18:55:42 -0400 Subject: [PATCH 7/7] Add some notes on Jupyter notebooks and variable names to instructor guide --- _extras/guide.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/_extras/guide.md b/_extras/guide.md index 21fce04c5..eac6fc7c5 100644 --- a/_extras/guide.md +++ b/_extras/guide.md @@ -2,6 +2,16 @@ title: "Instructor Notes" --- +## Working with Jupyter notebooks + +* This lesson is designed to be taught using Jupyter notebooks. We recommend that instructors guide learners to create a new Jupyter note for each episode. + +* Python `import` statements typically appear in the first code block near the top of each episode. In some cases, the purpose of specific libraries is briefly explained as part of the exercises. + +* The possibility of executing the code cells in a notebook in arbitrary order can cause confusion. Using the "restart kernel and run all cells" feature is one way to accomplish linear execution of the notebook and may help to locate and identify coding issues. + +* Many episodes in this lesson load image files from disk. To avoid name clashes in episodes that load multiple different files, we have used unique variable names (instead of generic names such as `image` or `img`). When copying code snippets between exercises, the variable names may have to be changed. The maintainers are keen to receive feedback whether this convention proves practical in workshops. + ## Working with skimage * Be aware, that learners might get surprising results in the *Keeping only low intensity pixels* exercise, if `plt.imshow` is called without the `vmax` parameter.