Only 1s created by erode()
1
0
Entering edit mode
loki • 0
@loki-11273
Last seen 5.0 years ago

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?

r ebimage morphology • 988 views
3
Entering edit mode
Andrzej Oleś ▴ 750
@andrzej-oles-5540
Last seen 8 months ago
Heidelberg, Germany

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)

path <- "C:/Program Files/R/R-3.2.3/doc/html/logo.jpg"
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)
0
Entering edit mode

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.

2
Entering edit mode

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.

Traffic: 555 users visited in the last hour
FAQ
API
Stats

Use of this site constitutes acceptance of our User Agreement and Privacy Policy.