Search
Question: Only 1s created by erode()
0
gravatar for loki
15 months ago by
loki0
loki0 wrote:

I am trying to create eroded and dilated versions of a raster object with your EBImage package in R.
Dilation works fine with the following code:

library(raster)
par(mfrow = c(1,2))
r <- raster("C:/Program Files/R/R-3.2.3/doc/html/logo.jpg")
plot(r, main = "original image")
library(EBImage)
kEBIMAGE <- makeBrush(3, shape = "box")
rAr <- as.array(r, transpose = TRUE)
rIm <- as.Image(rAr[])
rErIm <- dilate(rIm, kern = kEBIMAGE)
rErAr <- as.array(rErIm)
rRas <- setValues(r, as.vector(aperm(rErAr)))
unique(rRas)
plot(rRas, main = "dilated image")

However, erode() only returns 0 and 1 for the cells of the array/raster:

library(raster)
par(mfrow = c(1,2))
r <- raster("C:/Program Files/R/R-3.2.3/doc/html/logo.jpg")
plot(r, main = "original image")

library(EBImage)
kEBIMAGE <- makeBrush(3, shape = "box")
rAr <- as.array(r, transpose = TRUE)
rIm <- as.Image(rAr[])
rErIm <- erode(rIm, kern = kEBIMAGE)
rErAr <- as.array(rErIm)
rRas <- setValues(r, as.vector(aperm(rErAr)))
unique(rRas)
plot(rRas, main = "dilated image")
> sessionInfo()
R version 3.3.0 (2016-05-03)
Platform: x86_64-w64-mingw32/x64 (64-bit)

Do you know this kind of behaviour? How can I fix it, or is it a bug?

ADD COMMENTlink modified 15 months ago by Andrzej Oleś670 • written 15 months ago by loki0
3
gravatar for Andrzej Oleś
15 months ago by
Andrzej Oleś670
EMBL Heidelberg, Germany
Andrzej Oleś670 wrote:

Hi Matthias,

thank you for your inquiry! The main problem with your approach is that the example RasterLayer image data is not properly normalized: it contains integer values in the range 0:255, whereas EBImage processing functions expect the data to be in the 0:1 range. In fact, you probably don't need to use raster at all to achieve the desired result. You could simplify your script by relying just on the functionality provided by EBImage, as in the following example. readImage outputs the image already properly normalized, so you don't need to worry about it yourself.

library(EBImage)

## load image data
path <- "C:/Program Files/R/R-3.2.3/doc/html/logo.jpg"
img <- readImage(path)
display(img, method="raster", interpolate=FALSE)

## perform the filtering
k <- makeBrush(3, shape = "box")

img_er <- erode(img, kern=k)
display(img_er, method="raster", interpolate=FALSE)

img_di <- dilate(img, kern=k)
display(img_di, method="raster", interpolate=FALSE)

Note that your example file is an RGB image containing 3 color channels: red, green and blue. Erosion/dilation is performed on each of the color channels separately. In case you would like to process in the overall intensity domain, you would convert the image first to grayscale and only then do the filtering.

img <- channel(img, mode="gray") #or alternatively mode="luminance"

img_er <- erode(img, kern=k)
display(img_er, method="raster", interpolate=FALSE)

img_di <- dilate(img, kern=k)
display(img_di, method="raster", interpolate=FALSE)

If you wish to display the image similarly as raster::plot does, you can use colormap.

img <- readImage(path)

#convert to match the output of raster::plot
img <- colormap(1-(channel(img, "red")), terrain.colors(256))
display(img, method="raster", interpolate=FALSE)
ADD COMMENTlink written 15 months ago by Andrzej Oleś670

Thanks for your help. This helped. Since I have to deal with geotagged tiff files, i have to convert the data back to a RasterLayer object. To adjust the Data to the 16bit (2byte) structure I multiply the array by 2**16.

 


 

ADD REPLYlink written 15 months ago by loki0
2

In that case you probably want rather multiply by 2^16-1 in order to map from 0:1 to 0:65535, which I believe is your desired range.

ADD REPLYlink written 15 months ago by Andrzej Oleś670
Please log in to add an answer.

Help
Access

Use of this site constitutes acceptance of our User Agreement and Privacy Policy.
Powered by Biostar version 2.2.0
Traffic: 135 users visited in the last hour