I have a data frame that I'm casting to a matrix. Every row represents an image in white, gray, and black colors.
The image corresponds to the number 5. I'm wondering what I am missing that the number 5 appears mirrored?
plotimage <- function(df,n, imageTitle) {
convertedImage <- df
matrx <- matrix(unlist(convertedImage[n,1:784]), byrow = T, nrow=28)
image(col = gray(0:255/255), z = matrx)
}
plotimage(image5, 1600,"Image of 5")
Output I want
Number 5 not mirrored.
Thanks,
That's because of the (unusual) way image works:
Notice that image interprets the z matrix as a table of f(x[i], y[j])
values, so that the x axis corresponds to row number and the y axis to
column number, with column 1 at the bottom, i.e. a 90 degree
counter-clockwise rotation of the conventional printed layout of a
matrix.
That's how your matrx is interpreted. Hence, writing
image(col = gray(0:255/255), z = matrx[nrow(matrx):1, ])
should fix it.
Related
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))
I would like to create a 2D levelplot in R where the x and y coordinates are from an irregular grid without using interpolation. The grid is given below:
grid<-cbind(seq(from=0.05,to=0.5,by=0.05),seq(from=0.05,to=0.5,by=0.05))
grid<-rbind(grid,cbind(seq(from=0.0,to=0.95,by=0.05),seq (from=0.05,to=1,by=0.05)))
grid<-rbind(grid,cbind(seq(from=0,to=0.9,by=0.05),seq (from=0.1,to=1,by=0.05)))
grid<-rbind(grid,cbind(seq(from=0,to=0.85,by=0.05),seq(from=0.15,to=1,by=0.05)))
grid<-rbind(grid,cbind(seq(from=0,to=0.75,by=0.05),seq(from=0.25,to=1,by=0.05)))
grid<-rbind(grid,cbind(seq(from=0,to=0.80,by=0.05),seq(from=0.20,to=1,by=0.05)))
grid<-rbind(grid,cbind(seq(from=0,to=0.70,by=0.05),seq(from=0.30,to=1,by=0.05)))
grid<-rbind(grid,cbind(seq(from=0,to=0.65,by=0.05),seq(from=0.35,to=1,by=0.05)))
grid<-rbind(grid,cbind(seq(from=0,to=0.60,by=0.05),seq(from=0.40,to=1,by=0.05)))
grid<-rbind(grid,cbind(seq(from=0,to=0.55,by=0.05),seq(from=0.45,to=1,by=0.05)))
grid<-rbind(grid,cbind(seq(from=0,to=0.50,by=0.05),seq(from=0.50,to=1,by=0.05)))
grid<-rbind(grid,cbind(seq(from=0,to=0.40,by=0.05),seq(from=0.60,to=1,by=0.05)))
grid<-rbind(grid,cbind(seq(from=0,to=0.45,by=0.05),seq(from=0.55,to=1,by=0.05)))
grid<-rbind(grid,cbind(seq(from=0,to=.35,by=0.05),seq(from=0.65,to=1,by=0.05)))
grid<-rbind(grid,cbind(seq(from=0,to=0.30,by=0.05),seq(from=0.70,to=1,by=0.05)))
x=grid[,1]
y=grid[,2]
The Z-values are stored in another vector. I have tried to use the image-function, but without any luck. For instance, if I try
image(x,y,height.vals)
where
height.vals=matrix(runif(dim(grid)[1]),nrow=dim(grid)[1],ncol=1)
I get an error message saying that x and y should be increasing.
One could use the akima function interp, but then I get interpolated data.
Looks like you have points on a 20 x 20 grid. So, you can create a 20 x 20 matrix and fill it with the values from height.vals.
With a little bit of tweaking, you can turn the x and y values into indices of the matrix and use those indices to assign height.vals to the appropriate places in the matrix.
# Turn the x and y values into integers.
# R doesn't take 0 as an index, so add 1 to the x values to get rid of the 0s
inds <- cbind(x = as.integer(20*x + 1), y = as.integer(20*y))
# create the 20 x 20 matrix
m <- matrix(nrow = 20, ncol = 20)
# fill the matrix with height.vals based on the indices
m[inds] <- height.vals
Then, you can use m as an input to functions like image, filled.contour, and lattice::levelplot
image(m)
When grayscale images are represented by matrices each element of the matrix determines the intensity of the corresponding pixel. For convenience, most of the current digital files use integer numbers between 0 (to indicate black, the color of minimal intensity) and 255 (to indicate white, maximum intensity), giving a total of 256 = 2^8 different levels of gray.
Is there a way to get a pixel matrix of graysale images in R whose pixel values will range from 0 to 255?
It will also be helpful to know if I can resize the images in preferred dimension (say, $28 \times 28$) in R and then convert them into a pixel matrix whose elements range from 0 to 255?
What happens if the original image is RGB but I want the matrix for grayscale?
The R package png offers the readPNG() function which can read raster graphics (consisting of "pixel matrices") in PNG format into R. It returns either a single matrix with gray values in [0, 1] or three matrices with the RGB values in [0, 1].
For transforming between [0, 1] and {0, ..., 255} simply multiply or divide with 255 and round, if desired.
For transforming between RGB and grayscale you can use for example the desaturate() function from the colorspace package.
As an example, let's download the image you suggested:
download.file("http://www.greenmountaindiapers.com/skin/common_files/modules/Socialize/images/twitter.png",
destfile = "twitter.png")
Then we load the packages mentioned above:
library("png")
library("colorspace")
First, we read the PNG image into an array x with dimension 28 x 28 x 4. Thus, the image has 28 x 28 pixels and four channels: red, green, blue and alpha (for semi-transparency).
x <- readPNG("twitter.png")
dim(x)
## [1] 28 28 4
Now we can transform this into various other formats: y is a vector of hex character strings, specifying colors in R. yg is the corresponding desaturated color (again as hex character) with grayscale only. yn is the numeric amount of gray. All three objects are arranged into 28 x 28 matrices at the end
y <- rgb(x[,,1], x[,,2], x[,,3], alpha = x[,,4])
yg <- desaturate(y)
yn <- col2rgb(yg)[1, ]/255
dim(y) <- dim(yg) <- dim(yn) <- dim(x)[1:2]
I hope that at least one of these versions is what you are looking for. To check the pixel matrices I have written a small convenience function for visualization:
pixmatplot <- function (x, ...) {
d <- dim(x)
xcoord <- t(expand.grid(1:d[1], 1:d[2]))
xcoord <- t(xcoord/d)
par(mar = rep(1, 4))
plot(0, 0, type = "n", xlab = "", ylab = "", axes = FALSE,
xlim = c(0, 1), ylim = c(0, 1), ...)
rect(xcoord[, 2L] - 1/d[2L], 1 - (xcoord[, 1L] - 1/d[1L]),
xcoord[, 2L], 1 - xcoord[, 1L], col = x, border = "transparent")
}
For illustration let's look at:
pixmatplot(y)
pixmatplot(yg)
If you have a larger image and want to bring it to 28 x 28, I would average the gray values from the corresponding rows/columns and insert the results into a matrix of the desired dimension.
Final note: While it is certainly possible to do all this in R, it might be more convenient to use an image manipulation software instead. Depending on what you aim at, it might be easier to just use ImageMagick's mogrify for example:
mogrify -resize 28 -type grayscale twitter.png
Here is an example of converting and drawing an image from a grayscale png. Please ensure installing the relevant packages first.
library(png)
library(RCurl)
myurl = "https://postgis.net/docs/manual-dev/images/apple_st_grayscale.png"
my_image = readPNG(getURLContent(myurl))
img_mat=my_image[,,1] # will hold the grayscale values divided by 255
img_mat=t(apply(img_mat, 2, rev)) # otherwise the image will be rotated
image(img_mat, col = gray((0:255)/255)) # plot in grayscale
Let's say I have a unit vector a = Vector(0,1,0) and I want to add a random spread of something between x = Vector(-0.2,0,-0.2) and y = Vector(0.2,0,0.2), how would I go about doing that?
If I were to simply generate a random vector between x and y, I'd get a value somewhere in the bounds of a square:
What I'd like instead is a value within the circle made up by x and y:
This seems like a simple problem but I can't figure out the solution right now. Any help would be appreciated.
(I didn't ask this on mathoverflow since this isn't really a 'research level mathematics question')
If I read your question correctly, you want a vector in a random direction that's within a particular length (the radius of your circle).
The formula for a circle is: x2 + y2 = r2
So, if you have a maximum radius, r, that constrains the vector length, perhaps proceed something like this:
Choose a random value for x, that lies between -r and +r
Calculate a limit for randomising y, based on your chosen x, so ylim = sqrt(r2 - x2)
Finally, choose a random value of y between -ylim and +ylim
That way, you get a random direction in x and a random direction in y, but the vector length will remain within 0 to r and so will be constrained within a circle of that radius.
In your example, it seems that r should be sqrt(0.22) which is approximately 0.28284.
UPDATE
As 3D vector has length (or magnitude) sqrt(x2+y2+z2) you could extend the technique to 3D although I would probably favour a different approach (which would also work for 2D).
Choose a random direction by choosing any x, y and z
Calculate the magnitude m = sqrt(x2+y2+z2)
Normalise the direction vector (by dividing each element by its magnitude), so x = x/m, y = y/m, z=z/m
Now choose a random length, L between 0 and r
Scale the direction vector by the random length. So x = x * L, y = y * L, z = z * L
Here is my problem.
I have an hypercube I built using the following codes:
X <- seq (-1/sqrt(2),1/sqrt(2),length.out=100)
Y <- seq (-sqrt(2)/(2*sqrt(3)),sqrt(2)/sqrt(3),length.out=100)
Z <- seq (-1/(2*sqrt(3)),sqrt(3)/2,length.out=100)
grid <- data.frame (expand.grid(X=X,Y=Y,Z=Z))
Then, I would delete from the grid data.frame all the points that are not located within the tetrahedron defined by the following coordinates:
w : (0,0,sqrt(3)/2)
x : (0,sqrt(2)/sqrt(3),-1/(2*sqrt(3)))
y : (-1/sqrt(2),-sqrt(2)/(2*sqrt(3)),-1/(2*sqrt(3)))
z : (1/sqrt(2),-sqrt(2)/(2*sqrt(3)),-1/(2*sqrt(3)))
I do not find a away to do this without howfully long codes. Can anyone help me please
Thanks !!!
Package ptinpoly has a function pip3d to find wether a point is in a polyhedron or not.
library(ptinpoly)
X <- seq(-1/sqrt(2),1/sqrt(2),length.out=10) #I used a smaller dataset here
Y <- seq(-sqrt(2)/(2*sqrt(3)),sqrt(2)/sqrt(3),length.out=10)
Z <- seq(-1/(2*sqrt(3)),sqrt(3)/2,length.out=10)
# The query points has to be inputted as a matrix.
grid <- as.matrix(expand.grid(X=X,Y=Y,Z=Z))
w <- c(0,0,sqrt(3)/2)
x <- c(0,sqrt(2)/sqrt(3),-1/(2*sqrt(3)))
y <- c(-1/sqrt(2),-sqrt(2)/(2*sqrt(3)),-1/(2*sqrt(3)))
z <- c(1/sqrt(2),-sqrt(2)/(2*sqrt(3)),-1/(2*sqrt(3)))
# The matrix of vertices
tetra_vert <- matrix(c(w,x,y,z),byrow=TRUE,nrow=4)
# The matrix of faces (each row correspond to a vector of vertices linked by a face.
tetra_faces <- matrix(c(1,2,3,
1,2,4,
1,3,4,
2,3,4),byrow=TRUE,nrow=4)
inout <- pip3d(tetra_vert, tetra_faces, grid)
The result is a vector of integers, 0 means the point fall on a face, 1 that it is inside the polyhedron, -1 outside.
The solution of your problem is therefore:
grid[inout%in%c(0,1),]
make planes which form the tetrahedron and compare if a point is on the right side of each of the planes.
pointers: think of calculating dot products with the plane normal and such. One option is to draw a vector from tetrahedron point to each corner, 4 in total and 1 vector from point to point and then use dotproducts and whatnot to see if the point-point vector is within the 4 others.
the point is probably within the tetrahedron if vector to it can be expressed as a sum of non negative multiples of the corner vectors and the vector short enough.