簡體   English   中英

在 R 中保存旋轉圖像 - 避免背景並保持大小

[英]saving rotate images in R - avoiding background and maintaining size

我有以下代碼,它基於我之前的問題 當我保存圖像 SaveThisPlot.png 時,它會創建不需要的背景並且圖像大小也會改變(它會減小)。 如何保存圖像,使旋轉部分的大小與之前完全相同(77 行和 101 列)並且沒有背景?

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()

在此處輸入圖片說明

您可以使用透明背景,但旋轉繪圖需要重新調整大小。

保存繪圖時,您可以設置png("SaveThisPlot.png", bg="transparent")以防止顯示背景。 嘗試:

png("SaveThisPlot.png", width=101 height=77, units="px", pointsize=1, bg="transparent")

請注意,如果您嘗試使用旋轉版本的徽標來執行此操作,徽標會重新調整大小以適合 101 x 77 像素 png。 如果您想旋轉它並保持徽標大小,則必須調整 png 的大小,@RomanLuštrik 在他的評論中提到。 重新調整大小,如果這對你來說是一個選項,只是一個三角函數的問題,以找到合適的高度和寬度參數。

您可以嘗試使用一些三角函數設置新的高度和寬度以保存 png。 這是一個旋轉 35 度的示例:

# hypotenuse
hypot <- sqrt((nrow(x)/2)^2 + (ncol(x)/2)^2) 
# angle
angle <- asin((nrow(x)/2)/ hypot)/(pi/180)

width <- 2 * max(abs(hypot * cos((angle + 35) * pi/180)), 
                 abs(hypot * cos((- angle + 35) * pi/180)))

height <- 2 * max(abs(hypot * sin((angle + 35) * pi/180)), 
                 abs(hypot * sin((- angle + 35) * pi/180)))


png("SaveThisPlot.png", height=height, width=width, units="px", pointsize=1,
    bg="transparent")
par(mar=c(0,0,0,0), xaxs = "i", yaxs = "i")
persp(x1, y1, z, zlim=c(0,2), theta = 35, phi = 90, 
      col = col.mat, scale=FALSE, border=NA, box=FALSE)
dev.off()

在此處輸入圖片說明

整體圖像不會是 77 x 101 像素,但徽標本身應該是相同的大小,雖然有點粗糙。 要獲得更平滑的圖像,請參閱下面的rgl答案,但請注意,透明背景不適用於rgl

使用 rgl 包的替代方法:

如果最終目標是保持圖像的大小和平滑度,則生成圖像的不同方法可能會更好。 您可以嘗試使用rgl (R-to-OpenGL) 包和persp3d函數,您可以在其中旋轉其窗口內的繪圖,而無需重新調整窗口大小或更改徽標的比例。 您主要可以使用已有的東西,但需要修改顏色矩陣才能與persp3d一起persp3d

col.mat2 <- cbind(rbind(1, col.mat), 1)

然后,設置場景,調用persp3d ,旋轉它並保存。

open3d() 
rgl.pop("lights") 
light3d(specular="black") # to reduce reflection
persp3d(x1,y1,z, col=col.mat2, ylab="", xlab="", zlab="",
        axes=FALSE, smooth=FALSE, aspect="iso")

# Rotate it by defining the userMatrix, then save    
par3d(userMatrix = rotationMatrix(0*pi/180, 0, 0, 1))
rgl.snapshot("Rlogo_0.png") # to save

par3d(userMatrix = rotationMatrix(45*pi/180, 0, 0, 1))
rgl.snapshot("Rlogo_45.png")

par3d(userMatrix = rotationMatrix(135*pi/180, 0, 0, 1))
rgl.snapshot("Rlogo_135.png")

標志Rlogo_45度Rlog_135度

要強制將此圖像放入較小的窗口,您可以使用windowRectzoom參數的組合來操縱 rgl 顯示窗口的大小和背景量( 例如,請參閱此問答)。 但是,透明背景目前不是rgl的選項。

open3d()
bg3d(color="#FF00FF") # pink background (some color not in the actual image)
rgl.pop("lights") 
light3d(specular="black") 
persp3d(x1,y1,z, col=col.mat2, axes=FALSE,
     ylab="", xlab="", zlab="", smooth=FALSE, aspect="iso")
rgl.viewpoint(zoom=0.52)
par3d(userMatrix = rotationMatrix(0*pi/180, 0, 0, 1), windowRect=c(0,0, 101, 77))
rgl.snapshot("Rlogo_77h124w.png")
par3d(userMatrix = rotationMatrix(45*pi/180, 0, 0, 1), windowRect=c(0,0, 101, 77))
rgl.snapshot("Rlogo45_77h124w.png")

我無法使窗口寬度小於 124 像素。 似乎我的計算機上的 rgl 窗口的最小寬度為 124 像素,因為我無法使窗口變小(即無法折疊窗口頂部的最小化、恢復和關閉按鈕)。

在此處輸入圖片說明在此處輸入圖片說明

要獲得透明背景,您可以導入這些保存的 png,並將 alpha 值 1 分配給背景顏色(“#FF69B4”):

library(png)
add.alpha <- readPNG("Rlogo_77h124w.png") #Try a rotate version, too

library(abind)
add.alpha <- abind(add.alpha, matrix(1, nrow=nrow(add.alpha), ncol=ncol(add.alpha)))

add.alpha[,,4][which(rgb(add.alpha[,,1],add.alpha[,,2],add.alpha[,,3]) == "#FF00FF")] <- 0
writePNG(add.alpha, "Rlogo_77h124w_alpha.png")

事實證明,這種方法並不完美,您最終可能會在顏色不完全是“#FF00FF”的旋轉圖像上出現輕微邊框。 您可以通過一種或另一種方式解決邊界問題,如果這對您來說是個問題,但根據最終目標,它可能不會產生影響。 嘗試使用add.alpha[,,4][which(add.alpha[,,1] > .9 & add.alpha[,,3] > .9 & add.alpha[,,2] < .85 )] <- 0writePNG之前

在此處輸入圖片說明在此處輸入圖片說明在此處輸入圖片說明

如果您不希望像上面那樣切掉圖像角,請使用前面的三角函數來幫助在par3d內正確par3d窗口大小:

open3d(); bg3d(color="#FF69B4"); rgl.pop("lights"); light3d(specular="black") 
persp3d(x1,y1,z, col=col.mat2, axes=FALSE,
     ylab="", xlab="", zlab="", smooth=FALSE, aspect="iso")
view3d(zoom=.862)
par3d(userMatrix = rotationMatrix(-45*pi/180, 0, 0, 1), windowRect=c(0,0, width, height)) # width and height from trigonometry above
rgl.snapshot("Rlogo45_77h124w.png")
#library(png)
add.alpha <- readPNG("Rlogo45_77h124w.png") # Try "Rlogo_77h124w.png", too
#library(abind)
add.alpha <- abind(add.alpha, matrix(1, nrow=nrow(add.alpha), ncol=ncol(add.alpha)))

add.alpha[,,4][which(add.alpha[,,1] > .9 & add.alpha[,,3] > .9 & add.alpha[,,2] < .85 )] <- 0 # not a perfect solution
writePNG(add.alpha, "Rlogo45_77h124w_alpha.png")

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM