当前位置: 首页 > news >正文

使用深度图像实现照片虚化效果

使用深度图像实现照片虚化效果

语雀:https://www.yuque.com/lart/blog/vw6pcx

原理介绍

随着智能手机的发展,手机自带的相机功能也逐渐变得丰富起来。其中的“人像模式”可以模仿单反相机的效果,将特定目标突出并将其余背景虚化。这一效果可以获得良好的视觉效果,有效的突出感兴趣目标的主体。

在这里插入图片描述

从理论上来说,实现这一效果有两种思路。

  • 基于图像处理的办法:对主体目标进行分割后,获得前背景对应的区域。利用算法模糊背景区域的内容,即实现虚化的效果。
  • 基于深度信息的办法:部分手机利用硬件支持或者软件算法处理,可以得到近似的视差信息,即照片对应的深度图。基于得到的深度图数据,对深度进行过滤,从而依据相对深度或者绝对深度识别出感兴趣区域,为不同深度位置提供不同程度的虚化效果。

本文尝试对第二种方法进行一些简单的尝试。

需要说明的是,这里为了方便利用并行加速,所以代码都是基于 pytorch 实现的。

实现细节

对于第二种思路,一种直观的实现方式是使得模糊核与深度相关联,越远的位置对应的模糊程度越大。

这里我们基于均值滤波的形式进行扩展。让滤波器的权重分布在均值滤波器的基础上进行调整。

归一化深度数据

由于我们的 depth 图像中深度数据是 0~255 的数值,为了后面将其用作用于调整均值核和恒等核之间的变换参数,这里我们对 depth 图像进行 minmax 归一化:

depth = depth - depth.min()
depth = depth / depth.max()

折叠图像数据

在我们的处理中,可以注意到与传统的直接对整个背景整体模糊的形式最大的不同,即我们是根据不同位置自身对应的深度信息来自适应的调整模糊程度。所以这种位置自适应的处理形式就需要我们借助于 pytorch 提供的 img2col 函数 unfold 来实现了:

image = image.permute(2, 0, 1).unsqueeze(0)
image = F.pad(image, pad=(kernel_size//2, kernel_size//2, kernel_size//2, kernel_size//2), mode='replicate')
image = F.unfold(image, kernel_size=kernel_size)
image = image.reshape(num_channels, kernel_size*kernel_size, height, width)

这里同时利用 replicate 的模式来补齐边缘处的像素,以确保后期加权平均不会出现明显的暗边。

关于 unfold 的理解,可以参看我之前的文章中的介绍:https://www.yuque.com/lart/papers/frxyq3#sptFi。其就是用于将局部方形邻域的数据收集起来,堆叠到通道维度上。可以说其实现了卷积中的局部聚合操作中加权之前的行为。

生成权重

weight = get_log_kernel2d_pt(kernel_size=kernel_size, valid_ratio=depth, normalize=True)

这里将归一化后的 depth 传入了 valid_ratio 上。首先对这一参数进行约束,保证数值范围满足要求:

assert valid_ratio.min() >= 0 and valid_ratio.max() <= 1

这一参数用来调整核参数的形式:

  • 元素值为 1 的时候,对应的核形式为均值滤波器;
  • 元素值为 0 的时候,对应的核形式为恒等核,即仅有中心参数为 1,其余均为 0。

基于后面的设计,我们还需要将这一参数映射到 [ 0 , inf ⁡ ] [0, \inf] [0,inf] 区间上,其中 0 对应于恒等核,而正无穷对应于均值滤波器。这里基于负对数函数的形式:

valid_ratio = -torch.log(1 - valid_ratio)

为了对这些滤波器以均值滤波器为基础进行统一表示,我们引入了绝对值函数作为加权窗口中各点的权重分布形式。即 F.relu(1 - torch.abs(coords / valid_width)).nan_to_num(nan=1) 所表示的形式:

  • valid_width=0 的时候,对于相对坐标为 0 处,1 - torch.abs(coords / valid_width) 结果为 nan,而其余位置均为 -inf,通过 relu.nan_to_num() 处理后,可以得到恒等核,仅保留中心元素,其余元素的参数均为 0。
  • valid_width 趋向于无穷大的时候,此时开始从恒等核逐步向均值核变化。
title: PyTorch 中几个特殊值的除法

- inf / inf = nan
- num / inf = 0
- inf / num = inf
- \* / 0 = inf
- nan / \* = nan
- \* / nan = nan
>>> a = torch.tensor([-torch.inf, -1, 0, 1, torch.inf, torch.nan]) 
>>> a / -torch.inf 
tensor([nan, 0., -0., -0., nan, nan])
>>> a / -1        
tensor([inf,  1., -0., -1., -inf, nan])
>>> a / 0         
tensor([-inf, -inf, nan, inf, inf, nan])
>>> a / 1 
tensor([-inf, -1.,  0.,  1., inf, nan])
>>> a / torch.inf  
tensor([nan, -0., 0., 0., nan, nan])
>>> a / torch.nan
tensor([nan, nan, nan, nan, nan, nan])

二维权重可以通过一维权重矩阵相乘来获得。这里利用 einsum 来保留原始的形状,避免直接压缩维度后还需重新调整形状的麻烦。

kernel_1d = F.relu(1 - torch.abs(coords / valid_width)).nan_to_num(nan=1)
kernel_2d = torch.einsum("xhw,yhw->xyhw", kernel_1d, kernel_1d)
kernel_2d = kernel_2d.reshape(-1, *ori_shape)  # 压缩前两个维度

最终,我们可以根据需要来对权重进行归一化,以确保总和为 1:

if normalize:
    kernel_2d = kernel_2d / kernel_2d.sum(dim=0)

合成图像

直接对权重和原图相乘加和后得到结果:

tgt_image = (image * weight).sum(dim=1)
tgt_image = tgt_image.permute(1, 2, 0).numpy()

链接

  • 完整代码可见:https://github.com/lartpang/CodeForArticle/blob/main/MergeRGBDImages.Pytorch/main.py

相关文章:

  • reatc的几个基础的hooks
  • EN 14846建筑五金件锁和闩锁—CE认证
  • 一幅长文细学Vue目录
  • 运营业务指标--分类型探讨
  • 软考中活动图,关键路径、最早开始时间等
  • dotnet6 docker 部署
  • 【步骤详解】Docker一键部署微服务详细教程
  • LTC4056/TP4056国产替代DP4056锂电池充电保护芯片
  • VUE页面添加水印
  • 小米软开一面
  • 创建型模式-抽象工厂模式(三)
  • 美术作品登记版权如何收费?
  • 计算机毕业论文基于Python实现的仓库库存管理系统进销存储系统
  • 人工神经网络 人工智能,人工智能神经网络技术
  • 基于springboot的手办定制销售系统毕业设计源码031800
  • 4. 路由到控制器 - Laravel从零开始教程
  • 78. Subsets
  • angular学习第一篇-----环境搭建
  • Docker入门(二) - Dockerfile
  • HashMap剖析之内部结构
  • IDEA 插件开发入门教程
  • Java Agent 学习笔记
  • rc-form之最单纯情况
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • 复习Javascript专题(四):js中的深浅拷贝
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 回顾 Swift 多平台移植进度 #2
  • 前端路由实现-history
  • 前端自动化解决方案
  • 实习面试笔记
  • 手写一个CommonJS打包工具(一)
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • 进程与线程(三)——进程/线程间通信
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • #laravel 通过手动安装依赖PHPExcel#
  • #大学#套接字
  • #每日一题合集#牛客JZ23-JZ33
  • (39)STM32——FLASH闪存
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)iOS字体
  • (转)大道至简,职场上做人做事做管理
  • (转载)(官方)UE4--图像编程----着色器开发
  • **PHP二维数组遍历时同时赋值
  • .NET 实现 NTFS 文件系统的硬链接 mklink /J(Junction)
  • .NetCore项目nginx发布
  • .net程序集学习心得
  • .NET企业级应用架构设计系列之应用服务器
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • .project文件
  • /bin/bash^M: bad interpreter: No such file or directory
  • @Autowired自动装配