From 3ad1ed3a285cff9abfe29a50934ef0ffc2bf6d13 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 18 Aug 2012 23:09:47 -0400 Subject: [PATCH] DOC: Remove peak detection tutorial. The tutorial needs a lot of work and isn't a crucial part of this PR. Note: tutorial saved in a separate branch. --- .../plot_peak_detection_comparison.py | 231 ------------------ skimage/data/noisy_circles.jpg | Bin 26206 -> 0 bytes 2 files changed, 231 deletions(-) delete mode 100644 doc/examples/applications/plot_peak_detection_comparison.py delete mode 100644 skimage/data/noisy_circles.jpg diff --git a/doc/examples/applications/plot_peak_detection_comparison.py b/doc/examples/applications/plot_peak_detection_comparison.py deleted file mode 100644 index 8fe26c02..00000000 --- a/doc/examples/applications/plot_peak_detection_comparison.py +++ /dev/null @@ -1,231 +0,0 @@ -""" -============== -Peak detection -============== - -Peak detection (a.k.a. spot detection or particle detection) is a common -image analysis step. For example, it's used to detect tracer particles in a -flow for particle image velocimetry (i.e. PIV) and to identify features in -the Hough transform. - -To simplify plotting code, let's define a simple function that creates a new -figure on each call, and removes tick labels. -""" - -import matplotlib.pyplot as plt - -plt.rcParams['axes.titlesize'] = 10 -plt.rcParams['font.size'] = 10 -def imshow(image, **kwargs): - plt.figure(figsize=(2.5, 2.5)) - plt.imshow(image, **kwargs) - plt.axis('off') - -""" -To explore different peak detection techniques, we use an image of circles with -added noise: -""" - -from skimage import data -img = data.load('noisy_circles.jpg') -imshow(img) - -""" - -.. image:: PLOT2RST.current_figure - -This image is noisy and has uneven background illumination. The peaks in the -image, while readily identified by eye, can be tricky to find algorithmically. -The first thing we need to do is remove the high-frequency noise; this can -be done with a simple Gaussian filter. -""" - -import scipy.ndimage as ndimg -img_smooth = ndimg.gaussian_filter(img, 3) - -imshow(img_smooth) - -""" - -.. image:: PLOT2RST.current_figure - -Thresholding -============ - -One way to extract the background is to threshold the image. -""" - -thresh_value = 100 -background = img_smooth.copy() -background[img_smooth > thresh_value] = 0 -peaks = img_smooth - background - -""" -Here, all pixels values below the threshold value are subtracted from the -image. The resulting background image and the extracted peaks are shown below. -""" - -imshow(background, vmin=0, vmax=255) -plt.title("background image (thresholding)") - -""" -.. image:: PLOT2RST.current_figure -""" - -imshow(peaks, vmin=0, vmax=255) -plt.title("peaks (thresholding)") - -""" -.. image:: PLOT2RST.current_figure - -Because of uneven illumination, peaks on the right bleed into each other. -Increasing the threshold will fix this problem, but it will also cause some -peaks on the left to go undetected. - -Morphological reconstruction -============================ - -Morphological reconstruction uses two images: a seed image and a mask image. -Initially, all values of the reconstructed image start off pixel at the values -of the seed image. A seed pixels of high intensity spread outwards until it -hits the mask image (i.e. the mask value for a pixel is lower than the -high-intensity value). Note that the mask is a gray-scale image that limits the -maximum intensity at a pixel. This algorithm is clearer with pictures, which -we generate below. - -One common case uses mask and seed images derived from the same image but -shifted in intensity. Note: be careful when shifting images integer values, -since this can lead to under/overflow of values. To prevent the uint8 image we -started with from underflowing during subtraction, we first convert to float: -""" - -from skimage import img_as_float -img_r = img_as_float(img_smooth) - -import skimage.morphology as morph -h = 0.1 -rec = morph.reconstruction(img_r-h, img_r) - -imshow(img_r, vmin=0, vmax=1) -plt.title("original (smoothed) image") - -""" -.. image:: PLOT2RST.current_figure -""" - -imshow(rec, vmin=0, vmax=1) -plt.title("background image (reconstruction)") - -""" -.. image:: PLOT2RST.current_figure - -This reconstructed image looks pretty much like the original, except that the -peaks in the image are truncated. The reconstructed image can then be -subtracted from the original image to reveal the peaks of the image. -""" - -imshow(img_r-rec) -plt.title("h-dome of image") - -""" -.. image:: PLOT2RST.current_figure - -The result is known as the h-dome transformation [2]_, which extracts peaks of -height `h` from the original image. To better understand what's going on, -let's take a 1D slice along the middle of the image (cutting through peaks in -the image). -""" - -img_slice = img_r[99:100, :] -rec_slice = morph.reconstruction(img_slice-h, img_slice) - -""" -Plotting the reconstructed image (slice) next to the original image and the -seed image shed light on the reconstruction process -""" -plt.figure(figsize=(4, 3)) -plt.plot(img_slice[0], 'k', label='original image') -plt.plot(img_slice[0]-h, '0.5', label='seed image') -plt.plot(rec_slice[0], 'r', label='reconstructed') -plt.title("image slice") -plt.xlabel('x') -plt.ylabel('intensity') -plt.legend() - -""" -.. image:: PLOT2RST.current_figure - -Here, you see that morphological reconstruction dilates the seed image (i.e. -the `h`-shifted image) until it intersects the mask (original image). Note that -the peaks in the original image have very different intensity values (e.g. the -peak at x=200 and x=100 differ by about 80). Subtracting the reconstructed -image from the original image gives peaks of roughly equal intensity. Thus, the -h-dome transformation is quiet effective at removing uneven, dark backgrounds -from bright features. The inverse operation---the h-basin -transformation---should be used when removing bright backgrounds from dark -features. - - -White tophat -============ -""" - -selem = morph.disk(10) -opening = morph.opening(img_smooth, selem) -top_hat = img_smooth - opening - -imshow(opening, vmin=0, vmax=255) -plt.title("Greyscale opening of image") - -""" -.. image:: PLOT2RST.current_figure -""" - - -imshow(top_hat) -plt.title("Tophat with disk of r = 10") - -""" -.. image:: PLOT2RST.current_figure -""" - -selem = morph.disk(5) -top_hat = morph.white_tophat(img_smooth, selem) - -imshow(top_hat) -plt.title("Tophat with disk of r = 5") - -""" -.. image:: PLOT2RST.current_figure -""" - -selem = morph.square(20) -opening = morph.opening(img_smooth, selem) -# scikit's top hat filter uses uint8 and doesn't check for over(under)flow. -mask = opening > img_smooth -opening[mask] = img_smooth[mask] -top_hat = img_smooth - opening - -imshow(opening, vmin=0, vmax=255) -plt.title("Greyscale opening of image") - -""" -.. image:: PLOT2RST.current_figure -""" - -imshow(top_hat) -plt.title("Tophat with square of w = 10") - -plt.show() - -""" -.. image:: PLOT2RST.current_figure - - -References -========== - -.. [1] Crocker and Grier, Journal of Colloid and Interface Science (1996) -.. [2] Vincent, L., IEEE Transactions on Image Processing (1993) - -""" diff --git a/skimage/data/noisy_circles.jpg b/skimage/data/noisy_circles.jpg deleted file mode 100644 index a0f49d6767ca4ca3cfbef6c54c36039223d243ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26206 zcmeIa2UJr_*FSthBIOF9T@^x$B*3+R^b$&lAP{LPC@7*-A#_M+B81{axJp+6m7*X; znhHo$1BwDFy(!WJq?&+$L|XDc!E*2OywAVA-}=`2*7`hI=bR~f_UxJ2)ABpBnQxgN zgclA45zYaCsVT4*002&a8v+1O&;X?uv z;rsE%Ie9xcBagUxle~$p-abe@3l*fPy(7VkP7TRy-koJGfc4_pMeIXOAGIJvpF zxcRsLww-?mFE=;u4k1Co9fE>F{M=jD_t!Vizds>7+qd(;dHCRPzTe?+`0uO-{P%B3 z`2SBBFzW$+P9Ph|hC(C(Hhu_{AHp003;7$f5rPG!+y>dYK!I5o6o9b7wy|??a{aa) z^6!xlfDQU1k`I8uAW$|K+cpk%&TUX`B`}g73fnE9unl+AUQp6ELXrLVq}vY;qR=~z zH8?0K`$cx@aY!XwEPVLvNL1N*=V6qzeu|~jp=UWH)m>f3$D9|-FFx<~A73(%xtjZD z#kIzsiRHVMFM2{bwfffD#i3T{)3Ncx>6LBp}m1tqk@2fxT?{E|q*b1EfkNc$ayoQe zmE=73Q-uGy1Tue%z#IU$p<8+K16W`=Js*+RttVo8T&1M+5zto|xANeMOQ++hzIE$| z57%;T=9uu`R%*{$y=QBVa%$+AtE#_{s+5{`dST=uAMC=Hjh?F`<)t=?{Ta3mQ+m`u z@7X(!{+B&2MCILttpqx^Vy3E7#acf{4T>)okJ}Vvp!J)3rcvwoJyeDA!4EVfeeqN2 zl@ev-%Rha;`13tOCZ6LJP53f+EyKm#s7pj
  • F%n8k9it%ULC>PP!Y|GKDK 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 Q%i7-Ox?=fb6z04C0pd5rzW@LL