平滑

在数字图像上进行平滑操作,就是需要用模板(高斯模板,均值模板)在图像上做卷积,得到新值,这就是模糊的原理。卷积核中的每个元素叫做卷积系数,卷积核中卷积系数的大小、方向及排列次序决定图像卷积后处理的最终效果。改变卷积核中的加权系数,会影响到综合的数值与符号,从而影响到所求像素的新值。常用卷积核有3×3、5×5、7×7等,所有卷积核的行、列都是奇数。均值滤波、高斯滤波以及各种自定义的滤波都可以通过模板操作来实现。
其中常见的模板有:

  • 4邻域均值模板:
    1 / 4 [ 0 1 0 1 1 1 0 1 0 ] 1/4\begin{bmatrix} 0 & 1 &0 \\ 1 & 1 & 1\\ 0 & 1 & 0 \end{bmatrix} 1/4⎣⎡​010​111​010​⎦⎤​

  • 8邻域均值
    1 / 8 [ 1 1 1 1 0 1 1 1 1 ] 1/8\begin{bmatrix} 1 & 1 &1 \\ 1 & 0 & 1\\ 1 & 1 & 1 \end{bmatrix} 1/8⎣⎡​111​101​111​⎦⎤​

  • 均值模板
    1 / 9 [ 1 1 1 1 1 1 1 1 1 ] 1/9\begin{bmatrix} 1 & 1 &1 \\ 1 & 1 & 1\\ 1 & 1 & 1 \end{bmatrix} 1/9⎣⎡​111​111​111​⎦⎤​

  • 高斯模板
    1 / 16 [ 1 2 1 2 4 2 1 2 1 ] 1/16\begin{bmatrix} 1 & 2 &1 \\ 2 & 4 & 2\\ 1 & 2 & 1 \end{bmatrix} 1/16⎣⎡​121​242​121​⎦⎤​

代码实现

实现一个均值模糊:

Mat TemplateBlur(Mat src) {int row = src.rows;int col = src.cols;Mat dst(row, col, CV_8UC3);int border = 1;for (int i = border; i < row - border; i++) {for (int j = border; j < col - border; j++) {for (int k = 0; k < 3; k++) {int sum = src.at<Vec3b>(i, j)[k] + src.at<Vec3b>(i + 1, j)[k] + src.at<Vec3b>(i - 1, j)[k] +src.at<Vec3b>(i, j - 1)[k] + src.at<Vec3b>(i + 1, j - 1)[k] + src.at<Vec3b>(i - 1, j - 1)[k] +src.at<Vec3b>(i, j + 1)[k] + src.at<Vec3b>(i + 1, j + 1)[k] + src.at<Vec3b>(i - 1, j + 1)[k];sum /= 9;dst.at<Vec3b>(i, j)[k] = sum;}}}return dst;
}

中值模糊

中值滤波是一种非线性滤波。中值滤波在一定条件下可以克服线性滤波器如最小均方滤波、均值滤波(BoxFilter)等带来的图像细节的模糊,而且对滤除椒盐灵三点的噪声最为有效。但对于一些细节多,特别是点、线、尖顶细节多的图像不宜采用中值滤波。

中值滤波一般采用一个含有奇数个点的滑动窗口,将窗口中各点灰度值的中值来替代指定点的灰度值。对于奇数个元素,中值是值排序后中间的数值;对于偶数则是排数后中间两个元素的平均值。常用的中值滤波窗口有线状、方形、原型、十字型等,本文算法只实现方形的中值滤波,其他形状的中值滤波实现方式相似。

代码

Mat MedianFilter(Mat src, int ksize) {int row = src.rows;int col = src.cols;int border = (ksize - 1) / 2;int mid = (ksize*ksize - 1) / 2;Mat dst(row, col, CV_8UC3);for (int i = border; i < row - border; i++) {for (int j = border; j < col - border; j++) {for (int k = 0; k < 3; k++) {vector <int> v;for (int x = -border; x <= border; x++) {for (int y = -border; y <= border; y++) {v.push_back(src.at<Vec3b>(i + x, j + y)[k]);}}sort(v.begin(), v.end());dst.at<Vec3b>(i, j)[k] = v[mid];}}}return dst;
}

高斯模糊

一维高斯公式为: G ( x ) = 1 2 π δ e − x 2 2 δ 2 G(x)=\frac{1}{\sqrt{2\pi}\delta}e^{\frac{-x^2}{2\delta^2}} G(x)=2π ​δ1​e2δ2−x2​
二维高斯公式为: G ( x , y ) = 1 2 π δ 2 e − x 2 + y 2 2 δ 2 G(x,y)=\frac{1}{2\pi\delta^2}e^{-\frac{x^2+y^2}{2\delta^2}} G(x,y)=2πδ21​e−2δ2x2+y2​
理论上,高斯分布在所有定义域上都有非负值,这就需要一个无限大的卷积核。实际上,仅需要取均值周围3倍标准差内的值,以外部份直接去掉即可。 如下图为一个标准差为1.0的整数值高斯核:
1 / 273 [ 1 4 7 4 1 4 16 26 16 4 7 26 41 26 7 4 16 26 16 4 1 4 7 4 1 ] 1/273\begin{bmatrix} 1 &amp; 4 &amp;7 &amp;4 &amp;1 \\ 4 &amp; 16 &amp; 26&amp;16&amp;4\\ 7 &amp; 26 &amp; 41&amp;26&amp;7\\ 4&amp;16&amp;26&amp;16&amp;4\\ 1&amp;4&amp;7&amp;4&amp;1 \end{bmatrix} 1/273⎣⎢⎢⎢⎢⎡​14741​41626164​72641267​41626164​14741​⎦⎥⎥⎥⎥⎤​

在有些场合,可以用下面的模板来对高斯核进行近似:
1 / 16 [ 1 2 1 2 4 2 1 2 1 ] 1/16\begin{bmatrix} 1 &amp; 2 &amp;1 \\ 2 &amp; 4 &amp; 2\\ 1 &amp; 2 &amp; 1 \end{bmatrix} 1/16⎣⎡​121​242​121​⎦⎤​

代码

// 创建高斯核
// kSize:卷积核的大小3、5、7等(3×3、5×5、7×7)
// sigma:方差
const float EPS = 1e-7;
void CreatGaussKernel(float **pdKernel, int kSize, float sigma) {int sum = 0;float dCenter = (kSize - 1) / 2;//生成高斯数据for (int i = 0; i < kSize; i++) {for (int j = 0; j < kSize; j++) {//用和来近似平方和的开方float dis = fabsf(i - dCenter) + fabsf(j - dCenter);float val = exp(-dis * dis / (2 * sigma * sigma + EPS));pdKernel[i][j] = val;sum += val;}}//归一化for (int i = 0; i < kSize; i++) {for (int j = 0; j < kSize; j++) {pdKernel[i][j] /= (sum + EPS);}}
}Mat GaussBlur(Mat src, int kSize, float sigma) {int row = src.rows;int col = src.cols;//分配高斯核空间float **pKernel = new float*[kSize];for (int i = 0; i < kSize; i++) {pKernel[i] = new float[kSize];}Mat dst(row, col, CV_8UC3);CreatGaussKernel(pKernel, kSize, sigma);int border = (kSize - 1) / 2;float sum = 0;for (int i = border; i < row - border; i++) {for (int j = border; j < col - border; j++) {for (int k = 0; k < 3; k++) {sum = 0;for (int x = -border; x <= border; x++) {for (int y = -border; y <= border; y++) {sum += src.at<Vec3b>(i + x, j + y)[k] * pKernel[border + x][border + y];}}if (sum > 255) sum = 255;else if (sum < 0) sum = 0;dst.at<Vec3b>(i, j)[k] = sum;}}}return dst;
}

运动模糊

原文:https://blog.csdn.net/kezunhai/article/details/41757681
造成图像模糊的原因有很多种,如果是因为在摄像时相机和被摄景物有相对运动而造成的图像模糊则称为运动模糊。所得到的图像中的景物往往会模糊不清,我们称之为运动模糊图像。运动模糊(Motion Blur)是一种抓取物体运动状态效果的滤镜,主要应用物体运动时曝光的摄影手法,模拟出在摄像中拍摄运动物体的间接曝光功能,从而使图像产生出一种动态效果。它通常用来制造物体掠过或移动的效果。
运动模糊滤镜沿特定的方向,并以特定的强度进行模糊处理。首先,在数学上,Y轴向上为正,而在图像处理中,Y轴向下为正,所以在获取用户指定方向角度后,应先将其沿正方形旋转180°;接着,解决图像在指定方向上的位移问题。运动莫不是简单地将图像在指定的图像上移来移去,而是在距离限定的范围内,按某种方式复制并叠加像素。简单地可以看成,将一幅图像的多张副本叠放在指定的方向上,然后取其平均值;最后,要解决的问题就是图像的透明度,处理Alpha分类,这样最终产生的模糊效果才更理想。

代码实现


