Skip to content

Instantly share code, notes, and snippets.

@dmi3kno
Last active July 24, 2019 23:05
Show Gist options
  • Save dmi3kno/9c6cb927b799737698d27fcb66f75d0e to your computer and use it in GitHub Desktop.
Save dmi3kno/9c6cb927b799737698d27fcb66f75d0e to your computer and use it in GitHub Desktop.
Making pretty blobs
library(magick)
library(tidyverse)
# generate noise and apply morphological transformations to make blobs
blobs <- image_blank(600,400, "black") %>%
image_noise("Impulse") %>%
image_channel("Green") %>%
image_morphology("Dilate", "Diamond:6") %>%
image_morphology("Open", "Disk:10", 3) %>%
image_blur(10,10) %>%
image_threshold("white") %>%
image_transparent("black") %>%
image_channel("Opacity") %>%
image_negate() %>%
image_crop(geometry_area(600-10, 400-10, 5,5)) %>%
image_border("black", geometry_area(5,5))
blobs
# calculate centroids of the blobs for filling
point_fills <- blobs %>%
image_morphology("Thinning", "Skeleton:3", -1) %>%
image_morphology("Thinning", "LineEnds", -1) %>%
image_morphology("Thinning", "Corners", -1) %>%
image_morphology("Thinning", "Edges", -1) %>%
image_raster() %>%
dplyr::filter(col!="#000000ff") %>%
mutate(col=RColorBrewer::brewer.pal(n(),"Set3"))
# separate blobs
blob_lst <- point_fills %>%
split(1:nrow(.)) %>%
map(~image_fill(blobs, geometry_point(.x$x, .x$y), color = .x$col) %>%
image_transparent(.x$col) %>%
image_channel("Opacity") %>%
image_convert(matte=FALSE) %>%
image_transparent("black"))
# calculate required patch sizes
patch_sizes <- blob_lst %>%
map(image_trim) %>%
map_df(image_info)
# prepare gradiented patches
patches_lst <- patch_sizes %>%
bind_cols(point_fills) %>%
mutate(width=width*1.5,
height=height*1.5) %>%
select(width, height, col) %>%
pmap(~image_blank(..1, ..2, pseudo_image = paste0("gradient:", ..3, "-white")))
# take empty canvas, apply patches where the holes will be be
# bring holes and apply them over patches
res <- map(
seq_along(blob_lst),
~image_composite(image_blank(600,400, color="white"),
patches_lst[[.x]], operator = "Atop",
offset = geometry_point(point_fills$x[.x]-patch_sizes$width[.x]/2,
point_fills$y[.x]-patch_sizes$height[.x]/2))) %>%
map2(blob_lst, ~image_composite(.x, image_negate(.y), operator="CopyOpacity"))
# animated image
res %>% {Reduce(c,.)}
# flat image
res %>% {Reduce(c,.)} %>%
image_flatten() %>%
image_transparent("white") %>%
image_background("pink")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment