r image function change size - r

I'm trying to visualize a matrix using image function. I'd like to set the size of cells (I mean the small squares each of which represents one elements of the matrix). I don't know how many elements will my matrix have beforehand.
This is my code now:
A <- matrix(1:20, 5, 4)
image(A)
and I'd like to have something like this:
image(A, sizeOfCell=10)
Would anyone have some idea?

grid units are probably easiest to work with,
A <- matrix(1:20, 5, 4)
library(grid)
m = A/max(A) # replace with matrix of colours, this will default to grey
grid.raster(m,
width = unit(NROW(A)*5,"mm"), # cell 5mm wide
height = unit(NCOL(A)*4,"mm"),# and 4mm high
interpolate = FALSE)

Related

Simulate a matricies of data using R as bands of satellite imagery from scratch

I am trying to
1) Simulate a matrix of data using R (in effect an image of numbers where each cell in the matrix has a number on the numerical scale of 0-255 (8 bit data))
2) Map the simulated data using mapping tools
3) Classify the image into 8-10 classes
The idea is to use a simple function to generate an image with 3 bands of Red Green and Blue imagery simulating multispectral imagery from satellite. So a composite of 3 different matricies. Like this.
Then classify the composite by colour into 8 or 10 classes
Any help would be much appreciated.
Based on your comments, here is an approach to sample as a gradient.
imagerows <- 100
imagecols <- 100
cuts <- 8
(imagecols * imagerows) %% cuts == 0 #Must be true
colorgroups <- as.integer(cut(0:255,cuts))
colors <- c("red","green","blue")
result <- lapply(colors,function(y){
unlist(
lapply(seq(1,cuts),function(x){sample((0:255)[colorgroups == x],
size = (imagerows*imagecols)/cuts,
replace = TRUE)})
)})
result is now a list of length 3, each element of which is a 100x100 matrix. The matrix contains 100 * 100 random samples between 0 and 255, but in cuts number of increasing groups.
We can then control the direction of the gradient using byrow = in matrix and by using rev() on the data.
red.matrix <- matrix((result[[1]]),nrow=imagerows,ncol=imagecols,byrow = TRUE)
green.matrix <- matrix((result[[2]]),nrow=imagerows,ncol=imagecols,byrow = FALSE)
blue.matrix <- matrix(rev(result[[3]]),nrow=imagerows,ncol=imagecols,byrow = FALSE)
Then we put the colors together with rgb() which outputs a vector. We can coerce it back into a matrix by assigning dimensions. Then just plot with grid.raster().
library(grid)
rgb.matrix <- rgb(red.matrix,green.matrix,blue.matrix,maxColorValue = 255)
dim(rgb.matrix) <- c(imagerows,imagecols)
grid.newpage()
grid.raster(rgb.matrix,interpolate = FALSE)

How to remove raster pixels based on proportional coverage of other raster, R

