科研人员焦虑到头疼的时候,止痛靠艺术.gif

作者: 9d760c7ce737 | 来源:发表于2019-07-28 19:51 被阅读106次

    这个要看到最后啊。
    最近啃下了图片处理的神包magick, 里面把动图融合到另外一张图片中的操作很神奇。
    举个简单的例子。

    第一个例子

    加载R包,用image_read函数读入图片

    install.packages("magick")
    library(magick)
    # 读取前景图片
    banana <- image_read("https://jeroen.github.io/images/banana.gif")
    

    可以用image_scale函数调整图片大小

    banana <- image_scale(banana, "150")
    

    导入一张背景图片,调整大小,设置为背景

    logo <- image_read("https://jeroen.github.io/images/Rlogo.png")
    logo <- image_scale(logo, "200")
    background <- image_background(logo, "white", flatten = TRUE)
    

    现在通过image_composite函数把两个图片整合起来,offset参数设置图片的相对位置,第一个加号是x轴,第二个加号是y轴

    frames <- image_composite(background, banana, offset = "+70+30")
    

    image_animate函数这是最终图片的帧数快慢

    image_animate(frames, fps = 10)
    

    这时候,图片就做好了,好像并不惊艳,因为用PPT就可以实现这个操作。

    第二个例子

    下面我们就这个例子,再换种方法操作,这里面涉及到批量操作。
    一样的读入两张图片,调整大小

    library(magick)
    logo <- image_read("https://www.r-project.org/logo/Rlogo.png")
    banana <- image_read("https://jeroen.github.io/images/banana.gif")
    ## 调整图片大小
    front <- image_scale(banana, "300")
    background <- image_scale(logo, "400")
    

    批量地把用image_flatten函数,把动图的帧数一张张融合到背景上,形成多张图片,储存为列表

    frames <- lapply(as.list(front), function(x) image_flatten(c(background, x)))
    

    image_join函数把他们合并起来

    image_join(frames)
    

    最后再用image_animate函数把他们动起来

    image_animate(image_join(frames))
    

    在这里我知道一个概念,就是image_join函数可以操作列表。

    第三个例子

    下面举第三个例子,学习图片和ggplot2图表的融合。
    先读入一张图片,调整大小

    frink <- image_read("https://jeroen.github.io/images/frink.png")
    frink <- image_scale(frink, "150")
    

    下面这个操作,很不得了,ggplot2直接和图片不好融合,整理提供了一个方案,就是先打开一张画布,把ggplot2的图画在里面,成为能够被识别的对象。
    image_graph打开一张画布,然后ggplot2作图,最后关闭这张画布,对象储存为fig

    fig <- image_graph(width = 400, height = 400, res = 96)
    ggplot2::qplot(mpg, wt, data = mtcars, colour = cyl)
    dev.off()
    

    现在我们用之前的image_composite函数就可以把他们融合起来了

    image_composite(fig, frink, offset = "+220+70")
    

    当然,把动图插入到ggplot2也是很容易的事情。

    frames <- image_composite(fig, banana, offset = "+30+50")
    image_animate(frames, fps = 10)
    

    这跟香蕉贱兮兮的哈,真欠揍。

    总结一下,

    • 两张图片在R语言里面是可以融合的,如果是动图用image_animate来调整。
    • 一张动图可以被拆分为多个帧,可用image_join批量整合。
    • image_graph打开画布画图可以把画在里面的图存为可操作的格式

    现在重点来了!

    我在网上找到一个碉堡的构图函数

    phi <- (1 + sqrt(5)) / 2 
    golden_angle <- pi*(3-sqrt(5))
    create_art <- function(n=1800,u=5,v=0,angle=golden_angle,colors="#ffffff",...){
      my_colours <- colors 
      df <- tibble(
        idx = c(0:(n-1)),
        t = seq(0,2*pi,length.out=n),
        r = sqrt(idx),
        x = r*cos(angle*idx),
        y = r*sin(angle*idx),
        color_angle = atan2(y=y,x=x)
      )
      v <- ifelse(v<u,v,v%%u)
      max_r <- max(df$r)*1.1
      my_art <- df %>% 
        ggplot(aes(x=x,y=y,color=color_angle)) +
        geom_path(data= . %>% filter(idx%%u==v),
                  lineend="round", linejoin="mitre", linemitre=3,
                  aes(size=idx, alpha=idx)) + 
        coord_fixed() +
        theme_void() +
        scale_alpha_continuous(guide="none", range=c(0,1), trans="sqrt")+ 
        scale_size_continuous(guide="none",  range=c(10,0), trans="sqrt") +
        scale_color_gradientn(guide="none", colors=my_colours) +
        theme(panel.background = element_rect(fill="#000000de")) +
        expand_limits(x=c(-max_r,max_r),y=c(-max_r,max_r)) 
      
      my_art + annotate(geom="text", x=Inf,y=-Inf,
                        label=str_glue('n: {n} | u: {u} | v: {v} | angle: {round(angle,3)} radian'),
                        family="Roboto Condensed", color="#ffffffae",
                        hjust=1,vjust=-1)
    }
    

    这个create_art函数可以画出这样的图

    library(tibble)
    library(dplyr)
    library(ggplot2)
    library(stringr)
    create_art()
    

    更厉害的是,这个函数有四个重要的参数,大概是这样的。
    n, 点的数量
    u,跳过固定的点
    angle,点之间的角度
    v,整体图片的角度

    我们用patchwork连接多个图来集中展示

    devtools::install_github("thomasp85/patchwork")
    library(patchwork)
    

    现在仅仅改变点和点之间的角度来作8张图

    create_art(n=360,angle=sqrt(2)) +
      create_art(n=360,angle=sqrt(3)) +
      create_art(n=360,angle=sqrt(5)) +
      create_art(n=360,angle=pi/7) +
      create_art(n=360,angle=pi/9) +
      create_art(n=360,angle=pi/46) +
      create_art(n=360,angle=2) +
      create_art(n=360,angle=1) +
      plot_layout(ncol = 4)
    

    很惊艳是吧。
    现在仅仅改变跳过的点数这个参数来做8张图

    create_art(n=360,u=5) +
      create_art(n=360,u=11) +
      create_art(n=360,u=13) +
      create_art(n=360,u=6) +
      create_art(n=360,u=9) +
      create_art(n=360,u=8) +
      create_art(n=360,u=17) +
      create_art(n=360,u=3) +
      plot_layout(ncol = 4)
    

    不可以思议。

    那么现在问题来了,v这个选择整体图片角度的参数还没有用呢,如果我们制作成一系列带不同角度的图片,再用刚才学到的批量技能把他们融合起来,岂不是能够创造炫酷的动图?
    首先,image_graph打开画布
    其次,制作一个数据框,把几个参数一行行表示,这里面改变的只有v
    使用pmap函数批量操作,这个函数很神奇,你如果传给他一个数据框,他就把一行一行的数据当做参数传给后面的函数
    最后,关闭图形设备,所有的图片以列表形式存在imgs_1中。

    library(magick)
    imgs_1 <- image_graph(width=600, height=600)
    params <- tibble(n=1800,u=44,v=seq(0,u-1,by=2),angle=golden_angle)
    purrr::pmap(params,create_art)
    dev.off()
    

    这时候再用image_animate函数把她动起来。

    image_animate(imgs_1,fps=10)
    

    这真是思路决定出路
    换一个图更加炫酷

    imgs_2 <- image_graph(width=600, height=600)
    params <- tibble(n=1800,u=22,v=seq(0,u-1,by=1),angle=-golden_angle)
    purrr::pmap(params,create_art)
    dev.off()
    image_animate(imgs_2,fps=10)
    

    好了,我们已经理解了他做动图的逻辑,就是把一系列图片合在一起,按照一定速度一张张播放,最终产生gif。

    制作gif

    如果这个理解是对的话,我们就有了一个制作gif动图的神器。
    比如我在PPT里面先创作几张图片导出来,放在当前工作目录的magick文件夹中


    然后批量读入,联合,加速播放即可

    library(magick)
    dd <- lapply(paste0("./magick/",list.files("./magick",pattern = "*.jpg")),image_read)
    image_animate(image_join(dd),fps=4)
    

    服不服?
    理论上,如果你给他足够多的依次发生的图片,什么动作小人书,小电影都没问题,以下我简单地示范一下。


    本次参考(甚至是复制)的教程在这里:
    magick
    https://cran.r-project.org/web/packages/magick/vignettes/intro.html#installing_magick
    create_art:
    https://chichacha.netlify.com/2019/01/29/playing-around-with-phyllotactic-spirals/

    好了,我是果子,这几天很焦虑,明天见。

    相关文章

      网友评论

        本文标题:科研人员焦虑到头疼的时候,止痛靠艺术.gif

        本文链接:https://www.haomeiwen.com/subject/esvlrctx.html