//添加运动模糊效果
//angle:运动的方向,distance:运动的距离
//这里只是粗略的计算,以dx的长度为准,也可以以dy或者dx+dy等长度微赚
Mat MotionBlur(const Mat &src, int angle = 30, int distance = 100) {if (distance < 1) distance = 1;else if (distance > 200) distance = 200;double radian = ((double)angle + 180.0) / 180.0 * PI;int dx = (int)((double)distance * cos(radian) + 0.5);int dy = (int)((double)distance * sin(radian) + 0.5);int sign;if (dx < 0) sign = -1;if (dx > 0) sign = 1;int height = src.rows;int width = src.cols;int chns = src.channels();Mat dst;dst.create(height, width, src.type());for (int i = 0; i < height; i++) {unsigned  char* dstData = (unsigned char*)dst.data + dst.step * i;for (int j = 0; j < width; j++) {for (int k = 0; k < chns; k++) {int sum = 0, count = 0;for (int p = 0; p < abs(dx); p++) {int i0 = i + p*sign;int j0 = j + p*sign;if (i0 >= 0 && i0 < height && j0 >= 0 && j0 < width) {count++;sum += src.at<Vec3b>(i0, j0)[k];}}if (count == 0) {dstData[j*chns + k] = src.at<Vec3b>(i, j)[k];}else {dstData[j*chns + k] = int(sum / (double)count + 0.5);if (dstData[j*chns + k] < 0) dstData[j*chns + k] = 0;else if (dstData[j*chns + k] > 255) dstData[j*chns + k] = 255;}}}}return dst;
}

径向模糊之缩放和旋转

原理:https://blog.csdn.net/xoyojank/article/details/5146297

代码实现

//径向模糊:缩放
//num: 均值力度
Mat RadialBlurZoom(Mat src, int num=10) {int row = src.rows;int col = src.cols;Point center(row / 2, col / 2);Mat dst(row, col, CV_8UC3);for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {int R = norm(Point(i, j) - center);float angle = atan2(float(i - center.x), float(j - center.y));int sum1 = 0, sum2 = 0, sum3 = 0;for (int k = 0; k < num; k++) {int tmpR = (R - k) > 0 ? (R - k) : 0;int newX = tmpR * sin(angle) + center.x;int newY = tmpR * cos(angle) + center.y;if (newX < 0) newX = 0;if (newX > row - 1) newX = row - 1;if (newY < 0) newY = 0;if (newY > col - 1) newY = col - 1;sum1 += src.at<Vec3b>(newX, newY)[0];sum2 += src.at<Vec3b>(newX, newY)[1];sum3 += src.at<Vec3b>(newX, newY)[2];}dst.at<Vec3b>(i, j)[0] = (uchar)(sum1 / num);dst.at<Vec3b>(i, j)[1] = (uchar)(sum2 / num);dst.at<Vec3b>(i, j)[2] = (uchar)(sum3 / num);}}return dst;
}//径向模糊:旋转
Mat RadialBlurRotate(Mat src, int num = 10) {int row = src.rows;int col = src.cols;Point center(row / 2, col / 2);Mat dst(row, col, CV_8UC3);for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {int R = norm(Point(i, j) - center);float angle = atan2(float(i - center.x), float(j - center.y));int sum1 = 0, sum2 = 0, sum3 = 0;for (int k = 0; k < num; k++) {angle += 0.01;int newX = R * sin(angle) + center.x;int newY = R * cos(angle) + center.y;if (newX < 0) newX = 0;if (newX > row - 1) newX = row - 1;if (newY < 0) newY = 0;if (newY > col - 1) newY = col - 1;sum1 += src.at<Vec3b>(newX, newY)[0];sum2 += src.at<Vec3b>(newX, newY)[1];sum3 += src.at<Vec3b>(newX, newY)[2];}dst.at<Vec3b>(i, j)[0] = (uchar)(sum1 / num);dst.at<Vec3b>(i, j)[1] = (uchar)(sum2 / num);dst.at<Vec3b>(i, j)[2] = (uchar)(sum3 / num);}}return dst;
}