I have two rasters of different resolution and what I want is to mask out areas of raster A based on proportional cover of raster B. For example, I want to mask out pixels of raster A, if at least the 1/3 of them is covered by raster B.
I have no idea how to do this, so any help will be appreciated.
library(raster)
A <- raster(matrix(1:60,3,4))
B <- raster(matrix(1:20,5,6))
Your rasters are different resolutions over the same extent between 0 and 1 on x and y. A is 4x3, B is 6x5.
par(mfrow=c(1,2))
plot(A)
plot(B)
One first step could be to align the two to have the same resolution, so that we can apply the mask function. The raster::disaggregate function splits each cell into an integer number of columns an rows. In this case, with low resolution, I can split each cell into the number of columns and rows of the other matrix, so the four columns of A can each be split into 6, and the six columns of B can be split into 4, such that both are 24 wide. (Thanks to this answer for help.)
A_resize <- disaggregate(A, fact = c(dim(B)[2], dim(B)[1]), method = "bilinear")
B_resize <- disaggregate(B, fact = c(dim(A)[2], dim(A)[1]), method = "bilinear")
par(mfrow=c(1,2))
plot(A_resize)
plot(B_resize)
I'm interpreting your question to mean you want to mask out A when the values of B in that same place are < 1/3 of max.
We could make a modified version of B_resize which reclassifies everything < 1/3 of max as an NA. (Thanks to this answer for help.)
B_mask <- reclassify(B_resize,
rbind(c(0, B#data#max * 1/3, NA),
c(B#data#max * 1/3, B#data#max, 1)))
plot(B_mask)
and we could then use that to mask A:
par(mfrow = c(1,1))
plot(mask(A_resize,B_mask))

Sobel edge detector in R?

I am working on an R assignment about Sobel edge-detection. Unfortunately the video tutorial I was following uses R for every other task, but switches to python for image processing - I am guessing he did not find any useful R package for image convolution type work (this tutorial is from last year). I have tried EBImage and magick (this one seems new), but did not find much. This magick vignette talks aboutimage_convolve('Sobel')(about half way down the page) but only for vertical edges, not horizontal. Can someone suggest some good material that I can use? I am fairly new to image processing.
Update:
I have managed to get as far as detecting vertical and horizontal edges separately using magick package (code pasted below), but do not know how to combine them to generate a single image
library(magick)
# get image
img <- image_read("https://www.r-project.org/logo/Rlogo.png")
print(image_info(img))
# define horizontal and vertical Sobel kernel
Shoriz <- matrix(c(1, 2, 1, 0, 0, 0, -1, -2, -1), nrow = 3)
Svert <- t(Shoriz)
# get horizontal and vertical edges
imgH <- image_convolve(img, Shoriz)
imgV <- image_convolve(img, Svert)
print(plot(as.raster(img))) # view original image
print(plot(as.raster(imgH))) # view horizontal edges
print(plot(as.raster(imgV))) # view vertical edges
From the tutorial, next I need to combineimgHandimgVby computing the Euclidean distance between these edges, butdist()won't work with the image objects themselves. I need to get the data from these images, but do not know how. Something similar toimageData()inEBImagepackage would help, but cannot find it inmagick.It hasimage_data()function, but its output looks complicated.
Update(2):
I have (hopefully) got what I wanted withEBImagepackage (code below). I'd still like to get it working withmagickpackage, once I figure out how to get pixel data from edge images as described above, and also how to transform the final edge data back to image.
library(EBImage)
# get image
img <- readImage("https://www.r-project.org/logo/Rlogo.png")
print(img, short = T)
# define horizontal and vertical Sobel kernel
Shoriz <- matrix(c(1, 2, 1, 0, 0, 0, -1, -2, -1), nrow = 3)
Svert <- t(Shoriz)
# get horizontal and vertical edges
imgH <- filter2(img, Shoriz)
imgV <- filter2(img, Svert)
# combine edge pixel data to get overall edge data
hdata <- imageData(imgH)
vdata <- imageData(imgV)
edata <- sqrt(hdata^2 + vdata^2)
# transform edge data to image
imgE <- Image(edata, colormode = 2)
print(display(combine(img, imgH, imgV, imgE), method = "raster", all = T))
Thanks.

Draw a circle in a bitmap image and crop pixels outside circle in R

I'm loading bitmap images into R with dimensions that are roughly 17,000 X 17,000 pixels. I'd like to find a way to draw a circle with a radius (in pixels) of my choosing around the center of the picture and convert all pixels outside of the circle into NA's.
For example, if the radius desired was 500 pixels, all pixels within that distance (500) from the centroid would be kept as is. Any pixel farther than that distance (>= 501) from the centroid would be converted to an NA.
The bitmap images are made up entirely of 1's and 0's so here's a smaller example of what these images look like.
img=matrix(sample(c(1,0),1000000,replace=TRUE),ncol=1000,nrow=1000)
image(0:1000,0:1000,img)
This is a slight variation of the solution by eipi10. It does not use the "melt" function of the reshape package and rather uses subsetting the matrix directly:
# Number of rows and columns in image
nr = 200
nc = 100
# Create image values
set.seed(78)
img <- matrix(sample(c(1,0), nr*nc, prob=c(0.8, 1-0.8), replace=TRUE), ncol=nc, nrow=nr)
center <- c(median(1:nr), median(1:nc)) # center of image
r <- 40 # radius
# setting the matrix element inside the circle to value -1
img[(row(img) - center[1])^2 + (col(img) - center[2])^2 < r^2] <- -1
# plot image
par(mar = c(0, 0, 0, 0))
image(img, useRaster=TRUE, axes=FALSE)
I've created a fake image that's smaller than yours so that the code will run more quickly:
library(plotrix) # To draw a circle
library(reshape2) # For "melt" function
Create a fake image:
# Number of rows and columns in image
nr = 200
nc = 100
# Create image values
set.seed(78)
img = matrix(sample(c(1,0), nr*nc, prob=c(0.8, 1-0.8), replace=TRUE), ncol=nc, nrow=nr)
Now that we have our image, remove points outside the desired circle:
# melt matrix into "long" format
img = melt(id.var=1:nrow(img), img)
names(img) = c("rows","cols","z")
# Find center of image
center=c(median(1:nr), median(1:nc))
# Set desired radial distance from center
r=40
# Set values outside radius to -1 (or some value that can't otherwise appear in
# the matrix). You can set the value to NA, but then you won't be able to
# control the color of the excluded region (it will just be white).
img$z[sqrt((img$rows - center[1])^2 + (img$cols - center[2])^2) > r] = -1
# Plot image. Colors ordered from lowest (-1) to highest (1) value
image(1:nr, 1:nc, matrix(img$z, nrow=nr, byrow=FALSE), col=c("gray80", "green","red"))
# Draw a circle around the selected points
draw.circle(center[1], center[2], r, lwd=2)

Multipanel plot - how to omit a graphy from a specific position in a matrix layout

I cannot get the layout command to work. I want a multi-panel plot with a gap in a specific position, as given by this matrix:
mat <- matrix (c(1,2,3,4,5,6,7,8,9,10,0,12), 4, 3)
mat
where value 0 represents where I need empty space. However I get an error message when I run
layout(mat)
Using the following does not work either
mat <- matrix (c(1,1,1,1,1,1,1,1,1,1,0,1), 4, 3)
because when I run
layout.show(12)
it only gives me one panel instead of a 3x4 matrix layout. Where am I going wrong?
Thanks!
The issue is that you have a number 12 panel, but no number 11. Try this instead
mat <- matrix (c(1,2,3,4,5,6,7,8,9,10,0,11), 4, 3)
layout(mat)
layout.show(11)

Resources