大数跨境
0
0

用R语言实现抠图换景——图形分割:自动去除背景图

用R语言实现抠图换景——图形分割:自动去除背景图 简博士数据分析吧
2021-05-19
0
导读:抠图听过吧,比如证件照,可以通过美图抠图快速生成,当然,更专业地话,就得使用Photoshop了。但是,你试过用R抠图吗?



内容提要:

     *  加载和准备数据

     *  训练 U-net 模型

     *  测试模型

     *  自动去除背景

点击蓝字 |关注我们


前段时间小编我回家twitter冲浪,突然发现Rblog上贴了一个包含U-net模型的platypus包。U-net正好可以做图像分割,去除背景的任务。


我们今天就用platypus包内的U-net做一个换景的小案例。


流程大致是这样:



可能有伙伴好奇,为啥这个包叫platypus呢,platpus是啥?


当然是鸭嘴兽呀,这可是号称上古遗兽的家伙,而且非常可爱,不信,你瞅瞅。



知道了要是用的R包,下一步就是数据了。


为了训练模型,我们需要一组训练数据集。首先讲一下咱们拿到手的是什么数据。


训练数据集中的图是成对出现的,一张是包含背景和前景的正常图片;另一张是涂抹掉背景,只留下前景的被分割轮廓图。


说的这么复杂,不如看图,各位小伙伴,一看就明白了,不就是抠图么


加载和准备数据

Loading and Preparing

这里,我们使用的是牛津大学宠物数据集中的猫狗两类。


当然,小伙伴们自己练习的时候可以随便选取,注意保留对应的掩码文件就可以啦。


掩码图片:就是指涂抹掉背景,只留下前景的被分割轮廓图,是对原始数据图的一种标注,一般需要人工标注,无法依靠计算获得。


数据集,小编我已经找好了,小伙伴们在后台发送“图形分割”来获取哦~


table(dir("oxford_pets/annotations_jpg/") %in% dir("oxford_pets/images/"))table(dir("oxford_pets/images/") %in% dir("oxford_pets/annotations_jpg/"))


把宠物数据里的图片和掩码图片整理好后,先要验证一下图片和掩码图片是不是一一对应


我们可以做个随机检查,比如查看一下 image1 与 mask1:

image1 <- readJPEG("oxford_pets/images/Abyssinian_2.jpg")plot(as.raster(image1))mask1 <- readJPEG("oxford_pets/annotations_jpg/Abyssinian_2.jpg")plot(as.raster(mask1))

训练 U-net 模型

Training

初始化 U-net 模型,其实就是定义和编译网络模型,这个和 keras 很像。参数嘛,用默认的即可。

