写作参考

(1)OpenCV

(2)OpenCV中文论坛

(3)Richard Szeliski写的Computer Vision: Algorithms and Applications

我对Opencv平滑的理解

(1)就一幅数字图像来说,大多区域内都是较为平坦的,如果领域内有一两个点像素突然变化,一般认为是噪点。如果一些连续相近的点变化,认为是边缘

(2)而滤波旨在消除噪声对于图像的影响,例如取中值或者均值不就能较好的消除椒盐噪声的影响吗?但是问题又来了,这样边缘的变化不就也被模糊了吗?所以就用到双边滤波(Bilateral Filter)。

一,中值滤波

即:用中值像素代替核内所有像素。

ksize为正方形核大小,必须为奇数。如果为偶数,哪来的中值?

二,均值滤波(归一化滤波)

即:用核内所有像素的均值替换核内所有像素值。

归一化滤波的加权公式,如下图所示(均值滤波公式):

三,高斯滤波

高斯内核函数:

1-D分布(1-D Gaussian distribution with mean 0 and =1):

2-D分布(2-D Gaussian distribution with mean (0,0) and =1):

例如3*3高斯内核模板:

应用:

(1)高斯滤波后图像被平滑的程度取决于标准差。它的输出是领域像素的加权平均,同时离中心越近的像素权重越高。因此,相对于均值滤波(mean filter)它的平滑效果更柔和,而且边缘保留的也更好。

(2)高斯滤波被用作为平滑滤波器的本质原因是因为它是一个低通滤波器,见下图。而且,大部分基于卷积平滑滤波器都是低通滤波器

Matlab函数:

h = fspecial('gaussian', hsize, sigma) returns a rotationally symmetric Gaussian lowpass filter of size hsize with standard deviation sigma (positive). hsize can be a vector specifying the number of rows and columns in h, or it can be a scalar, in which case h is a square matrix.
The default value for hsize is [3 3]; the default value for sigma is 0.5.

四,双边滤波

双边滤波就会很好的保留边缘信息,具体附上一个链接:

http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html


C++代码实现:

static void exchange(int& a, int& b)
{   int t = 0;t = a;a = b;b = t;
}static void bubble_sort(int* K, int lenth)
{for (int i = 0; i < lenth; i++)for (int j = i + 1; j < lenth; j++){if (K[i]>K[j])exchange(K[i], K[j]);}
}
///产生二维的高斯内核
static cv::Mat generate_gassian_kernel(double u, double sigma, cv::Size size)
{int width = size.width;int height = size.height;cv::Mat gassian_kernel(cv::Size(width, height), CV_64FC1);double sum = 0;double sum_sum = 0;for (int i = 0; i < width; i++)for (int j = 0; j < height; j++){sum = 1.0 / 2.0 / CV_PI / sigma / sigma * exp(-1.0 * ((i - width / 2)*(i - width / 2) + (j - width / 2)*(j - width / 2)) / 2.0 / sigma / sigma);sum_sum += sum;gassian_kernel.ptr<double>(i)[j] = sum;}for (int i = 0; i < width; i++)for (int j = 0; j < height; j++){gassian_kernel.ptr<double>(i)[j] /= sum_sum;}return gassian_kernel;
}
///均值滤波
void lmt_main_blur(cv::Mat& img_in, cv::Mat& img_out, int kernel_size)
{img_out = img_in.clone();cv::Mat mat1;cv::copyMakeBorder(img_in, mat1, kernel_size, kernel_size, kernel_size, kernel_size, cv::BORDER_REPLICATE);int cols = mat1.cols;int rows = mat1.rows;int channels = img_out.channels();const uchar* const pt = mat1.ptr<uchar>(0);uchar* pt_out = img_out.ptr<uchar>(0);for (int i = kernel_size; i < rows - kernel_size; i++){for (int j = kernel_size; j < cols - kernel_size; j++){if (channels == 1){long long int sum_pixel = 0;for (int m = -1 * kernel_size; m < kernel_size; m++)for (int n = -1 * kernel_size; n < kernel_size; n++){sum_pixel += pt[(i + m)*cols + (j + n)];}img_out.ptr<uchar>(i - kernel_size)[j - kernel_size] = (double)sum_pixel / (kernel_size*kernel_size * 4);}else if (channels == 3){long long int sum_pixel = 0;long long int sum_pixel1 = 0;long long int sum_pixel2 = 0;for (int m = -1 * kernel_size; m < kernel_size; m++)for (int n = -1 * kernel_size; n < kernel_size; n++){sum_pixel += pt[((i + m)*cols + (j + n))*channels + 0];sum_pixel1 += pt[((i + m)*cols + (j + n))*channels + 1];sum_pixel2 += pt[((i + m)*cols + (j + n))*channels + 2];}img_out.ptr<uchar>(i - kernel_size)[(j - kernel_size)*channels + 0] = (double)sum_pixel / (double)(kernel_size*kernel_size * 4);img_out.ptr<uchar>(i - kernel_size)[(j - kernel_size)*channels + 1] = (double)sum_pixel1 / (double)(kernel_size*kernel_size * 4);img_out.ptr<uchar>(i - kernel_size)[(j - kernel_size)*channels + 2] = (double)sum_pixel2 / (double)(kernel_size*kernel_size * 4);}}}}
///中值滤波
void lmt_median_blur(cv::Mat& img_in, cv::Mat& img_out, int kernel_size)
{img_out = img_in.clone();cv::Mat mat1;cv::copyMakeBorder(img_in, mat1, kernel_size, kernel_size, kernel_size, kernel_size, cv::BORDER_REPLICATE);int cols = mat1.cols;int rows = mat1.rows;int channels = img_out.channels();cv::Mat mat[3];cv::Mat mat_out[3];cv::split(mat1, mat);cv::split(img_out, mat_out);for (int k = 0; k < 3; k++){const uchar* const pt = mat[k].ptr<uchar>(0);uchar* pt_out = mat_out[k].ptr<uchar>(0);for (int i = kernel_size; i < rows - kernel_size; i++){for (int j = kernel_size; j < cols - kernel_size; j++){long long int sum_pixel = 0;int* K = new int[kernel_size*kernel_size * 4];int ker_num = 0;for (int m = -1 * kernel_size; m < kernel_size; m++)for (int n = -1 * kernel_size; n < kernel_size; n++){K[ker_num] = pt[(i + m)*cols + (j + n)];ker_num++;}bubble_sort(K, ker_num);mat_out[k].ptr<uchar>(i - kernel_size)[j - kernel_size] = K[ker_num / 2];}}}cv::merge(mat_out, 3, img_out);
}
///高斯滤波
void lmt_gaussian_blur(cv::Mat& img_src, cv::Mat& img_dst, cv::Size kernel_size)
{img_dst = cv::Mat(cv::Size(img_src.cols, img_src.rows), img_src.type());int cols = img_src.cols;int rows = img_src.rows;int channels = img_src.channels();cv::Mat gassian_kernel = generate_gassian_kernel(0, 1, kernel_size);int width = kernel_size.width / 2;int height = kernel_size.height / 2;for (int i = height; i < rows - height; i++){for (int j = width; j < cols - width; j++){for (int k = 0; k < channels; k++){double sum = 0.0;for (int m = -height; m <= height; m++){for (int n = -width; n <= width; n++){sum += (double)(img_src.ptr<uchar>(i + m)[(j + n)*channels + k]) * gassian_kernel.ptr<double>(height + m)[width + n];}}if (sum > 255.0)sum = 255;if (sum < 0.0)sum = 0;img_dst.ptr<uchar>(i)[j*channels + k] = (uchar)sum;}}}}
///双边滤波
void lmt_bilateral_filter(cv::Mat& img_in, cv::Mat& img_out, const int r, double sigma_d, double sigma_r)
{int i, j, m, n, k;int nx = img_in.cols, ny = img_in.rows, m_nChannels = img_in.channels();const int w_filter = 2 * r + 1; // 滤波器边长  double gaussian_d_coeff = -0.5 / (sigma_d * sigma_d);double gaussian_r_coeff = -0.5 / (sigma_r * sigma_r);double  **d_metrix = new double *[w_filter];for (int i = 0; i < w_filter; ++i)d_metrix[i] = new double[w_filter];double r_metrix[256];  // similarity weight  img_out = cv::Mat(img_in.size(),img_in.type());uchar* m_imgData = img_in.ptr<uchar>(0);uchar* m_img_outData = img_out.ptr<uchar>(0);// copy the original image  double* img_tmp = new double[m_nChannels * nx * ny];for (i = 0; i < ny; i++)for (j = 0; j < nx; j++)for (k = 0; k < m_nChannels; k++){img_tmp[i * m_nChannels * nx + m_nChannels * j + k] = m_imgData[i * m_nChannels * nx + m_nChannels * j + k];}// compute spatial weight  for (i = -r; i <= r; i++)for (j = -r; j <= r; j++){int x = j + r;int y = i + r;d_metrix[y][x] = exp((i * i + j * j) * gaussian_d_coeff);}// compute similarity weight  for (i = 0; i < 256; i++){r_metrix[i] = exp(i * i * gaussian_r_coeff);}// bilateral filter  for (i = 0; i < ny; i++)for (j = 0; j < nx; j++){for (k = 0; k < m_nChannels; k++){double weight_sum, pixcel_sum;weight_sum = pixcel_sum = 0.0;for (m = -r; m <= r; m++)for (n = -r; n <= r; n++){if (m*m + n*n > r*r) continue;int x_tmp = j + n;int y_tmp = i + m;x_tmp = x_tmp < 0 ? 0 : x_tmp;x_tmp = x_tmp > nx - 1 ? nx - 1 : x_tmp;   // 边界处理,replicate  y_tmp = y_tmp < 0 ? 0 : y_tmp;y_tmp = y_tmp > ny - 1 ? ny - 1 : y_tmp;int pixcel_dif = (int)abs(img_tmp[y_tmp * m_nChannels * nx + m_nChannels * x_tmp + k] - img_tmp[i * m_nChannels * nx + m_nChannels * j + k]);double weight_tmp = d_metrix[m + r][n + r] * r_metrix[pixcel_dif];  // 复合权重  pixcel_sum += img_tmp[y_tmp * m_nChannels * nx + m_nChannels * x_tmp + k] * weight_tmp;weight_sum += weight_tmp;}pixcel_sum = pixcel_sum / weight_sum;m_img_outData[i * m_nChannels * nx + m_nChannels * j + k] = (uchar)pixcel_sum;} // 一个通道  } // END ALL LOOP  for (i = 0; i < w_filter; i++)delete[] d_metrix[i];delete[] d_metrix;
}

