Search
Question: Only 1s created by erode()
0
gravatar for loki
23 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 23 months ago by Andrzej Oleś710 • written 23 months ago by loki0
3
gravatar for Andrzej Oleś
23 months ago by
Andrzej Oleś710
Heidelberg, Germany
Andrzej Oleś710 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 23 months ago by Andrzej Oleś710

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 23 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 23 months ago by Andrzej Oleś710
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: 299 users visited in the last hour