library(BioC2015Oles) library(knitr) opts_chunk$set(error=FALSE) set.seed(7) .dpi = 100
Learn how to read and write images in and out of R
Learn how images are represented in R and how to manipulate them
Understand how to apply filters and transformations to images
Apply these skills to microscopy images of cells to do segmentation and feature extraction
Explore spatial distributions of the position of cells
Since Bioconductor 1.8 (2006)
### Original developers: Oleg Sklyar Wolfgang Huber Mike Smith Gregoire Pau | ### Contributors: Joseph Barry Bernd Fischer Ilia Kats Philip A. Marais |  |
library(EBImage) f = system.file("images", "sample.png", package="EBImage") img = readImage(f) display(img)
Images can be read from local files or URLs.
bioc = readImage("http://www.bioconductor.org/images/logo/jpg/bioconductor_logo_rgb.jpg") display(bioc)
 | *EBImage* supports JPEG, PNG and TIFF file formats. For reading proprietary microscopy image data and metadata use *[RBioFormats](https://github.com/aoles/RBioFormats)*. |
The default display
method can be set by options(EBImage.display)
.
options(EBImage.display = "raster")
display(img, method = "raster") text(x = 20, y = 20, label = "Parrots", adj = c(0,1), col = "orange", cex = 2) filename = "parrots.jpg" dev.print(jpeg, filename = filename , width = dim(img)[1], height = dim(img)[2]) ```r file.size(filename)
Supported file formats: JPEG, PNG and TIFF.
writeImage(img, "sample.jpeg", quality = 85) writeImage(img, "sample.tiff") writeImage(img, "sample_compressed.tiff", compression = "deflate") files = list.files(pattern = "sample*") data.frame(row.names=files, size=file.size(files))
Multi-dimensional pixel intensity arrays - (x, y) - (x, y, **z**) z-stack - (x, y, **t**) time-lapse - (x, y, **c**) channels - (x, y, c, z, t, ...) |  |
 |  |
str(img) getClassDef("Image") dim(img)
img imageData(img)[1:3, 1:6]
hist(img) range(img)
f = system.file("images", "sample-color.png", package="EBImage") imgcol = readImage(f) display(imgcol) print(imgcol, short = TRUE)
nuc = readImage(system.file("images", "nuclei.tif", package="EBImage")) ```r nuc = readImage(system.file("images", "nuclei.tif", package="EBImage")) print(nuc, short = TRUE) display(nuc)
display(nuc, method = "raster", all = TRUE)
Being numeric arrays, images can be conveniently manipulated by any of R's arithmetic operators.
img = img[366:749, 58:441]
img_neg = max(img) - img display(img_neg)
img_comb = combine( img, img + 0.3, img * 2, img ^ 0.5 ) display( tile(img_comb, numberOfFrames(img_comb), lwd = 20, fg.col = "white") )
Images which contain only two sets of pixels, which represent the background and the foreground pixels.
img_thresh = img > .5 display(img_thresh)
Images which contain only two sets of pixels, which represent the background and the foreground pixels.
img_thresh
img_translate = translate(img, v = c(100, -50)) display(img_translate)
img_rotate = rotate(img, 30) ```r img_rotate = rotate(img, angle = 30, bg.col = "white") display(img_rotate)
img_resize = resize(img, w = 512, h = 256) display(img_resize) ```r img_resize = resize(img, 256) display(img_resize)
display( flip(img) ) display( flop(img) )
Described by a 3x2 transformation matrix $\textbf{m}$
Example: horizontal sheer mapping
angle = pi/6 m = matrix(c(1, -sin(angle), sin(angle)*dim(img)[2]/2, 0, 1, 0), nrow = 3, ncol = 2) m img_affine = affine(img, m) display(img_affine)
imgcol_t = transpose(imgcol) display(imgcol_t)
The weight function can be generated using makeBrush
.
opts_knit$set(global.par=TRUE) ```r .par=par(mai = c(.45, .75, 0.05, 0.05)) ```r w = makeBrush(size = 31, shape = 'gaussian', sigma = 5) plot(w[(nrow(w)+1)/2, ], ylab = "w", xlab = "")
Other available brush shapes: "box"
(default), "disc"
, "diamond"
, "line"
2D linear convolution is implemented by filter2
(uses FFT)
Example: Smoothing an image using a Gaussian filter of width 5
opts_knit$set(global.par=FALSE) ```r img_flo = filter2(img, w) display(img_flo)
Detecting edges and sharpening images
fhi = matrix(1, nrow = 3, ncol = 3) fhi[2, 2] = -8 fhi img_fhi = filter2(img, fhi) display(img_fhi)
Compensate for spatial dependencies of the background signal
disc = makeBrush(21, "disc") disc = disc / sum(disc) nuc = getFrame(nuc, 1) nuc_bg = filter2(nuc, disc) offset = 0.02 nuc_thresh = (nuc - nuc_bg) > offset img_comb = combine(nuc, nuc_bg, nuc_thresh) display( tile(img_comb, numberOfFrames(img_comb), lwd = 20, fg.col = "white") )
Non-linear noise removal technique
l = length(img) n = l/10 img_noisy = img img_noisy[sample(l, n)] = runif(n, min = 0, max = 1) img_median = medianFilter(img_noisy, size = 1) display( combine(img_noisy, img_median), all=TRUE)
Implemented using the constant time algorithm [@Perreault2007].
Non-linear filtering of binary images
leaf = readImage( system.file('images', 'leaf.png', package='BioC2015Oles') ) .leafDim = BioC2015Oles:::tilesDim(dim(leaf), 3) ```r leaf = readImage( system.file('images', 'leaf.png', package='BioC2015Oles') ) kern = makeBrush(size = 3) morph = combine( leaf, erode(leaf, kern), dilate(leaf, kern) ) displayTiles(morph)
morph = combine( leaf, opening(leaf, kern), closing(leaf, kern) ) displayTiles(morph)
Fluorescent microscopy images from two channels of HeLa cells.
dna = readImage(system.file("images", "nuclei.tif", package="EBImage")) print(dna, short=TRUE) tub = readImage(system.file("images", "cells.tif", package="EBImage")) print(tub, short=TRUE)
display( combine(getFrame(dna, 3), getFrame(tub, 3)), all=TRUE ) ```r rgb = rgbImage(green = 1.5 * tub, blue = dna) displayTiles(rgb)
nmaskt = thresh(dna, w = 15, h = 15, offset = 0.05) nmaskf = fillHull( opening(nmaskt, makeBrush(5, shape='disc')) ) display( combine(getFrame(nmaskt, 3), getFrame(nmaskf, 3)), all=TRUE )
dmap = distmap(nmaskf) range(dmap) display(normalize(dmap), frame = 3)
nmask = watershed(dmap, tolerance = 2) display( combine( toRGB( getFrame(dna, 3) ), colorLabels( getFrame(nmask, 3) ) ), all=TRUE )
bwlabel
- a simpler and faster function for segmenting connected objects
Identification of cell bodies by Voronoi partitioning using the segmented nuclei as seeds.
cmaskt = closing( gblur(tub, 1) > 0.105, makeBrush(5, shape='disc') ) cmask = propagate(tub, seeds=nmask, mask=cmaskt, lambda = 0.001) display( combine( toRGB( getFrame(cmaskt, 3) ), colorLabels( getFrame(cmask, 3) ) ), all=TRUE )
Voronoi diagram is a partitioning of a plane into regions based on distance to some specific points of that plane (seeds).
mask
)display( paintObjects(nmask, paintObjects(cmask, rgb, col = "magenta", thick = TRUE), col = "yellow", thick = TRUE), all = TRUE)
st = stackObjects(cmask, rgb) display(st, all = TRUE)
Quantitative cellular descriptors
computeFeatures.basic
computeFeatures.shape
computeFeatures.moment
computeFeatures.haralick
head( computeFeatures.shape(cmask[,,1], tub[,,1]) )
Using multivariate analysis methods we can:
Lymph nodes
wzxhzdk:39 |
Breast cancer lymph node biopsy [@Setiadi2010].
Cell typing was done by staining the cells with protein antibodies that provide specific signatures.
|
data(brcalymphnode, package = "BioC2015Oles") head(brcalymphnode) nrow(brcalymphnode) table(brcalymphnode$class)
Plot of the x and y positions of the T cells (left) and tumor cells (right)
par(mfrow = c(1, 2), mar = c(4.5, 4.5, 0.5, 0.5)) xlim = range(brcalymphnode$x) ylim = range(brcalymphnode$y) cols = c(`T_cells` = "dodgerblue4", `Tumor` = "darkmagenta") for(i in seq_along(cols)) plot(subset(brcalymphnode, class==names(cols)[i])[, c("x", "y")], pch = ".", asp = 1, xlim = xlim, ylim = ylim, col = cols[i])
Marked spatial point process:
xlim
, ylim
)class
)library("spatstat") ln = with(brcalymphnode, ppp(x = x, y = y, marks = class, xrange = xlim, yrange = ylim) ) ln
chull = convexhull(ln) par(mar = c(0, 0, 0, 0)) plot(Window(ln), main = NULL, asp = 1) plot(chull, lty = 2, col = "lightblue", add = TRUE) Window(ln) = chull ln
Number of points lying in a circle of area $a$ around a point $p=(x,y)$ $$N(p, a)$$
Local intensity $$\lambda(p) = \lim_{a\rightarrow 0} \frac{E[ N(p, a)]}{a}$$
For a stationary process, i.e., homogeneous all over the region $$\lambda(p) = \text{const.}$$ Then the intensity in an area $A$ is proportional to the area $$E(N(\cdot, A)) = \lambda A$$
Kernel smoothed intensity estimate of a point pattern [@Diggle1985] $$\hat{\lambda}(p) = \sum_i e(p_i) K(p-p_i)$$ where $K$ is the Gaussian smoothing kernel, and $e(p_i)$ is an edge correction factor.
densities = solist( `Diggle's edge correction` = density(subset(ln, marks=="Tumor"), diggle = TRUE), `No edge correction` = density(subset(ln, marks=="Tumor"), edge = FALSE) ) plot(densities, equal.ribbon = TRUE, col = topo.colors, main = "")
Estimate of the spatially-varying probability of a particular event type
rr = relrisk(ln, sigma = 250) plot(rr, equal.ribbon = TRUE, col = topo.colors, nrows = 1, main = "")
Spatial clustering (or anticlustering) of points: whether and to what extent neighboring points are more/less dense than expected by chance.
Cumulative distribution function of the distance $W$ from a typical random point to its nearest neighbor. For a Poisson process
$$G(r) = P(W \leq r) = 1-e^{-\lambda \pi r^2}$$
gln = Gest(ln) gln
library(RColorBrewer) par(mar = c(4.5, 4.5, 0.5, 0.5)) plot(gln, lty = 1, col = brewer.pal(4, "Set1"), main = "")
For a stationary point process $\lambda K(r)$ is the expected number of additional points within a distance $r$ of a given, randomly picked point.
Lln = Linhom( subset(ln, marks=="T_cells") ) Lln ```r data(Lln, package = "BioC2015Oles") Lln
par(mar = c(4.5, 4.5, 0.5, 0.5)) plot(Lln, lty = 1, col = brewer.pal(3, "Set1"), main = "")
Describes how point density varies as a function of distance from a reference point.
For a stationary Poisson process $g(r) = 1$.
pcfln = pcf( Kinhom(subset(ln, marks=="T_cells")) ) plot(pcfln, lty = 1, log = "x") ```r par(mar = c(4.5, 4.5, 0.5, 0.5)) data(pcfln, package = "BioC2015Oles") plot(pcfln, lty = 1, log = "x", main = "")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.