Opencv图像处理之平滑(Smoothing)模糊(Blurring)操作相关推荐

  1. OpenCV图像处理_2:平滑smoothing模糊blurring操作

    如之前所述,我个人在这个栏目下的所有文章大都是拷贝,拷贝和粘贴,有需要请阅读原文: OpenCV,OpenCV中文论坛,和Richard Szeliski写的Computer Vision: Algo ...

  2. Practical Python and OpenCV 3rd Edition读书笔记_Chapter8_Smoothing and Blurring平滑与模糊_思维导图

    <Practical Python and OpenCV 3rd Edition>真的是一本非常棒的入门书籍. 它也很薄,只有166页,虽然是纯英文的,如果静下心来认真看一两天就可以读完. ...

  3. OpenCV-python学习笔记(四)——smoothing and blurring平滑和模糊

    文章目录 smoothing and blurring平滑和模糊 1 averaging均值滤波 2 gaussian高斯滤波 3 median中值滤波 4 bilateral双边滤波 smoothi ...

  4. 使用Python,OpenCV进行平滑和模糊

    使用Python,OpenCV进行平滑和模糊 1. 效果图 2. 原理 2.1 依赖库及安装 2.2 简单平均模糊 2.3 高斯模糊 2.4 中值模糊 2.5 双边滤波 3. 源代码 参考 这篇博客将 ...

  5. OpenCV图像处理---模糊原理

    模糊原理 Smooth/Blur(平滑和模糊) 是图像处理中最简单和常用的操作之一 使用该操作的原因之一就是为了给图像预处理时候降低噪声 , 把噪声与周围的数值平均一下就可以平滑噪声. 使用Smoot ...

  6. OpenCV图像处理-模糊

    OpenCV图像处理-模糊 前言 概念 均值滤波(归一化盒子滤波) 高斯滤波 中值滤波 双边滤波 示例 前言 本文使用的环境为:Qt5.11 + OpenCV3.4.6 环境安装参考文档:https: ...

  7. OpenCv平滑与模糊

    OpenCv平滑与模糊 1.介绍 平滑与模糊 失去焦点,致使看不 图像细节,即像素点与周围的像素点混合了,在边缘检测方面很有用处 常用的平滑方法有均值.高斯.中值.双边. 2.代码部分 import ...

  8. OpenCV图像处理(2)——形态学操作

    形态学操作 Mat element = getStructuringElement(MORPH_RECT, Size(9, 9)); morphologyEx(InputImage, OutputIm ...

  9. OpenCV java 图像基本处理-模糊 (8)

    其实我们知道支付宝在支付的时候有人脸识别操作,我们在第一次开通的时候,需要我们人脸的认证操作,需要我们露脸,在手机的摄像头面前摇摇头,眨眨眼.其实这个过程是属于特征提取的过程,我们下次支付的时候,我们 ...

最新文章

  1. 漫画 | 在中国,程序媛到底有多难?
  2. 想要早睡的最好的办法就是
  3. java 08_java 08 权限修饰符 编译运行
  4. LinbDesk --- 新的extjs4.2 desktop demo : 技术交流Q群:336584192
  5. 滤波 放电速度比充电慢 模电
  6. 因 inode 不足导致数据库登陆报错相关问题
  7. 华为估值知多少?倪光南:位居世界第一应该没问题
  8. python的django框架http请求_python django框架(一)
  9. 使用Python+tkinter编写电脑桌面放大镜程序
  10. Springboot日常游玩----logback的添加
  11. python任务栏显示网速_win10状态栏显示网速小工具_超好用
  12. 调用聚合数据新闻头条API
  13. 这么多2B项目管理软件,怎么选?
  14. java 判断日期格式_java判断字符是否是日期格式
  15. Unity 将图片转换成 sprite 格式
  16. 如何实现文字逐个出现的打字机效果
  17. PyCharm 中 import 导包呈现灰色,已解决
  18. matlab提取wind底层数据库操作
  19. word文件限制编辑如何解除
  20. Jenkins使用经验谈4(创建Job)

热门文章

  1. 管路流体仿真matlab,MathWorks 在 Simscape 中新增建模和仿真流体系统功能
  2. 【风马一族_Python】 决策树
  3. python解决猴子偷桃问题_猴子偷桃蟠桃园土地是知道的,不举报是不敢吗?
  4. 计算机视觉之--使用opencv生成简笔画小视频
  5. c语言四字节对齐,C语言字节对齐详解
  6. 网页番茄钟(Pomodoro timer)
  7. CCID 设备通讯 (Windows 平台)
  8. 字节跳动全链路压测(Rhino)的实践
  9. 分布式缓存Hazelcast详解及原理探究
  10. 方舟服务器id哪里显示,方舟怎么看自己的ID | 手游网游页游攻略大全