使用PNG/JPEG格式的图片创建多面板图形

4
问题:

我想使用PNG或JPEG图像制作多面板图。 这些图像不是在R中创建的,但我想要在R中将它们拼合成一个图形。 所有图像的大小/尺寸都相同。

我尝试过的方法:
library(png)

img1 <- readPNG("filepath/img1.png")
img2 <- readPNG("filepath/img2.png")

library(patchwork)

patch <- img1 + img2
patch

当我运行这个程序时,出现了以下错误:
[ reached getOption("max.print") -- omitted 3 matrix slice(s) ]

我多次增加了最大打印次数(增加到非常高的数字):

options(maxprint = 1000000000000)

但是仍然得到相同的错误。

接着我尝试使用以下代码将每个图像转换为一个 ggplot(不带点):

library(ggplot2)

img1plot <- ggplot() + 
background_image(img1) +
theme(plot.margin = margin(t=1, l=1, r=1, b=1, unit = "cm"))

这会返回以下错误:

Error in background_image(d311) : 
  could not find function "background_image"

有没有其他方法在R中拼接图片以制作一张图?

编辑:

根据@davidnortes的评论,我尝试了以下操作:

p1 <- ggplot2::annotation_custom(grid::rasterGrob(img1,
                                            width=ggplot2::unit(1,"npc"),
                                            height=ggplot2::unit(1,"npc")),
                           -Inf, Inf, -Inf, Inf)

p2 <- ggplot2::annotation_custom(grid::rasterGrob(img2,
                                                  width=ggplot2::unit(1,"npc"),
                                                  height=ggplot2::unit(1,"npc")),
                               -Inf, Inf, -Inf, Inf)


library(cowplot)

plots <- plot_grid(
  p1, p2,
  labels = c('A', 'B'),
  align="hv"
)
plots

我收到以下警告信息,但是图形没有形成:
Warning messages:
1: In as_grob.default(plot) :
  Cannot convert object of class LayerInstanceLayerggprotogg into a grob.
2: In as_grob.default(plot) :
  Cannot convert object of class LayerInstanceLayerggprotogg into a grob.

1
抱歉!我的 ggplot2 答案中有一个 bug,所以你遇到了错误。我正在进行编辑。 - davidnortes
1
顺便说一下,你的第一次尝试几乎成功了。使用 library(patchwork),你可以这样做:patch <- wrap_elements(img1) + wrap_elements(img2)。虽然不能直接查看它,但 ggsave 可以正常工作。此外,请确保在 readPNG 中设置 native = TRUE - mths
谢谢 @mths 添加这个! - cgxytf
4个回答

5

我将为您提供我经常使用的两个替代方案:

替代方案1:结合使用ggplot2、grid和cowplot

您可以使用以下方法将每个PNG图片嵌入到ggplot对象中:

ggplot2::ggplot() + ggplot2::annotation_custom(grid::rasterGrob(YourPNGimage,
                                                width=ggplot2::unit(1,"npc"),
                                                height=ggplot2::unit(1,"npc")),
                               -Inf, Inf, -Inf, Inf)

然后您可以使用cowplot::plot_grid()来排列您的图表。

替代方案2:使用magick包。

该包使用自己的函数来读取图像,因此我们需要对您的代码进行一些调整:

img1 <- magick::image_read("filepath/img1.png")
img2 <- magick::image_read("filepath/img2.png")

然后使用像 magick::image_append(c(img1, img2)) 这样的函数,你就可以将它们组合起来。有关更多信息,请参见 magick软件包文档


1
magick::image_write 中,你有像 densityquality 这样的参数,可以帮助你指定输出质量。虽然从低分辨率的 PNG 文件中无法生成高分辨率的渲染图,因为输入的质量会影响到输出的质量;如果有人对此了解得更好,请告诉我 :) - davidnortes
1
@jl748795 看一下这个:https://stackoverflow.com/questions/56060625/how-to-save-a-high-resolution-image-with-magick-in-r - davidnortes
还有一个问题,使用这个函数是否可以选择列数?我只能找到关于stack = TRUE的信息,它会垂直堆叠照片而不是水平堆叠,但我想要3列。 - cgxytf
1
@jl748795 很可能你需要使用 image_append 定义和每一列一样多的对象,然后将它们全部附加在一起。 - davidnortes
2
我当时没有解释清楚。我的意思是,作为一种解决方法,你可以使用 image_append() 创建行,将它们存储为 magick 图像对象。然后,你可以使用 image_append(c(row1,row2,...,row n), stack = TRUE) 将这些对象堆叠起来。 - davidnortes
显示剩余5条评论

2

正如其他人建议的那样,magick软件包比使用grobs和相关工具的低级解决方案要简单得多。 magick功能强大,但在我看来文档很差,而且非常循环。

然而,在image_montage()页面中有一个简单的解决方案可回答您的问题。最重要的参数是geometry规范,它控制“瓷砖”之间的间距。

library(magick)
input <- rep(logo, 12)
image_montage(input, geometry = 'x100+10+10', tile = '4x3', bg = 'pink', shadow = TRUE)

为了完全消除间距,请使用geometry = '0x100+0+0', shadow = FALSE"。这里不需要间隔,同时阴影设置为假。

2
你也可以使用 rbind 合并图像数组。但由于它们是3D的(x,y,RGB),因此必须使用abind包中的abind函数。along=1用于垂直拼接,2用于水平拼接。

这是有效的,因为图像具有相同的大小。

img1 <- readPNG("filepath/img1.png")
img2 <- readPNG("filepath/img2.png")
img12 <- abind::abind(img1,img2,along=1)
png::writePNG(img12,"filepath/img12.png")

2
你可以使用R中的magick包来制作拼贴画。
# read the the png files into a list
  pngfiles <-
  list.files(
    path = here::here("png_ouput_folder"),
    recursive = TRUE,
    pattern = "\\.png$",
    full.names = T
  )
 
 # read images and then create a montage
 # tile =2 , means arrange the images in 2 columns
 # geometry controls the pixel sixe, spacing between each image in the collage output. 

 magick::image_read(pngfiles) %>%
      magick::image_montage(tile = "2", geometry = "x500+10+5") %>%
      magick::image_convert("jpg") %>%
      magick::image_write(
        format = ".jpg", path = here::here(paste(name,"_collage.jpg",sep="")),
        quality = 100
      )

这个完美地运行了。谢谢! - Tung

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