batch_size <- 32size <- 256n_training <- length(dir("oxford_pets/images/"))
test_unet <- u_net(size,size,                    grayscale = F,                    blocks = 4,                    n_class = 2 #background + foreground)
test_unet %>% compile(optimizer = optimizer_adam(lr=0.001),                      loss = loss_dice(),                      metrics = metric_dice_coeff())
test_unet

不过,由于网络结构太大了,无奈之下,小编我只能截取部分给大家看一下了:

定义好网络之后,咱们就要使用猫狗数据来“炼丹”啦。


先把供料装置安装起来:

datagen <- segmentation_generator(  path = "oxford_pets",  colormap = trinity_colormap,  only_images = F,  mode = "dir",  net_h = size, net_w = size,  grayscale = F,  batch_size = batch_size,  shuffle = F,  subdirs = c("/images", "/annotations_jpg"))


若要区分背景图、前景图和边界线,需要自定义 segmention_generator 函数中的 colormap 参数。


现在,一切准备就绪,咱们开炉炼丹!


小编我使用的是笔记本,所以迭代次数我就搞个5吧,我怕我小电脑冒烟...... 


history <- test_unet %>%  fit_generator(    datagen,    epochs = 5,    steps_per_epoch = n_training %/% batch_size,    verbose = 2)

如果小伙伴们使用过 Rstudio 下的 keras,那一定很熟悉炼丹过程中,生成的过程图:

迭代了5次之后,loss就比较小了,dice coefficient 大约是0.9,这个结果其实还是说的过去的。


loss大家都比较熟悉,这里就解释一下dice coefficient。这个因子用来对比预测的掩码图片和实际掩码图片的相似度,即调和平均精度,harmonic mean of precision,其实英文更加容易理解😮


虽然只训练了5次,但好不容易也练出了一颗丹,自然要保存一下。


此外,悄悄地说一声,加载模型的方法,小编我写在了保存的模型下面,大家按需食用。


save_model_weights_tf(test_unet, "unet_model_weights")load_model_weights_tf("unet_model_weights")

测试模型

Testing 

到这里,其实拿上面的模型就可以做许多东西了。


但是,为了呼应开头,我们还是 “画” 图片的掩码,去除图片背景。


我找了只鸟的图片。训练的猫狗,让找鸟,貌似不是很合适,但是手里只有这么一张图了

bird <- image_load("birds_folder/starling female/020.jpg", target_size = c(size,size)) bird %>%  image_to_array() %>%   `/`(255) %>%  as.raster() %>%  plot()

把上面加载进来的鸟儿输入到模型,得到掩码图片:

x <- bird %>%   image_to_array() %>%  array_reshape(., c(1, dim(.))) %>%  `/`(255)
mask <- test_unet %>% predict(x) %>%  get_masks(binary_colormap)
plot(as.raster(mask[[1]]/255))

emmmm 模型出的结果不是很好,把鸟儿脚下的木头也给识别成小鸟的一部分了。


主要是由于模型的前景色和背景色相近导致的样。大家在训练的时候,可以构建更加复杂的网络,以提高模型对图形的识别能力。

自动去除背景

Removing

现在,咱们可以写个小函数,从读取图片、生成掩码图片到换景一气呵成地做完。


即通过训练好的模型,得到掩码图片,然后贴到你喜欢的背景图上,实现换景操作。

change_background <- function(image, background){  img <- image_load(image, target_size = c(size,size))    x <- img %>%     image_to_array() %>%    array_reshape(., c(1, dim(.))) %>%    `/`(255)    mask <- test_unet %>% predict(x) %>%    get_masks(binary_colormap)     mask_blur <- magick::image_read(mask[[1]]/255) %>%    image_blur(20,5)     img_crop <- image_composite(image_read(image_to_array(img)/255), mask_blur,operator = "CopyOpacity")                                background <- image_read(background)    image_composite(background, img_crop, gravity = "center")  }


咱们用的这个是猴面鹰,也称作仓鸮(xiao),是国家二级保护动物,和猫头鹰的习性类似。



我们用大海做背景图:


咱们现在把原图和背景图放到刚才自编的小函数中


change_background(image = "birds/owl/612.jpg",                  background = "backgrounds/random_water.jpg")


然后,就得到在大海上翱翔的猴面鹰了。



效果貌似有点不理想,只是给大家提供个指引。小伙伴们做的时候,可以通过下面几个小Tips提高 ”换景“ 的效果噢:


  • 训练的时间长一点;


  • 训练背景、前景、和边界三类图作为原始用图,并在此基础上使用一些模糊、透明等函数处理;


  • 可以使用 R-CNN 来代替 U-Net 网络。



参考文献

Image segmentation in R: Automatic background removal like in a Zoom conference

欢迎大家关注简博士的B站和公众号,在公众号私信“入群”,可以与小伙伴们一起讨论问题哦。

扫码关注我们

微信号|Dr_Janneil

B站|简博士

【声明】内容源于网络
0
0
简博士数据分析吧
信息时代最不缺的是什么?数据!最缺的是什么?数据分析的思维!在这里,你将获取神秘的力量,推开数据之门!
内容 181
粉丝 0
简博士数据分析吧 信息时代最不缺的是什么?数据!最缺的是什么?数据分析的思维!在这里,你将获取神秘的力量,推开数据之门!
总阅读66
粉丝0
内容181