如何旋转一个 R 语言中的栅格图像

9
我有下面的代码,可以将图像保存到我的电脑上。我想将该图像围绕其中心(或左下角)旋转45度、90度和135度,然后保存为3个不同的图像。我该怎么做?
library(raster)
r1 <- brick(system.file("external/rlogo.grd", package="raster"))
x <- crop(r1, extent(0,50,0,50))
plotRGB(x)
png(width=50, height=50)
par(mai=c(0,0,0,0))
image(x)
dev.off()

---------更新1-------------------------

基于被接受的答案,以下是可工作的代码:

library(raster)
r1 <- brick(system.file("external/rlogo.grd", package="raster"))
r1
x <- crop(r1, extent(0,ncol(r1),0,nrow(r1)))
plotRGB(x)

x1 <- 0:ncol(x)
y1 <- 0:nrow(x)
z <- matrix(1, nrow=length(x1), ncol=length(y1))

col.mat <- t(apply(matrix(rgb(getValues(x)/255), nrow=nrow(x), byrow=TRUE), 2, rev))

# Rotate 45 degrees
persp(x1, y1, z, zlim=c(0,2), theta = 20, phi = 90, 
      col = col.mat, scale=FALSE, border=NA, box=FALSE)
png("SaveThisPlot.png")
persp(x1, y1, z, zlim=c(0,2), theta = 20, phi = 90, 
      col = col.mat, scale=FALSE, border=NA, box=FALSE)
dev.off()

2
raster包中有类似rotate的函数吗? - Alex A.
你有任何例子吗?我尝试了,但是出现了如上所示的错误。 - user2543622
@Frank,有没有一种方法可以进行45度旋转?你的命令很有效! - user2543622
@AlexA。在raster包中旋转只会改变坐标系。OP所问的是对图像本身进行真正的旋转。 - Rodrigo
2个回答

14
对于90度旋转,这是一个简单的解决方案:
image(t(flip(x, 1)))
image(t(flip(x, 2)))
plotRGB(t(flip(x, 1)))
plotRGB(t(flip(x, 2)))

对于45度和135度的旋转,会有一些棘手。可能还有其他方法,但我将使用`persp`函数,并给`theta`参数赋予不同的角度。
只需要正确设置对`persp`的调用即可。`x1`、`y1`和`z`只是`persp`函数的输入(有关该函数参数的更多信息,请参见`?persp`)。`col.mat`是一个包含颜色值的矩阵。
x1 <- 0:ncol(x)
y1 <- 0:nrow(x)
z <- matrix(1, nrow=length(x1), ncol=length(y1))
col.mat <- t(apply(matrix(rgb(getValues(x)/255), nrow=nrow(x), byrow=TRUE), 2, rev))
# the transposing and reversing are just to get the colors in the same 
# spots as they're in when viewing plotRGB(x).
#
# getValues(x) is how you get the rgb colors, in the form of a 3-column matrix.
# rgb(getValues(x)/255) converts them into hex code, which is convenient enough here.

如果您发现这是您要查找的内容的镜像,请尝试以不同的方式填充颜色矩阵。例如:

col.mat <- matrix(rgb(getValues(x)/255), nrow=nrow(x))

正如你所看到的,正确填充颜色矩阵是使此方法对您有效的关键。我将把如何对颜色矩阵进行任何其他操作留给读者作为练习。

现在,调用persp。在这里,我设置了zlim值,以便包括1的范围。因为我将所有z值都设置为1,所以您需要设置有效范围,否则persp会抛出关于无效限制的错误。它不喜欢从1到1的范围。

# Rotate 45 degrees
persp(x1, y1, z, zlim=c(0,2), theta = 45, phi = 90, 
    col = col.mat, scale=FALSE, border=NA, box=FALSE)

这里是 135 度:

这是 135 度:

# Rotate 135 degrees
persp(x1, y1, z, zlim=c(0,2), theta = 135, phi = 90, 
    col = col.mat, scale=FALSE, border=NA, box=FALSE)

enter image description here

保存图表的方法与您在问题中展示的方式相同:

png("SaveThisPlot.png")
persp(x1, y1, z, zlim=c(0,2), theta = 135, phi = 90, 
    col = col.mat, scale=FALSE, border=NA, box=FALSE)
dev.off()

原帖发布者后来遇到了一些问题,当宽度!=高度时,正如后来的帖子中所指出的:http://stackoverflow.com/questions/31814873/r-raster-rotating-images-and-not-changing-their-size。 - aaryno

1

如果在阅读帮助页面并尝试示例后,不出现错误或警告消息的方法:

extent(x) <- extent(0, 360, -90, 90)
rr <- rotate(x)
 png()
 plotRGB(x)
dev.off()

但是你可能不喜欢它,因为它假定了一个特定的坐标系,而你可能没有。如果你想要提取数据元素,那么使用@运算符:

str(x)  The slots are named 'data' and 'values'
image(x)
image(matrix(x@data@values[,1], 50, byrow=TRUE)) # rotate one layer

我不认为它在旋转我的图像,相反它似乎沿着x轴拉伸了我的图像 :( - user2543622
实际上它正在旋转和变形,但是在分成两半之后(因为假设使用-180到+180坐标系统)。我警告过你不会喜欢它。 - IRTFM
“rotate” 是针对单个特殊情况的。用于将全局经纬度数据从0..360旋转到-180..180度经度。这种(直接使用S4插槽,你不知道它们的作用)image(matrix(x@data@values[,1], 50, byrow=TRUE))是一个糟糕的建议。 - Robert Hijmans
是的,rotate 是针对特定情况的。那就是我的观点。同意“直接使用”'values'矩阵可能对那些从不想深入了解的用户来说是一个“可怕的建议”,但我反驳说,你通常确实希望了解正在处理的数据对象的性质。 - IRTFM
我同意“想要理解”的观点,但我认为在这种情况下,你正在引导人们走错路。 “raster”包有获取值的方法(例如getValues、as.matrix、values()等)。如果一个对象是从文件派生出来的,那么你提到的插槽中就不会有任何值。 - Robert Hijmans

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接