Bilateral Filtering for Gray and Color Images

双边滤波器:保留边界的平滑滤波器。 在局部上,就是在灰度值差异不大的区域平滑,在灰度值差异比较大的边界地区保留边界。所以双边滤波器作用于每个像素的同时,必然会受到领域像素点的距离、灰度值差的权重影响。

已知低通滤波可以表示为:

range filter可以表示为:(range filter 试选定一个数值范围,再做滤波的一个操作)

所以,双边滤波器的定义是:

其中,k(x)是归一化(normalize)函数,

( f 表示原图像,h 表示处理后的图像 x 表示 h 中某个像素点位置,ξ 表示 f 中x位置像素点的邻域像素,f(ξ)表示该像素点的灰度值,c表示低通滤波, s表示range filter)

其中,

//Filters.h

#ifndef FILTERS_H
#define FILTERS_H#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core.hpp"#include <iostream>
#include <cmath>//Bilateral Filtering
//sigmaD == sigmaSpace, sigmaR == sigmaColor
cv::Mat BilateralFilter(cv::Mat inputImg, int filterSize, double sigmaD, double sigmaR);cv::Mat fastBilateralFilter(cv::Mat inputImg, int filterSize, double sigmaD, double sigmaR);#endif // ! FILTERS_H

//Filters.cpp

#include "Filters.h"double SpaceFactor(int x1, int y1, int x2, int y2, double sigmaD) {double absX = pow(abs(x1 - x2), 2);double absY = pow(abs(y1 - y2), 2);return exp(-(absX + absY) / (2 * pow(sigmaD, 2)));
}double ColorFactor(int x, int y, double sigmaR) {double distance = abs(x - y) / sigmaR;return exp(-0.5 * pow(distance, 2));
}cv::Mat BilateralFilter(cv::Mat inputImg, int filterSize, double sigmaD, double sigmaR) {int len; //must be odd numbercv::Mat gray; // must be 1-channel imagecv::Mat LabImage; // if channels == 3if (filterSize % 2 != 1 || filterSize <= 0) {std::cerr << "Filter Size must be a positive odd number!" << std::endl;return inputImg;}len = filterSize / 2;if (inputImg.channels() >= 3) {cv::cvtColor(inputImg, LabImage, cv::COLOR_BGR2Lab);gray = cv::Mat::zeros(LabImage.size(), CV_8UC1);for (int i = 0; i < LabImage.rows; i++) {for (int j = 0; j < LabImage.cols; j++) {gray.ptr<uchar>(i)[j] = LabImage.ptr<uchar>(i, j)[0];}}}else if(inputImg.channels() == 1){inputImg.copyTo(gray);}else {std::cerr << "the count of input image's channel can not be 2!" << std::endl;return inputImg;}cv::Mat resultGrayImg = cv::Mat::zeros(gray.size(), CV_8UC1);for (int i = 0; i < gray.rows; i++) {for (int j = 0; j < gray.cols; j++) {double k = 0;double f = 0;for (int r = i - len; r <= i + len; r++) {for (int c = j - len; c <= j + len; c++) {if (r < 0 || c < 0 || r >= gray.rows || c >= gray.cols)continue;f = f + gray.ptr<uchar>(r)[c] * SpaceFactor(i, j, r, c, sigmaD) * ColorFactor(gray.ptr<uchar>(i)[j], gray.ptr<uchar>(r)[c], sigmaD);k += SpaceFactor(i, j, r, c, sigmaD) * ColorFactor(gray.ptr<uchar>(i)[j], gray.ptr<uchar>(r)[c], sigmaD);}}int value = f / k;if (value < 0) value = 0;else if (value > 255) value = 255;resultGrayImg.ptr<uchar>(i)[j] = (uchar)value;}}cv::Mat resultImg;if (inputImg.channels() >= 3) {for (int i = 0; i < LabImage.rows; i++) {for (int j = 0; j < LabImage.cols; j++) {LabImage.ptr<uchar>(i, j)[0] = resultGrayImg.ptr<uchar>(i)[j];}}cv::cvtColor(LabImage, resultImg, cv::COLOR_Lab2BGR);}else {resultGrayImg.copyTo(resultImg);}return resultImg;
}cv::Mat fastBilateralFilter(cv::Mat inputImg, int filterSize, double sigmaD, double sigmaR) {int len; //must be odd numbercv::Mat gray; // must be 1-channel imagecv::Mat LabImage; // if channels == 3if (filterSize % 2 != 1 || filterSize <= 0) {std::cerr << "Filter Size must be a positive odd number!" << std::endl;return inputImg;}len = filterSize / 2;if (inputImg.channels() >= 3) {cv::cvtColor(inputImg, LabImage, cv::COLOR_BGR2Lab);gray = cv::Mat::zeros(LabImage.size(), CV_8UC1);for (int i = 0; i < LabImage.rows; i++) {for (int j = 0; j < LabImage.cols; j++) {gray.ptr<uchar>(i)[j] = LabImage.ptr<uchar>(i, j)[0];}}}else if (inputImg.channels() == 1) {inputImg.copyTo(gray);}else {std::cerr << "the count of input image's channel can not be 2!" << std::endl;return inputImg;}cv::Mat resultGrayImg = cv::Mat::zeros(gray.size(), CV_8UC1);for (int i = 0; i < gray.rows; i++) {for (int j = 0; j < gray.cols; j++) {double k = 0;double f = 0;double sum = 0;for (int r = i - len; r <= i + len; r++) {if (r < 0 || r >= gray.rows)continue;f = f + gray.ptr<uchar>(r)[j] * SpaceFactor(i, j, r, j, sigmaD) * ColorFactor(gray.ptr<uchar>(i)[j], gray.ptr<uchar>(r)[j], sigmaD);k += SpaceFactor(i, j, r, j, sigmaD) * ColorFactor(gray.ptr<uchar>(i)[j], gray.ptr<uchar>(r)[j], sigmaD);}sum = f / k;f = k = 0.0;for (int c = j - len; c <= j + len; c++) {if (c < 0 || c >= gray.cols)continue;f = f + gray.ptr<uchar>(i)[c] * SpaceFactor(i, j, i, c, sigmaD) * ColorFactor(gray.ptr<uchar>(i)[j], gray.ptr<uchar>(i)[c], sigmaD);k += SpaceFactor(i, j, i, c, sigmaD) * ColorFactor(gray.ptr<uchar>(i)[j], gray.ptr<uchar>(i)[c], sigmaD);}int value = (sum + f / k) / 2;if (value < 0) value = 0;else if (value > 255) value = 255;resultGrayImg.ptr<uchar>(i)[j] = (uchar)value;}}cv::Mat resultImg;if (inputImg.channels() >= 3) {for (int i = 0; i < LabImage.rows; i++) {for (int j = 0; j < LabImage.cols; j++) {LabImage.ptr<uchar>(i, j)[0] = resultGrayImg.ptr<uchar>(i)[j];}}cv::cvtColor(LabImage, resultImg, cv::COLOR_Lab2BGR);}else {resultGrayImg.copyTo(resultImg);}return resultImg;
}

//main.cpp

#include <iostream>
#include <time.h>#include "Filters.h"using namespace std;int main() {cv::Mat img = cv::imread("Capture.jpg", cv::IMREAD_UNCHANGED);clock_t begin_time = clock();cv::Mat result = BilateralFilter(img, 15, 12.5, 50);std::cout << float(clock() - begin_time) / CLOCKS_PER_SEC << std:: endl;cv::imshow("original", result);cv::waitKey(0);cv::imwrite("original.jpg", result);begin_time = clock();result = fastBilateralFilter(img, 15, 12.5, 50);std::cout << float(clock() - begin_time) / CLOCKS_PER_SEC << std::endl;cv::imshow("fast", result);cv::waitKey(0);cv::imwrite("fast.jpg", result);begin_time = clock();cv::bilateralFilter(img, result, 15, 50, 12.5);std::cout << float(clock() - begin_time) / CLOCKS_PER_SEC << std::endl;cv::imshow("opencv", result);cv::waitKey(0);cv::imwrite("opencv.jpg", result);system("pause");return 0;
}

运行结果:

46.889s  5.694s  0.202s

二维算子降成两个一维算子之后,速度加快了一些,但是还是不如opencv的快,效果也比它差一些(No more reinventing the wheel...)

从左至右:“小雀斑”帅气原图、BilateralFilter处理结果、fastBilateralFilter处理结果、opencv接口处理结果

   

转载于:https://www.cnblogs.com/cheermyang/p/6637186.html

【C++】双边滤波器(bilateral filter)相关推荐

  1. OpenCV图像处理学习九,双边滤波器 (Bilateral Filter)和中位数滤波器 (Median Filter)

    均值模糊无法克服边缘像素信息丢失缺陷,原因是均值滤波是基于平均权重,赋予图像内的像素与图像边缘像素一样的比值权重,图像处理是会使得边缘部分图像部分像素信息丢失: 高斯模糊部分克服了该缺陷,但是无法完全 ...

  2. 三种经典图像滤波方法介绍——双边滤波(Bilateral filter)、导向滤波(Guided Fliter)、滚动导向滤波(RollingGuidedFilter)

    文章目录 一.前言 二.双边滤波(Bilateral filter) 2.1 双边滤波的理论介绍及公式推导 2.2 双边滤波的matlab程序实现 三.导向滤波(Guided Fliter) 3.1 ...

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

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

  4. 双边滤波(Bilateral filter)原理介绍及matlab程序实现

    双边滤波 1.原理介绍 双边滤波由C. Tomasi在1998年提出,是一种经典的非线性空间滤波方法.在滤波器稀疏的制定上,双边滤波同时考虑到了输出像素与邻域内其它像素的欧氏距离和取值的差异,即:同时 ...

  5. (十五)双边滤波Bilateral Filter

    文章目录 mathjax: true 1.高斯滤波 1.1 理论 1.2 示例 2.双边滤波(Bilateral Filter) 2.1 理论基础 2.2 OpenCV bilateralFilter ...

  6. matlab双边收敛,双边滤波(bilateral filter)快速算法 matlab实现代码

    本算法参考自论文"Paris S, Durand F. A fast approximation of the bilateral filter using a signal process ...

  7. 双边滤波(bilateral filter)彩色图 matlab实现代码

    https://blog.csdn.net/weixin_38285131/article/details/77719199 https://blog.csdn.net/majinlei121/art ...

  8. c语言双边滤波算法,浅析bilateral filter双边滤波器的理解

    图像去噪的方法很多,如中值滤波,高斯滤波,维纳滤波等等.但这些降噪方法容易模糊图片的边缘细节,对于高频细节的保护效果并不明显.相比较而言,bilateral filter双边滤波器可以很好的边缘保护, ...

  9. 能使曲线变平滑的一维滤波器_双边滤波器的原理及实现

    双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的. 双边滤波器之所以能够做到在平 ...

  10. bilateral filter双边滤波器的通俗理解

    bilateral filter双边滤波器的通俗理解 图像去噪的方法很多,如中值滤波,高斯滤波,维纳滤波等等.但这些降噪方法容易模糊图片的边缘细节,对于高频细节的保护效果并不明显.相比较而言,bila ...

最新文章

  1. DevExpress控件使用系列--ASPxUploadControl(图片上传及预览)
  2. SmartNIC/DPU — 技术方向
  3. 三点到六点是几个小时_环卫工在10吨垃圾里找了6小时,终于找到这张价值19万元的餐巾纸...
  4. 交换机二层交换和三层交换技术比较
  5. JAVA基础知识系列---进程、线程安全
  6. python百万并发压测_100W高并发(转载) - 橙子柠檬's Blog
  7. 《Linux高性能服务器编程》——2.7 IPv6头部结构
  8. AlbertTransformerEncoder
  9. 网络安全实验室 脚本关 10
  10. 你对自己未来五年的职业规划是什么
  11. Detection物体检测及分类方法总结(RFCN/SSD/RCNN/FastRCNN/FasterRCNN/SPPNet/DPM/OverFeat/YOLO)
  12. python求极限_数学——函数极限知识以及sympy库的limit
  13. item_password-获得淘口令真实url接口,淘宝app短链接商品接口,1688商品淘口令url接口
  14. 【学相伴】Nginx最新教程通俗易懂-狂神说
  15. 微信小程序开发中的这些坑你遇到过吗?
  16. 68.qq号索引结构体写入内存,并实现快速排序
  17. Mathematica中的绘图
  18. 如何注册个人邮箱?又应该如何选择邮箱呢?
  19. 身家200亿到入狱,中国股神的悲壮人生
  20. ChargerFuelGauge (Riogande platform)

热门文章

  1. java web 学习网站_我的第一个javaweb学习----模仿社区网站(三)
  2. 人工智能 AI技术学习路线图 初阶+中阶+高阶
  3. 《工业元宇宙白皮书 2022年 》(附免费pdf下载地址)
  4. C++ tbb unsafe_erase() 并发访问 解决方案
  5. 微信小程序this.setData如何修改对象、数组中的值
  6. You have an error in your SQL syntax.....for the right syntax to use near 'describe
  7. php向mysql提交数据_PHP 如何向 MySQL 发送数据
  8. Linux学习(2)常用的命令
  9. algorithm:next_permutation
  10. 创建git仓库和常用的命令