【问题标题】:Create multi-panel figure using PNG/JPEG images使用 PNG/JPEG 图像创建多面板图
【发布时间】:2020-10-12 10:49:52
【问题描述】:

问题:

我想使用 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.

【问题讨论】:

  • 对不起,伙计!我对 ggplot2 的回答中有一个错误;这就是你得到错误的原因。我正在编辑它
  • 你的第一次尝试几乎成功了,顺便说一句。使用library(patchwork),您可以使用patch &lt;- wrap_elements(img1) + wrap_elements(img2)。您不能直接查看它,但ggsave 可以正常工作。另外,请确保在readPNG 中设置native = TRUE
  • 感谢您添加此@mths!

标签: r image ggplot2 png jpeg


【解决方案1】:

我给你几个我最常用的替代方案:

备选方案1ggplot2、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: 使用 ma​​gick 包。

该包依靠自己的函数来读取图像,因此我们需要稍微调整一下您的代码:

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

然后使用magick::image_append(c(img1, img2)) 之类的函数,您可以将它们组合起来。请参阅magick package documentation 了解更多信息。

【讨论】:

  • 谢谢,使用magick的第二个选项有效!但是,分辨率很低(96 dpi)。有没有办法像在 ggsave 中一样指定分辨率(例如 300 dpi)?
  • magick::image_write 中有densityquality 之类的参数可以帮助指定输出质量。尽管您可能无法从低分辨率 PNG 进行高分辨率渲染。输入的质量将决定输出的质量;让我们看看是否有人在这方面比我更了解:)
  • @jl748795 很可能您必须定义与列一样多的对象(使用 image_append),然后将它们全部附加
  • 当时我没有解释自己。我的意思是,作为一种解决方法,您可以创建,例如,使用 image_append() 将它们存储为魔法图像对象的行。然后用 image_append(c(row1,row2,...,row n), stack = TRUE) 堆叠这些对象
【解决方案2】:

您还可以rbind 图像阵列。但由于它们是 3D (x,y,RGB),您必须使用 abind 包中的 abind 函数。沿=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")

【讨论】:

    【解决方案3】:

    你可以在 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
          )
    

    【讨论】:

    • 这非常有效。谢谢!
    【解决方案4】:

    正如其他人所建议的那样,ma​​gick 包比使用 grobs 和相关的低级解决方案要简单得多。 ma​​gick 很强大,但恕我直言,文档很差而且非常循环。

    但是,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"

    【讨论】:

      猜你喜欢
      • 2012-05-15
      • 1970-01-01
      • 1970-01-01
      • 2011-01-30
      • 1970-01-01
      • 1970-01-01
      • 2010-10-27
      • 1970-01-01
      相关资源
      最近更新 更多