实验要求:
给定函数:function im = jbf(D,C,w, sigma_f, sigma_g)
其中:D为输入图像;C为引导图像;W为滤波窗口大小;
sigma_f 为spatial kernel标准差;
sigma_g为range kernel 标准差;
给定公式:

其中:p是q的邻域中的一个像素。 f和g是空间和距离内核,通常以高斯的形式表示,I是输入图像。
f 是空间滤波器内核,定义为:exp([-d_ f^ 2]/[2*sigma_f^2])

其中:d_ f 为输入图像I的像素位置差,sigma_ f为空间滤波核函数的标准差
g是距离滤波器内核,定义为:exp([-d_g^ 2]/[2*sigma_g^2])
其中:d_g为引导图像 的像素灰度值差,sigma_g为滤波核函数的标准差

输入图像I下采样(1/2)得到LR低分辨率图像,再由LR图像上采样2倍得到引导图像。
注:图像缩放采用双线性插值。
实验思路:
1.根据双线性插值对图像缩放。双线性插值,是将输出图像dst的某像素(x, y)映射到原图像src中的位置,再根据公式计算像素的值。参考了https://blog.csdn.net/pentiumCM/article/details/104720100
2.滤波器的计算没什么难度。
实验效果:
输入时可以尝试的参数:
滤波器尺寸、空间滤波器sigma、距离滤波器sigma
3 1 1: 19秒,感觉几乎没变化
5 10 10:30秒,很轻微的变化
7 10 20:45秒,明显的变化
8 10 20:57秒,明显变化,还行
9 10 20:72秒,很不错,真实
13 13 30:131秒,非常漂亮
25 12.5 50:451秒,有点假
上面的451秒实在是太慢了,难以接受。通过大量修改代码使用numpy运算,451秒变为11秒左右,19秒变为6秒左右。目前还是比较满意的。




实验代码:

import cv2 as cv
import numpy as np
import mathdef jbf(D, C, W, sigma_f, sigma_g):"""brief: 实现图像的联合双边滤波处理:param D: 输入图像:param C: 引导图像:param W: 滤波窗口大小:param sigma_f: spatial kernel 标准差:param sigma_g: range kernel 标准差:return: 元组(JBF后的图像,执行时间)"""timeBegin = cv.getTickCount()  # 记录开始时间# 让变量更清楚一些imgSrc = DimgGuide = Csize = W // 2 * 2 + 1  # 重新调整滤波器大小,保证为奇数sigmaSpatial = sigma_fsigmaRange = sigma_g# 两次采样后,可能会导致图像的shape不一致,因此选择最小值rowsSrc, colsSrc, channels = imgSrc.shaperowsGuide, colsGuide, channels = imgGuide.shaperows = min(rowsSrc, rowsGuide)cols = min(colsSrc, colsGuide)imgSrc = imgSrc[:rows, :cols, :]imgGuide = imgGuide[:rows, :cols, :]# Spatial KernelkernelSpatial = np.zeros([size, size], dtype=np.float)center = size // 2  # 将滤波器分为size x size个小方格,中心点为center,坐标为(0, 0)for i in range(size):for j in range(size):x = i - center  # 方格的横坐标y = center - j  # 方格的纵坐标kernelSpatial[i, j] = np.exp(-(x ** 2 + y ** 2) / (2 * sigmaSpatial ** 2))#print(kernelSpatial[i, j], end=' ')  # 打印Spatial模板,与下一行共同使用#print('')  # 打印Spatial模板,与上一行共同使用# Range Kernel# 提前计算 2*sigmaRange**2代入公式,对于这个计算会提升25%的速度,但由于其本身时间仅为0.0004311s# 加速后也仅为0.0002932s,因此意义不大kernelRange = np.zeros([256], dtype=np.float)for i in range(256):kernelRange[i] = np.exp(-(i ** 2) / (2 * sigmaRange ** 2))#print(kernelRange[i], end=' ')  # 打印Range模板# 输出的图像imgDst = np.zeros([rows, cols, channels], dtype='uint8')# 边界填充,imgFillSrc为对原图的边界扩充,imgFillGuide为对引导图的边界扩充border = center  # 需要添加的边界大小imgFillSrc = cv.copyMakeBorder(imgSrc, border, border, border, border,borderType=cv.BORDER_REPLICATE)imgFillGuide = cv.copyMakeBorder(imgGuide, border, border, border, border,borderType=cv.BORDER_REPLICATE)# 为了便于计算,改为np.intimgFillSrc = imgFillSrc.astype(np.int)imgFillGuide = imgFillGuide.astype(np.int)# matSpatial就是kernelSpatial的三维形式matSpatial = np.zeros([size, size, channels], dtype=np.float)for k in range(channels):matSpatial[:, :, k] = kernelSpatial# matRange 储存距离滤波器内核对imgFillGuide的结果matRange = np.zeros([size, size, channels], dtype=np.float)# 开始滤波操作for i in range(rows):for j in range(cols):# 计算matRange。colorDiff是灰度差colorDiff = np.abs(imgFillGuide[i:i + size, j:j + size, :] - imgFillGuide[i + center, j + center, :])matRange = kernelRange[colorDiff]# matMulti 储存空间滤波器和内核滤波器相乘的结果matMulti = np.multiply(matSpatial, matRange)# sumMat为matMulti元素的和,matMulti的shape为(size, size, channels),sumMat的shape为(channels,)sumMat = np.sum(np.sum(matMulti, axis=0), axis=0)matMulti = np.multiply(matMulti, imgFillSrc[i:i+size, j:j+size, :])temp = np.sum(np.sum(matMulti, axis=0), axis=0) / sumMat# 限制在0~255范围temp = np.minimum(temp, 255)temp = np.maximum(temp, 0)imgDst[i, j, :] = temptimeEnd = cv.getTickCount()  # 记录结束时间time = (timeEnd - timeBegin) / cv.getTickFrequency()  # 计算总时间return imgDst, timedef sampling(imgSrc, scaleRow, scaleCol):"""双线性插值法,来调整图片尺寸:param imgSrc: 原始图片:param scaleRow: x的倍数变化,eg. 0.5; 1; 2:param scaleCol: y的倍数变化,eg. 0.5; 1; 2:return: 元组(缩放后的图像,执行时间)"""timeBegin = cv.getTickCount()  # 记录开始时间rowsSrc, colsSrc, channels = imgSrc.shaperowsDst = int(rowsSrc*scaleRow)colsDst = int(colsSrc*scaleCol)dst_img = np.zeros((rowsDst, colsDst, channels), dtype='uint8')# i:纵坐标y,j:横坐标x# 缩放因子,scaleCol 和 scaleRow,和函数的参数不一样scaleCol = colsSrc / colsDstscaleRow = rowsSrc / rowsDstfor i in range(rowsDst):for j in range(colsDst):srcX = float((j + 0.5) * scaleCol - 0.5)srcY = float((i + 0.5) * scaleRow - 0.5)# 向下取整,代表靠近源点的左上角的那一点的行列号srcXint = math.floor(srcX)srcYint = math.floor(srcY)# 取出小数部分,用于构造权值srcXfloat = srcX - srcXintsrcYfloat = srcY - srcYintif srcXint + 1 == colsSrc or srcYint + 1 == rowsSrc:dst_img[i, j, :] = imgSrc[srcYint, srcXint, :]continuedst_img[i, j, :] = (1. - srcYfloat) * (1. - srcXfloat) * imgSrc[srcYint, srcXint, :] + \(1. - srcYfloat) * srcXfloat * imgSrc[srcYint, srcXint + 1, :] + \srcYfloat * (1. - srcXfloat) * imgSrc[srcYint + 1, srcXint, :] + \srcYfloat * srcXfloat * imgSrc[srcYint + 1, srcXint + 1, :]timeEnd = cv.getTickCount()  # 记录结束时间time = (timeEnd - timeBegin) / cv.getTickFrequency()  # 计算总时间return dst_img, timesize = int(input('Please input the size of kernel: '))
sigmaSpatial = float(input('Please input the value of Spatial sigma: '))
sigmaRange = float(input('Please input the value of Range sigma'))
"""
不断的优化后,下面的时间已经大为减少,如最后一个451秒,现在也只需要11.28秒,最开始的一个19秒,变为6.52秒
参数(按照上面顺序):3  1  1: 19秒,感觉几乎没变化5  10 10:30秒,很轻微的变化7  10 20:45秒,明显的变化8  10 20:57秒,明显变化,还行9  10 20:72秒,很不错,真实13 13 30:131秒,非常漂亮25 12.5 50:451秒,有点假
"""imgSrc = cv.imread('../images/images2_2/2_2.png')
imgDownSamp, timeDown = sampling(imgSrc, 0.5, 0.5)  # 这里可以修改下采样率
imgUpSamp, timeUp = sampling(imgDownSamp, 2, 2)  # 这里可以修改上采样率
imgGuide = imgUpSampimgJBF, timeJBF = jbf(imgSrc, imgGuide, size, sigmaSpatial, sigmaRange)print('DownSamp image(s):', timeDown)
print('UpSamp image(s):', timeUp)
print('JBF image(s):', timeJBF)cv.imshow('source image', imgSrc)
cv.imshow('guide image', imgGuide)
cv.imshow('jbf image', imgJBF)cv.waitKey(0)
cv.destroyAllWindows()

OpenCV实验(4):实现图像的联合双边滤波处理相关推荐

  1. 【OpenCV 例程200篇】60. 非线性滤波—联合双边滤波

    [OpenCV 例程200篇]60. 非线性滤波-联合双边滤波(Joint bilateral filter) 欢迎关注 『OpenCV 例程200篇』 系列,持续更新中 欢迎关注 『Python小白 ...

  2. 【OpenCV 例程200篇】59. 非线性滤波—双边滤波

    [OpenCV 例程200篇]59. 非线性滤波-双边滤波(Bilateral filter) 欢迎关注 『OpenCV 例程200篇』 系列,持续更新中 欢迎关注 『Python小白的OpenCV学 ...

  3. 双边滤波(bilateral filter)以及联合双边滤波(joint bilateral filter)

    文章目录 双边滤波 理论公式 代码(C++) 数学辅助理解 联合双边滤波(joint bilateral filter) 参考链接 写在最后 双边滤波 自用备忘,若侵则删. 理论公式 利用二维高斯函数 ...

  4. 联合双边滤波-Joint Bilateral Filter

    1. 回顾: 双边滤波(BF) 具体参考上篇博客:图像滤波之双边滤波 2. 联合双边滤波(JBF) 联合双边滤波与双边滤波之间的差别就是JBF用了一个引导图作为值域权重的计算依据,但是空间域权重计算仍 ...

  5. 利用联合双边滤波或引导滤波进行升采样(Upsampling)技术提高一些耗时算法的速度。...

    这十年来,在图像处理领域提出了很多新的图像分析和处理方法,包括是自动的以及一些需要有人工参与的,典型的比如stereo depth computations.image colorization.to ...

  6. 中值滤波,均值滤波,高斯滤波,双边滤波,联合双边滤波介绍

    看GAMES202相关课程发现闫老师讲的太好了,所以记录一下.当然文中涉及的PPT也来自闫老师的课程PPT,欢迎交流. 首先这几种都是空域的滤波方式,用于抑制图像中的噪声.它们采用的原理基本都是通过滤 ...

  7. games202:六,实时光线追踪RTRT:Temporal Filtering、联合双边滤波、Outlier Removal、SVGF、RAE

    games202:六,实时光线追踪RTRT:Temporal Filtering.联合双边滤波.Outlier Removal .SVGF.RAE RTRT现状 实时降噪方法 一,Temporal F ...

  8. 图像处理-双边滤波和联合双边滤波

    图像处理-双边滤波和联合双边滤波 双边滤波原理 ​ 双边滤波(Bilateral Filter)是一种非线性滤波器,可以达到保持边缘,降噪平滑的效果.其算法最早由C. Tomasi和R. Manduc ...

  9. 【OpenCV】邻域滤波:方框、高斯、中值、双边滤波

    邻域滤波(卷积) 邻域算子值利用给定像素周围像素的值决定此像素的最终输出.如图左边图像与中间图像卷积禅城右边图像.目标图像中绿色的像素由原图像中蓝色标记的像素计算得到. 通用线性邻域滤波是一种常用的邻 ...

最新文章

  1. 【怎样写代码】对象克隆 -- 原型模式(三):原型模式
  2. 【Java】 Java网络编程总结
  3. android java 给控件设置style,在Android Lollipop for Material Design中为SwitchCompat按钮设置样式/着色...
  4. Matlab图形绘制
  5. C++ 学习之旅(12)——static用法小结
  6. linux 解压文件zip格式
  7. easyui中idField的作用
  8. 腾讯看点CTO徐羽: QQ浏览器背后的推荐AI中台 | AICon
  9. soapUI 接口测试断言
  10. 认识netty+实战
  11. 翻译记忆软件-塔多思TRADO经典教程_2
  12. 解决问题最重要的习惯不是一直盯着屏幕和编写修改代码,某些时候,阻止你成功的东西恰恰会是过于努力。这时候你需要暂停一下,平缓你的思绪,换一种方法或许能带给你不一样的效果。
  13. 空之轨迹手游服务器维护,空之轨迹7月9日临时维护公告_空之轨迹7月9日更新了什么_玩游戏网...
  14. 神秘网络蠕虫不搞破坏却让几万台服务器抵抗木马
  15. 获取滚动条滚动距离兼容写法
  16. java NIO BIO和AIO
  17. python中for无限循环_关于循环:在Python中从1循环到无穷大
  18. HTML中的删除线:del和s的区别
  19. acer(宏碁) Aspire S3-951 笔记本无线网卡连接不稳定原因及解决
  20. .net core 阿里云ddns解析

热门文章

  1. 【云计算入门3】基础技术和并行计算模型
  2. Windows10下局域网的两台电脑间传输文件,设置文件夹共享
  3. 无线智能插座的Android客户端软件代码框架
  4. 按规则生产txt文本
  5. PHP 快递鸟接口封装
  6. DSP CCS12.00 芯片:TMS320F28335 结课设计 综合设计 TFTLCD + 按键 + 蜂鸣器 + 流水灯
  7. 用四阶龙格-库塔方法求微分方程组
  8. Jenkins任务分组
  9. PAT乙级 1009 说反话
  10. 猜数字小游戏(图像用户界面编程实验——猜数字游戏)