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

台州网站排名绵阳住房和城乡建设厅官方网站

台州网站排名,绵阳住房和城乡建设厅官方网站,石家庄微信网站制作,进度插件 wordpress“他山之石#xff0c;可以攻玉”#xff0c;站在巨人的肩膀才能看得更高#xff0c;走得更远。在科研的道路上#xff0c;更需借助东风才能更快前行。为此#xff0c;我们特别搜集整理了一些实用的代码链接#xff0c;数据集#xff0c;软件#xff0c;编程技巧等可以攻玉”站在巨人的肩膀才能看得更高走得更远。在科研的道路上更需借助东风才能更快前行。为此我们特别搜集整理了一些实用的代码链接数据集软件编程技巧等开辟“他山之石”专栏助你乘风破浪一路奋勇向前敬请关注。作者知乎—尹相楠原文地址https://zhuanlan.zhihu.com/p/310710051前几天研究了传统的美颜算法了解到双边滤波(bilateral filtering)。在看懂原理后为加深理解抽时间用 pytorch 重新造了个轮子。虽然效率肯定比不上 opencv 但当个小练习也不错。为了方便复习以及帮助初学者在此记录。01高斯滤波1. 高斯核函数图像领域的高斯滤波器是个二维的矩阵。矩阵中每个元素的值与它与矩阵中心的距离有关计算公式就是二维高斯函数的公式为了让卷积前后的图像亮度保持不变需要对 (1) 计算的矩阵归一化(除以矩阵所有元素的和)因此 (1) 中 exp 之前的系数部分可以省略。生成高斯滤波器的代码如下torch.no_grad()def getGaussianKernel(ksize, sigma0): if sigma 0: # 根据 kernelsize 计算默认的 sigma和 opencv 保持一致 sigma 0.3 * ((ksize - 1) * 0.5 - 1) 0.8 center ksize // 2 xs (np.arange(ksize, dtypenp.float32) - center) # 元素与矩阵中心的横向距离 kernel1d np.exp(-(xs ** 2) / (2 * sigma ** 2)) # 计算一维卷积核 # 根据指数函数性质利用矩阵乘法快速计算二维卷积核 kernel kernel1d[..., None] kernel1d[None, ...] kernel torch.from_numpy(kernel) kernel kernel / kernel.sum() # 归一化 return kernel2. 高斯滤波器pytorch 自带的 conv2d 可以很方便地对图像施加高斯滤波代码如下def GaussianBlur(batch_img, ksize, sigmaNone): kernel getGaussianKernel(ksize, sigma) # 生成权重 B, C, H, W batch_img.shape # C图像通道数group convolution 要用到 # 生成 group convolution 的卷积核 kernel kernel.view(1, 1, ksize, ksize).repeat(C, 1, 1, 1) pad (ksize - 1) // 2 # 保持卷积前后图像尺寸不变 # moderelfect 更适合计算边缘像素的权重 batch_img_pad F.pad(batch_img, pad[pad, pad, pad, pad], modereflect) weighted_pix F.conv2d(batch_img_pad, weightkernel, biasNone, stride1, padding0, groupsC) return weighted_pix关于 group convolution如果不熟悉可以看我这篇回答什么是「Grouped Convolution」https://www.zhihu.com/question/60484190/answer/150778317902双边滤波高斯滤波器的权重完全由距离决定。在大块颜色差不多、偶有噪点的区域它可以把颜色平均化从而过滤掉噪点。但是在颜色变化剧烈的边缘区域它还是一视同仁地把所有像素做加权平均这让本应该清晰锐利的边缘也变得模糊不清了这就造成了如下图所示的效果在做人像美颜时是不希望看到的。这里就引入了双边滤波(bilateral filtering)。双边滤波的权重公式也基于高斯函数。但和高斯滤波的区别是决定卷积核权重的不单纯是像素之间的空间距离还包括像素之间的亮度差异。以卷积核中心为坐标原点该处像素值为I(0,0)。那么坐标为 (u, v) 处的像素对应的权重为(2) 中 exp 的第一个指数项和高斯核函数相同与像素的空间距离有关第二个指数项则是像素值距离的函数。以e为底对这两项做指数运算再相乘即得到了公式 (2)。根据公式 (2) 计算的卷积核有如下性质距离中心像素越远的像素其权重就越小亮度和中心像素亮度差异越大的像素其权重就越小第一条比较好理解第二条的含义是像素只和与自己相似的像素求平均不和与自己差别太大的像素求平均。例如上图中人脸部分的像素和背景部分的像素差异过于显著这将导致在对边缘区域做卷积时背景侧像素对人脸侧的像素的权重极小反之同理。这就达到了保持边缘 (edge-preserving) 的特性。03代码实现由于 (2) 中卷积核的权重不仅仅依赖于空间距离还依赖于像素的亮度因此卷积核的权重是不固定的不能简单地利用 pytorch 的 conv2d 来实现。pytorch 的 tensor 自带了一个 unfold 方法正好可以用在这里。unfold 的作用是把图像拆分成 patch每个patch 为卷积核覆盖的像素。下面举个小例子import torchx torch.arange(12).view(3, 4)xOut[4]: tensor([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])# 沿着行以步长 1 拆分 x每个 patch 为 2 行列保持不变y x.unfold(dimension0, size2, step1) y.shapeOut[6]: torch.Size([2, 4, 2])y[0]Out[7]: tensor([[0, 4], [1, 5], [2, 6], [3, 7]])y[1]Out[8]: tensor([[ 4, 8], [ 5, 9], [ 6, 10], [ 7, 11]])# 直接对 y 的第二个维度拆分例如拆分成 3 列步长仍为 1z y.unfold(dimension1, size3, step1)z.shapeOut[10]: torch.Size([2, 2, 2, 3])# 观察 z[0, 0]发现正是 x 左上角的六个元素z[0,0]Out[11]: tensor([[0, 1, 2], [4, 5, 6]])# z[0, 1] 也同样符合预期z[0,1]Out[12]: tensor([[1, 2, 3], [5, 6, 7]])实现的思路是把原始图像 unfold 成一个个的 patch对每个 patch 计算权重以及加权平均。代码如下def bilateralFilter(batch_img, ksize, sigmaColorNone, sigmaSpaceNone): device batch_img.device if sigmaSpace is None: sigmaSpace 0.15 * ksize 0.35 # 0.3 * ((ksize - 1) * 0.5 - 1) 0.8 if sigmaColor is None: sigmaColor sigmaSpace pad (ksize - 1) // 2 batch_img_pad F.pad(batch_img, pad[pad, pad, pad, pad], modereflect) # batch_img 的维度为 BxcxHxW, 因此要沿着第 二、三维度 unfold # patches.shape: B x C x H x W x ksize x ksize patches batch_img_pad.unfold(2, ksize, 1).unfold(3, ksize, 1) patch_dim patches.dim() # 6 # 求出像素亮度差 diff_color patches - batch_img.unsqueeze(-1).unsqueeze(-1) # 根据像素亮度差计算权重矩阵 weights_color torch.exp(-(diff_color ** 2) / (2 * sigmaColor ** 2)) # 归一化权重矩阵 weights_color weights_color / weights_color.sum(dim(-1, -2), keepdimTrue) # 获取 gaussian kernel 并将其复制成和 weight_color 形状相同的 tensor weights_space getGaussianKernel(ksize, sigmaSpace).to(device) weights_space_dim (patch_dim - 2) * (1,) (ksize, ksize) weights_space weights_space.view(*weights_space_dim).expand_as(weights_color) # 两个权重矩阵相乘得到总的权重矩阵 weights weights_space * weights_color # 总权重矩阵的归一化参数 weights_sum weights.sum(dim(-1, -2)) # 加权平均 weighted_pix (weights * patches).sum(dim(-1, -2)) / weights_sum return weighted_pix最终结果为下图雀斑都没了同时人脸的轮廓和五官的细节依然被很好地保留下来输入图片尺寸为 256 x 256ksize15sigmaColor0.15sigmaSpace5 。需要注意的是由于 bilateral filter 的权重和像素值相关因此设置 sigmaColor 时要注意输入图像的像素范围看清楚到底是 0-1 还是 0-255(上图像素范围为 0-1)。04总结本文介绍了双边滤波的基本原理并附带了 pytorch 的实现。虽然不如 opencv 快但优点是 backward trackable 适合包装为模块加入网络中。利用 unfold 实现的缺点是很占内存/显存kernelsize 越大unfold 出来的冗余数据就越多如果有大神知道更高效的实现方式还望不吝赐教。05后记我发现网上搜到的很多磨皮祛斑的算法主要的目标是设计一个高通滤波器从而得到一个基于像素亮度的 mask亮的地方权重大(对应皮肤区域)暗的地方权重小(对应雀斑、噪点区域)。将原图 I 和 模糊化的图I_blur(各种模糊化方式都可以目标是把较暗的斑点模糊掉)利用 mask 融合I_maskI_blur(1-mask) 。这种方法既保留了原图的细节又能模糊掉斑点不过在不同图片上应用时仍然免不了调整一些超参数而真有调参的功夫直接调一下双边滤波的几个参数最后得到的效果未必比那些复杂的算法差。本文目的在于学术交流并不代表本公众号赞同其观点或对其内容真实性负责版权归原作者所有如有侵权请告知删除。“他山之石”历史文章编译PyTorch静态库工业界视频理解解决方案大汇总动手造轮子-rnn凭什么相信你我的CNN模型关于CNN模型可解释性的思考“最全PyTorch分布式教程”来了c接口libtorch介绍 vscodecmake实践python从零开始构建知识图谱一文读懂 PyTorch 模型保存与载入适合PyTorch小白的官网教程Learning PyTorch With Examplespytorch量化备忘录LSTM模型结构的可视化PointNet论文复现及代码详解SCI写作常用句型之研究结果发现白话生成对抗网络GAN及代码实现pytorch的余弦退火学习率更多他山之石专栏文章请点击文章底部“阅读原文”查看分享、点赞、在看给个三连击呗
http://www.sadfv.cn/news/2222/

相关文章: