目录

  • 源码
    • 滤波器
    • 主函数
  • 效果
  • 完整源码

平台:Windows 10 20H2
Visual Studio 2015
OpenCV 4.5.3


本文所用源码修改自双边滤波(bilateral filter)以及联合双边滤波(joint bilateral filter)—— flow_specter

源码

滤波器

// 双边滤波
// @ src 待滤波的影像
// @ dst 输出的影像
void BilateralFilter(Mat& src, Mat& dst, int d, double sigmaColor, double sigmaSpace)
{dst = src.clone();int n_rows = dst.rows;int n_cols = dst.cols;int n_channels = dst.channels();int n_cols_with_channels = n_cols * n_channels;int half_kernel_size = d / 2;int index;double pixel_sum;double weight_sum = 0;double temp_bilateral_weight = 0;double color_kernel[256];// 颜色域权重确定// @ color_kernel 颜色域核,1D,长度为256for (int i = 0; i < 256; i++){color_kernel[i] = exp(-1.0 * (i * i) / (2 * sigmaColor * sigmaColor));}// 空间域权重确定// @ distance_kernel 空间域核,1D// **************************************************************************************************************double *distance_kernel;distance_kernel = new double[d * d];int k = d / 2;//二维动态数组申请空间double **distance_kernel_2D = new double*[d];for (int i = 0; i < d; i++)distance_kernel_2D[i] = new double[d];double delta_square = 2 * sigmaSpace * sigmaSpace; //分母for (int i = -k; i <= k; i++){for (int j = -k; j <= k; j++){double distance_numerator = i * i + j * j;distance_kernel_2D[i + k][j + k] = exp(-1.0 * distance_numerator / delta_square);}}// 将2D kernel 转换为 1D kernelfor (int i = 0; i < d; i++){for (int j = 0; j < d; j++){distance_kernel[d * i + j] = distance_kernel_2D[i][j];}}//释放二维动态数组空间for (int i = 0; i < d; i++)delete[] distance_kernel_2D[i];delete[] distance_kernel_2D;// **************************************************************************************************************// 边界不做处理for (int i = half_kernel_size; i < (n_rows - half_kernel_size); i++) {uchar* pt_dst = dst.ptr<uchar>(i);uchar* pt_src = src.ptr<uchar>(i);for (int j = n_channels * half_kernel_size; j < (n_cols_with_channels - n_channels * half_kernel_size); j++) {index = 0;pixel_sum = weight_sum = 0;// 内层kx,ky循环,空间域内滤波for (int kx = i - half_kernel_size; kx <= i + half_kernel_size; kx++) {uchar* pt_k_src = src.ptr<uchar>(kx);for (int ky = j - n_channels * half_kernel_size; ky <= (j + n_channels * half_kernel_size); ky += n_channels) {temp_bilateral_weight = distance_kernel[index++] * color_kernel[(int)abs(pt_src[j] - pt_k_src[ky])];weight_sum += temp_bilateral_weight;pixel_sum += (pt_k_src[ky] * temp_bilateral_weight); // 邻域某像素与中心点的双边权重乘积}}pixel_sum /= weight_sum; // 归一化pt_dst[j] = saturate_cast<uchar>(pixel_sum); //加权赋值}}delete[]distance_kernel;
}
//————————————————
//版权声明:本文为CSDN博主「flow_specter」的原创文章,遵循CC 4.0 BY - SA版权协议,转载请附上原文出处链接及本声明。
//原文链接:https ://blog.csdn.net/flow_specter/article/details/107557303

主函数

图片路径根据实际情况调整,注意反斜杠是转义字符的开头,故“\”应替换为“\”

int main(int argc, char * argv[])
{Mat src = imread("D:\\Work\\OpenCV\\Workplace\\Test_1\\face.jpg");Mat dst;BilateralFilter(src, dst, 23, 35, 10);imshow("原图", src);imshow("输出", dst);waitKey(0);return 0;
}

效果

完整源码

#include <opencv2\opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;// 双边滤波
// @ src 待滤波的影像
// @ dst 输出的影像
void BilateralFilter(Mat& src, Mat& dst, int d, double sigmaColor, double sigmaSpace)
{dst = src.clone();int n_rows = dst.rows;int n_cols = dst.cols;int n_channels = dst.channels();int n_cols_with_channels = n_cols * n_channels;int half_kernel_size = d / 2;int index;double pixel_sum;double weight_sum = 0;double temp_bilateral_weight = 0;double color_kernel[256];// 颜色域权重确定// @ color_kernel 颜色域核,1D,长度为256for (int i = 0; i < 256; i++){color_kernel[i] = exp(-1.0 * (i * i) / (2 * sigmaColor * sigmaColor));}// 空间域权重确定// @ distance_kernel 空间域核,1D// **************************************************************************************************************double *distance_kernel;distance_kernel = new double[d * d];int k = d / 2;//二维动态数组申请空间double **distance_kernel_2D = new double*[d];for (int i = 0; i < d; i++)distance_kernel_2D[i] = new double[d];double delta_square = 2 * sigmaSpace * sigmaSpace; //分母for (int i = -k; i <= k; i++){for (int j = -k; j <= k; j++){double distance_numerator = i * i + j * j;distance_kernel_2D[i + k][j + k] = exp(-1.0 * distance_numerator / delta_square);}}// 将2D kernel 转换为 1D kernelfor (int i = 0; i < d; i++){for (int j = 0; j < d; j++){distance_kernel[d * i + j] = distance_kernel_2D[i][j];}}//释放二维动态数组空间for (int i = 0; i < d; i++)delete[] distance_kernel_2D[i];delete[] distance_kernel_2D;// **************************************************************************************************************// 边界不做处理for (int i = half_kernel_size; i < (n_rows - half_kernel_size); i++) {uchar* pt_dst = dst.ptr<uchar>(i);uchar* pt_src = src.ptr<uchar>(i);for (int j = n_channels * half_kernel_size; j < (n_cols_with_channels - n_channels * half_kernel_size); j++) {index = 0;pixel_sum = weight_sum = 0;// 内层kx,ky循环,空间域内滤波for (int kx = i - half_kernel_size; kx <= i + half_kernel_size; kx++) {uchar* pt_k_src = src.ptr<uchar>(kx);for (int ky = j - n_channels * half_kernel_size; ky <= (j + n_channels * half_kernel_size); ky += n_channels) {temp_bilateral_weight = distance_kernel[index++] * color_kernel[(int)abs(pt_src[j] - pt_k_src[ky])];weight_sum += temp_bilateral_weight;pixel_sum += (pt_k_src[ky] * temp_bilateral_weight); // 邻域某像素与中心点的双边权重乘积}}pixel_sum /= weight_sum; // 归一化pt_dst[j] = saturate_cast<uchar>(pixel_sum); //加权赋值}}delete[]distance_kernel;
}
//————————————————
//版权声明:本文为CSDN博主「flow_specter」的原创文章,遵循CC 4.0 BY - SA版权协议,转载请附上原文出处链接及本声明。
//原文链接:https ://blog.csdn.net/flow_specter/article/details/107557303int main(int argc, char * argv[])
{Mat src = imread("D:\\Work\\OpenCV\\Workplace\\Test_1\\face.jpg");Mat dst;BilateralFilter(src, dst, 23, 35, 10);imshow("原图", src);imshow("输出", dst);waitKey(0);return 0;
}

【机器视觉学习笔记】双边滤波算法(C++)相关推荐

  1. 机器视觉学习笔记--图像滤波1

    基本理论 图像滤波的目的:去除图像噪声,修复图像损坏,改变图像分布. 均值滤波(Mean Filter) 求取NxN像素范围内的均值作为中心点的像素值,N为核大小 例:核为3 核越大,噪声消除效果越好 ...

  2. java 滤波算法_双边滤波算法

    1.原理 高斯滤波是以距离为权重,设计滤波模板作为滤波系数,只考虑了像素间的空间位置上的关系,因此滤波的结果会丢失边缘的信息. 高斯滤波的缺陷如下图所示:平坦区域正常滤波,图像细节没有变化,而在突变的 ...

  3. c语言双边滤波算法,快速双边滤波 附完整C代码

    很早之前写过<双边滤波算法的简易实现bilateralFilter>. 当时学习参考的代码来自cuda的样例. 相关代码可以参阅: https://github.com/johng12/c ...

  4. 机器视觉学习笔记(4)——单目摄像机标定参数说明

    机器视觉学习笔记(4)--单目摄像机标定参数说明 标签: 机器视觉 1.针孔摄像机模型 在介绍摄像机标定参数之前,需要先简单说一下针孔摄像机的原理.投影平面到小孔的距离为焦距f,物体到小孔的距离为Z, ...

  5. R语言与机器学习学习笔记(分类算法)

    转载自:http://www.itongji.cn/article/0P534092014.html 人工神经网络(ANN),简称神经网络,是一种模仿生物神经网络的结构和功能的数学模型或计算模型.神经 ...

  6. 图像处理:双边滤波算法

    今天主要是回顾一下双边滤波,我曾经在这篇--图像处理:推导五种滤波算法中推导过它,其中包含了我自己写的草稿图. 目录 双边滤波算法原理 (1)空间域核 (2)值域核 理解双边滤波 空域权重​编辑和值域 ...

  7. 《基于张量网络的机器学习入门》学习笔记8(Shor算法)

    <基于张量网络的机器学习入门>学习笔记8 Shor算法 来源 Shor算法的大致流程 因数分解 周期求取与量子傅里叶变换(QFT) Shor算法 来源 1994 1994 1994年,应用 ...

  8. 【学习笔记】【算法】【智能优化】粒子群优化(PSO)

    [学习笔记][算法][智能优化]粒子群优化(PSO) 文章目录 [学习笔记][算法][智能优化]粒子群优化(PSO) 1 算法背景 1.1 背景 1.2 基础知识 2 算法原理 2.1 基本原理 2. ...

  9. Bilateral Filters(双边滤波算法)原理及实现(一)

    双边滤波算法原理 双边滤波是一种非线性滤波器,它可以达到保持边缘.降噪平滑的效果.和其他滤波原理一样,双边滤波也是采用加权平均的方法,用周边像素亮度值的加权平均代表某个像素的强度,所用的加权平均基于高 ...

  10. 【学习笔记】网络流算法简单入门

    [学习笔记]网络流算法简单入门 [大前言] 网络流是一种神奇的问题,在不同的题中你会发现各种各样的神仙操作. 而且从理论上讲,网络流可以处理所有二分图问题. 二分图和网络流的难度都在于问题建模,一般不 ...

最新文章

  1. 连接统计学、机器学习与自动推理的新兴交叉领域——因果科学读书会再起航...
  2. python与excel表格-如何用python处理excel表格
  3. 计算机组成原理第3章-存储系统
  4. C++STL的string容器
  5. mysql创建表时遇到的问题_MySQL语言创建表时遇到了问题,请问我错在哪里了?...
  6. php算法台阶,php如何解决青蛙跳台阶的问题(代码)
  7. wireshark解析rtp协议,流媒体中的AMR/H263/H264包的方法
  8. java引入bean代码_通过java代码装配bean
  9. yum 安装的时候出现错误
  10. 在u-boot中自定义的命令
  11. ASP.NET MVC 重点教程一周年版 第三回 Controller与View
  12. 酷q点歌机器人软件_酷q_酷q机器人官方下载[最新版]-下载之家
  13. 深信服虚拟服务器设置ip,深信服服务器虚拟化asv操作步骤.pdf
  14. @SpringBootApplication注解的意思
  15. 【JZOJ5336】【NOIP2017提高A组模拟8.24】提米树
  16. 什么是视距传播,如何验证微波链路视线
  17. linux 服务器加装硬盘流程及sda sdb加载顺序
  18. seo优化教程-免费SEO优化详细教程
  19. SQL--超键、候选键、主键、外键的认识和区分
  20. Android性能优化典范(五)

热门文章

  1. 生产库自动派送报表派送失败之重新派送
  2. [转]T4模版引擎之基础入门
  3. lvs和HA的高可用性
  4. 11月中30个精心设计的网站案例精选
  5. oracle10g随服务器启动而自动启动(linux as 5)
  6. 处理输入屏幕的互相锁定
  7. 使用机器学习预测天气_如何使用机器学习预测着陆
  8. opencv:卷积涉及的基础概念,Sobel边缘检测代码实现及Same(相同)填充与Vaild(有效)填充
  9. leetcode46. 全排列(回溯)
  10. express 路由中间件_Express通过示例进行解释-安装,路由,中间件等