图像处理中的模糊算法相关推荐

  1. T-S型模糊算法简述及FPGA的实现

    目录 0 引言 1 将清晰的数据模糊化 2.模糊推理 2.1模糊命题 2.2T-S模糊推理 3.将模糊的数据清晰化 4.使用模糊算法逼近一阶线性定常系统在MATLAB中实现 5.在FPGA中实现模糊算 ...

  2. 数字图像处理——中值滤波及其改进算法

    一.算法介绍 中值滤波器是非线性滤波器的一个例子,它在保留图像特征方面非常有效. 但是,滤波器的窗口大小直接影响中值滤波器的性能. 较小的窗口保留了特征,但会导致噪声抑制的减少. 在较大窗口的情况下, ...

  3. 【算法随记三】小半径中值模糊的急速实现(16MB图7.5ms实现) + Photoshop中蒙尘和划痕算法解读。...

    在本人的博客里,分享了有关中值模糊的O(1)算法,详见:任意半径中值滤波(扩展至百分比滤波器)O(1)时间复杂度算法的原理.实现及效果 ,这里的算法的执行时间和参数是无关的.整体来说,虽然速度也很快, ...

  4. 小半径中值模糊的急速实现(16MB图7.5ms实现) + Photoshop中蒙尘和划痕算法解读

    本篇博文来自博主Imageshop,打赏或想要查阅更多内容可以移步至Imageshop. 转载自:https://www.cnblogs.com/Imageshop/p/11087804.html  ...

  5. OpenCV图像处理专栏九 | 基于直方图的快速中值滤波算法

    转载自:https://zhuanlan.zhihu.com/p/98092747  侵删 前言 这是OpenCV图像处理专栏的第9篇文章,主要介绍一个基于直方图的快速中值滤波算法,希望对大家有帮助. ...

  6. 把计算机视觉算法应用遥感,RANSAC算法及其在遥感图像处理中的应用

    摘要: 在计算机视觉,工程设计等领域都需要根据相关数据集确定模型参数,但是所得到的数据中往往存在大量不符合模型的异常数据(又被称为野点),这些野点对模型参数稳健性有很大的干扰.经典的参数估计算法如最小 ...

  7. 图像处理中消除相机透镜畸变和视角变换

    from:图像处理中消除相机透镜畸变和视角变换 一般的针孔相机模型如下: 三维坐标点经过透视投影变换,转换到一个图像平面坐标点. 而相机透镜还存在一定的畸变,包括横向畸变和切向畸变. 因此,针孔相机模 ...

  8. 图像处理中常用数学知识

    2.3.3 赋范空间 每个实数或复数,都有相对应的绝对值或者模,每一个n维矢量,也都可以定义其长度.如果把"长度"的概念推广到一般抽象空间中的元素上,就可以得到范数这个概念. 本节 ...

  9. matlab中基于十字形窗口的滤波算法,#215;字形滤波窗口在Matlab自适应中值滤波算法中的应用 - 21ic中国电子网...

    由于种种原因,图像在生成.传输.变换等过程中往往会受到各种噪声的污染,从而导致图像质量退化.噪声信号的滤波是图像处理的基本任务之一,主要有线性滤波和非线性滤波两种方法.线性滤波方法一般具有低通特性,而 ...

最新文章

  1. Eclipse基金会发布Eclipse Photon IDE
  2. 安装虚拟机及Linux常用操作命令
  3. 深度学习和几何(演讲提要)
  4. 北电ERS1600,8300,8600交换机的基本技术-第六章 二层冗余技术(MLT,SMLT,IST)
  5. RabbitMQ脑裂
  6. unix网络编程 的环境配置
  7. Linux下的常用软件列表
  8. jggrid 设置了自适应宽度仍然有滚动条的问题
  9. 基于51单片机的数码管显示方案
  10. 计算机检索逻辑关系,第二讲 计算机检索基础知识.ppt
  11. OpenWrt配置阿里云动态域名服务DDNS
  12. 计算机设备管理cmd命令,打开设备管理器的命令,教你一分钟学会最简单
  13. java中的方法基础
  14. Python类传参报错-TypeError:takes 2 positional arguments but 3 were given
  15. 瑞幸咖啡新获2.5亿美元融资背后
  16. 2017安防民用市场现状及特点浅析
  17. 程序员的浪漫--词云kumo
  18. Linux动物乐园 Ubuntu版本代号赏析
  19. <<人性的弱点>>读后感
  20. Flayway mysql自动生成版本_Flyway详解及Springboot集成Flyway的详细教程

热门文章

  1. 遇到滴滴司机以返程空驶为由额外加价,该如何有效维权?
  2. mysql客户端能运行sql文件_通过mysql客户端执行sql文件的方法
  3. mysql使用INSERT INTO ON DUPLICATE KEY UPDATE导致dead lock分析和解决
  4. Qt5详细入门知识介绍
  5. 选择“食品装箱机”应该考虑的几个方面
  6. 网络威胁情报:数据的力量
  7. python爬虫多线程是什么意思_python爬虫14 | 就这么说吧,如果你不懂多线程和线程池,那就去河边摸鱼!...
  8. 几何公差之基准的定义和3-2-1原则
  9. Flip Gamedfs
  10. JAVA 以逗号隔开的字符串怎么分割出来?