Only 1s created by erode()
1
0
Entering edit mode
loki • 0
@loki-11273
Last seen 8.4 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 • 1.8k views
ADD COMMENT
3
Entering edit mode
Andrzej Oleś ▴ 750
@andrzej-oles-5540
Last seen 4.1 years 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)

## 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 COMMENT
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.

 


 

ADD REPLY
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.

ADD REPLY

Login before adding your answer.

Traffic: 945 users visited in the last hour
Help About
FAQ
Access RSS
API
Stats

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

Powered by the version 2.3.6