技术标签: 中点和中值滤波的区别 均值滤波计算 Python 图像 一样大小 图像同态滤波 python实现
python版本:python3.5.4 ; opencv-python版本:opencv-python3.4.2.17
使用的开发环境是jupyter notebook,是一个python的交互式开发环境,测试十分方便,并集成了vim操作,安装教程可参考:https://blog.csdn.net/feilong_csdn/article/details/80186276
先导文章:
opencv-python快速入门篇【数字图像处理系列一】
基本概念:亮度、对比度、饱和度、锐化、分辨率【数字图像处理系列二】
图像增强:线性、 分段线性、 对数、 反对数、 幂律(伽马)变换、直方图均衡【数字图像处理系列三】
图像数据集增强方式总结和实现【数字图像处理系列四】
在图像增强:线性、 分段线性、 对数、 反对数、 幂律(伽马)变换、直方图均衡【数字图像处理系列三】一文中我们从图像灰度变换的角度阐述了图像增强的各种方式,本文我们将一起学习图像处理中重点的方式:图像滤波,图像滤波分为空间域滤波和频率域滤波,频率域滤波我们将在下一节重点说明。图像空间滤波对于图像处理主要体现在两个方面:
(1) 平滑图像,达到降低图像噪音的效果(平滑空间滤波)
(2) 锐化图像,主要目的是突出灰度的过渡部分,即突出图像的边缘(锐化空间滤波)
先上图,感受一下空间滤波对图像处理的效果(原图、经过拉普拉斯处理后的图像):
一、空间滤波原理
图像的空间滤波器有两大部分:
(1) 一个基于图像像素的矩形邻域
(2) 对矩形邻域包围的图像像素的操作方式
理解图像的矩形邻域如下图所示
将图像的左上角看做是空间域中的原点O,向下取为x轴,向右取为y轴,图中便显示了中心点(x,y)的一个3*3邻域。每经过一个滤波产生一个新像素,新像素的坐标等于领域中心坐标(x,y),新像素的值是滤波操作的结果。而滤波器的类型也取决于邻域上操作的类型,如果邻域操作是线性操作,则滤波器称为线性空间滤波器;反之如果邻域操作是非线性操作,则滤波器称为非线性空间滤波器。
这里我们假设 f(x,y) 为原像素值,g(x,y) 为滤波后的像素值,则对于一个大小为M * N的图像使用大小为m * n的滤波器进行线性空间滤波,若令m=2a+1,n=2b+1,则邻域上线性操作可统一表达成下式:
其中x,y是可变的,以便w中的每个像素可访问f中的每个像素,我们一般称邻域内像素和滤波器模板的操作叫做卷积。下面将分别讲解平滑空间滤波器和锐化空间滤波器
二、平滑空间滤波
1、均值滤波、加权均值滤波
均值滤波又称为线性空间滤波,利用邻域平均法,即用几个像素灰度的平均值来代替每个像素的灰度。有效抑制加性噪声,但容易引起图像模糊,尤其是会模糊图像边缘。通过下图便可看到均值滤波和加权均值滤波的区别:
其中左图是均值滤波,即邻域中每个像素权重相同,取邻域平均值作为中心像素点的滤波输出值,则滤波器模板计算公式为:
而右图滤波器模板则赋予中心点最高权重,然后随着距中心点距离的增加而减小系数值,其目的是在平滑处理中试图降低模糊,加权均值滤波器的操作如下是:
下面分别通过opencv-python提供的均值滤波和自定义均值滤波器两种方式实现图像的均值滤波:
import cv2import copyimport randomimport imutilsimport numpy as npimg = cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/lena.png')gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#利用opencv提供函数实现均值滤波blur_img = cv2.blur(gray_img, (3, 3))#在灰度图上手动实现均值滤波器gray_avg_img = copy.deepcopy(gray_img)for i in range(1, gray_img.shape[0]-1): for j in range(1, gray_img.shape[1]-1): sum_pix = sum([gray_img[l, k] for l in range(i-1, i+2) for k in range(j-1, j+2)]) gray_avg_img [i, j] = int(sum_pix/9)#在RGB彩色图上手动实现均值滤波器rgb_avg_img = copy.deepcopy(img)for i in range(1, img.shape[0]-1): for j in range(1, img.shape[1]-1): sum_b_pix = sum([img[l, k, 0] for l in range(i-1, i+2) for k in range(j-1, j+2)]) sum_g_pix = sum([img[l, k, 1] for l in range(i-1, i+2) for k in range(j-1, j+2)]) sum_r_pix = sum([img[l, k, 2] for l in range(i-1, i+2) for k in range(j-1, j+2)]) rgb_avg_img [i, j] = [int(sum_b_pix/9), int(sum_g_pix/9), int(sum_r_pix/9)]cv2.imshow('origin image', imutils.resize(img, 500))cv2.imshow('gray image', imutils.resize(gray_img, 500))cv2.imshow('blur image', imutils.resize(blur_img, 500))cv2.imshow('gray average image', imutils.resize(gray_avg_img , 500))cv2.imshow('rgb average image', imutils.resize(rgb_avg_img , 500))if cv2.waitKey(0) == 27: cv2.destroyAllWindows()
效果图如下:依次是原图、灰度图、基于灰度图opencv提供函数blur均值滤波效果、基于灰度图自定义均值滤波效果、基于彩色图自定义均值滤波效果
2、中值滤波
中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性平滑滤波信号处理技术。中值滤波的特点即是首先确定一个以某个像素为中心点的邻域,然后将邻域中各像素的灰度值排序,取其中间值作为中心像素灰度的新值。中值滤波在对于椒盐噪音处理上效果很好
下面分别通过opencv-python提供的中值滤波和自定义中值滤波器两种方式实现图像的中值滤波,下面实验中我们尝试着对图像添加椒盐噪音然后进行使用中值滤波进行消除:
import cv2import copyimport randomimport imutilsimport numpy as npimg = cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/old.jpg')gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#给灰度图像自动添加椒盐噪音pepper_img = copy.deepcopy(gray_img)for i in range(gray_img.shape[0]): for j in range(gray_img.shape[1]): if random.randint(0, 20) == 0: pix = random.randint(250, 255) pepper_img[i, j] = pix#opencv提供cv2.medianBlur()函数实现中值滤波blur_img = cv2.medianBlur(pepper_img, 5)#自实现中值滤波器temp_arr = np.zeros((9))median_img = copy.deepcopy(pepper_img)for i in range(1, pepper_img.shape[0]-1): for j in range(1, pepper_img.shape[1]-1): temp_arr[0] = pepper_img[i-1, j-1] temp_arr[1] = pepper_img[i-1, j] temp_arr[2] = pepper_img[i-1, j+1] temp_arr[3] = pepper_img[i, j-1] temp_arr[4] = pepper_img[i, j] temp_arr[5] = pepper_img[i, j+1] temp_arr[6] = pepper_img[i+1, j-1] temp_arr[7] = pepper_img[i+1, j] temp_arr[8] = pepper_img[i+1, j+1] arr = np.sort(temp_arr) median_img[i, j] = arr[4]cv2.imshow('pepper image', imutils.resize(pepper_img, 600))cv2.imshow('blur image', imutils.resize(blur_img, 600))cv2.imshow('median image', imutils.resize(median_img, 600))if cv2.waitKey(0) == 27: cv2.destroyAllWindows()
效果图如下:依次是含椒盐噪音图、经过cv2.medianBlur()函数处理后的图像、经过自定义中值滤波器滤波后图像
除了中值滤波外,还有一种非线性滤波是最值滤波,最值滤波是去邻域中的最大值最为新像素值,在搜寻一幅图像最亮点时非常有用。
三、锐化空间滤波器
写在前面:上节提到的图像平滑是通过模糊图像达到图像降噪的目的,但同时存在一个问题就是会使得图像的边缘被淡化。因此本节图像锐化滤波恰相反,图像平滑是一个积分的过程,图像锐化便是通过图像微分增强边缘和其他突变,削弱灰度变换缓慢的区域。
在图像微分锐化操作中,对于一阶微分的任何定义需要保证以下三点:
(1) 在恒定灰度区域的微分值为零
(2) 在灰度台阶或斜坡处微分值非零
(3) 沿着斜坡的微分值非零
同样类比得对于二阶微分的任何保证以下三点:
(1) 在恒定区域微分值为零
(2) 在灰度台阶或斜坡的起点处微分值非零
(3) 沿着斜坡的微分值非零
1、二阶微分图像锐化—laplacian算子
首先一个二维图像函数 f(x,y) 的拉普拉斯算子定义为:
拉普拉斯变换是一个线性算子,在x方向上离散化有:
在y方向离散化有:
从上面三个式子可以得出离散拉普拉斯算子是:
上面公式便是拉普拉斯算子中一种计算方式,等价于下图中的laplacian模板1,自然laplacian模板2也可以类比写出离散算子公式:
注:由于拉普拉斯是一种微分算子,因此其强调的是图像中灰度的变换,忽视图像灰度变换缓慢的区域。因此我们通过laplacian算子得出的是图像更多的是边缘线,因此,我们可以将原图和拉普拉斯图像叠加在一起,可以复原背景特性并且保持拉普拉斯锐化处理的效果,由此得出下面公式:
对于上面展示的拉普拉斯模板1和拉普拉斯模板2,常数c取-1,也有其他模板,这里不再详述
下面给出利用opencv函数和自实现上述拉普拉斯模板的应用实例:
import cv2import copyimport randomimport imutilsimport numpy as npimg = cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/blurry_moon.jpg')#手动实现拉普拉斯滤波,使用上述laplacian模板1lap_img1 = copy.deepcopy(img)for i in range(1, img.shape[0]-1): for j in range(1, img.shape[1]-1): temp = img[i+1, j] + img[i-1, j] + img[i, j+1] + img[i, j-1] -4*img[i, j] lap_img1[i, j] = img[i, j] - temp#手动实现拉普拉斯滤波,使用上述laplacian模板2lap_img2 = copy.deepcopy(img)for i in range(1, img.shape[0]-1): for j in range(1, img.shape[1]-1): temp = img[i-1, j-1] + img[i-1, j] + img[i-1, j+1] + img[i, j-1] + \ img[i, j+1] + img[i+1, j-1] + img[i+1, j] + img[i+1, j+1] - 8*img[i, j] lap_img2[i, j] = img[i, j] - temp#使用opencv自带函数实现,使用上述laplacian模板1kernel = np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]]) #定义了卷积核,对每一个像素进行操作lapkernel_img = cv2.filter2D(img, -1, kernel)lap_img3 = img - lapkernel_imgcv2.imshow('origin image', imutils.resize(img, 400))cv2.imshow('laplacian image1', imutils.resize(lap_img1, 400))cv2.imshow('laplacian image2', imutils.resize(lap_img2, 400))cv2.imshow('laplacian image3', imutils.resize(lap_img3, 400))if cv2.waitKey(0) == 27: cv2.destroyAllWindows()
效果图如下,顺序既是上述程序的输出顺序:
2、非锐化掩蔽
非锐化掩蔽的思路便是应原图像减去平滑的图像,这样便得到强调边缘的图像,然后再和原图像相加,便达到强调图像边缘的效果,具体步骤如下:
(1) 模糊原图像
(2) 从原图像减去模糊图像(产生的差值图像称为模板)
(3) 将模板和原图像相加
则将上述思路换算成数学公式便是:
然后在原图像加上模板的一个权重部分:
当k>1时我们称该处理为高提升滤波,当k<1时则是不强调非锐化模板的作,下面提供代码实现如下:
import cv2import copyimport randomimport imutilsimport numpy as npimg = cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/blurry_moon.jpg')blur_img = cv2.blur(img, (5, 5))mask_img = img - blur_imgsharp_mask_img = img + mask_imgcv2.imshow('origin image', imutils.resize(img, 400))cv2.imshow('blur image', imutils.resize(blur_img, 400))cv2.imshow('mask image', imutils.resize(mask_img, 400))cv2.imshow('sharpen mask image', imutils.resize(sharp_mask_img, 400))if cv2.waitKey(0) == 27: cv2.destroyAllWindows()
opencv-python中提供cv2.filter2D()函数可实现自定义内核和图像进行卷积操作,cv2.filter2D()一般定义为:
cv2.filter2D(img, -1, kernel) #参数三kernel是卷积核; 参数二ddepth输入值为-1时,目标图像和原图像深度保持一致
下面我们提供实例展示对图像滤波的效果:
import cv2import copyimport randomimport imutilsimport numpy as npimg = cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/old.jpg')kernel = np.array([[0, -1, 0], [0, 5, 0], [0, -1, 0]]) #自定义了卷积核,对每一个像素进行操作new_img = cv2.filter2D(img, -1, kernel)cv2.imshow('origin image', imutils.resize(img, 400))cv2.imshow('new image', imutils.resize(new_img, 400))if cv2.waitKey(0) == 27: cv2.destroyAllWindows()
根据自定义的卷积核 kernel = np.array([[0, -1, 0], [0, 5, 0], [0, -1, 0]]) 得到的滤波效果如下:
往期精彩:
深度学习多种模型评估指标介绍 - 附sklearn实现
干货 | Attention注意力机制超全综述
Tensorflow常用函数使用说明及实例简记
机器学习中优化相关理论知识简述
自己动手实现一个神经网络多分类器
Transformer 模型的 PyTorch 实现
干货 | NLP中的十个预训练模型
干货|一文弄懂机器学习中偏差和方差
FastText原理和文本分类实战,看这一篇就够了
Transformer模型细节理解及Tensorflow实现
GPT,GPT2,Bert,Transformer-XL,XLNet论文阅读速递
机器学习算法篇:最大似然估计证明最小二乘法合理性
Word2vec, Fasttext, Glove, Elmo, Bert, Flair训练词向量教程+数据+源码
原创不易,别偷偷摸摸的在看,有用就点个好看呀
一直以来想搞清楚FWHM这个名词的由来,使用MATLAB画了一下高斯磨光核的图形,发现那还是有意思的。FWHM英文是Full Width at Half Maximum,同时在文献中也可以见到这样的词HWHM,其英文是Half Width at Half Maximum,字面上来讲这两个词都是指一个度量长度的数量,只不过前者是后者两倍而已,本质上这就完全给了高斯分布一个刻画。生成图形的代码如下_fxhmrw
题目描述从键盘输入3个实数a, b, c,通过比较交换,将最小值存储在变量a中,最大值存储在变量c中,中间值存储在变量b中,并按照从小到大的顺序输出这三个数a, b, c。末尾输出换行。输入输入以空格分隔的三个实数输出按照从小到大的顺序输出这三个实数,中间以空格分隔,最小值在前,最大值在后。小数点后保留2位小数。注意末尾的换行。样例输入 Copy3 7 1样例输出 Copy1.00 3.00 7.00#include <stdio.h>#include <stdl_从键盘输入3个实数a, b, c,通过比较交换,将最小值存储在变量a中,最大值存储在变量
package game.utils{ import flash.utils.Dictionary; /** * 类似java中HashMap类的实现 继承于IMap 具体方法说明见IMap中的注释 * */ public class HashMap { /** * 键名数组,存储键名 * */ private var _key
所谓句柄实际上是一个数据,是一个Long (整长型)的数据。 句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。 从上面的定义中的我们可以看到,句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓..._句柄计算机
达梦数据库故障恢复1、定义:数据库故障指的是数据库的实例不在运行中,实例不可用,实例无法启动。造成故障的原因多种多样,包括磁盘崩溃、电源故障、软件错误,甚至人为破坏。这些情况一旦发生,就可能会丢失数据,数据库系统将无法正常运行。那么,就需要我们去排查问题,尽快做实例的恢复,使数据库能正常对外提供服务。2、故障排查思路:1)查看实例是否运行中的方式:ps -ef | grep dmserver./DmServiceDMSERVER status./dm_services status DmSer_win11 用360优化以后达梦数据服务没了
使用webstorm一段时间了,这里分享一下常用到的快捷键,不用死记,孰能生巧!Ctrl+/或Ctrl+Shift+/注释(//或者/*…*/)Shift+F6重构-重命名Ctrl+X删除行Ctrl+D复制行Ctrl+G查...
从学校毕业了走向了工作岗位,来到了公司,公司用的前台页面框架是ExtJs,于是作为一个从JSP转向ExtJs的程序员记录下自己学习ExtJs的具体过程。刚接触ExtJs,首先看的是ExtJs的API文档,映入眼帘的是很多组件,以及各组件所对应的属性以及方法等。ExtJs的官方下载地址是:http://www.sencha.com/products/extjs/ ExtJs是一个与后
第8章,用jQuery打造个性网站网站结构文件结构images文件夹用于存放将要用到的图片styles文件夹用于存放CSS样式表,个人更倾向于使用CSS文件夹scripts文件夹用于存放jQuery脚本,个人更倾向于使用JS文件夹存放所有的js及jQuery脚本编写CSS样式推荐首先编写全局样式,接着编写可大范围内重用的样式,最后编写细节样式,这样根据CSS最...
软件整理网站 小众软件 http://love.appinn.com/快速启动launchy http://www.launchy.net/ 文本编辑器notepad++ https://notepad-plus-plus.org/ cmder好用的命令行 http://cmder.net/ Everything https://www.voidtools.com/ Not...
一、什么是全角和半角?1. 全角:是一种电脑字符,是指一个全角字符占用两个标准字符(或两个半角字符)的位置。全角占两个字节。汉字字符和规定了全角的英文字符及国标GB2312-80中的图形符号和特殊字符都是全角字符。在全角中,字母和数字等与汉字一样占据着等宽的位置。2. 半角:是指一个字符占用一个标准的字符位置。半角占一个字节。半角就是 ASCII 方式的字符,在没有汉字输入法起作用
ubuntu14.04修改用户名1、首先先进入到root权限下2、修改 /etc/passwd用户信息文文件将里面的最后一行的用户名改成你想要的名字这是我改完之后的图片,这里有三处要改的,改完之后保存3、修改 /etc/shadow用户密码文件自己想要的名字也是将最后一行中的用户名改成,改完之后保存4、修改 /etc/group用户组文件这个文件有多处要修改的地方,在里面我们...
「JOISC 2014 Day1」有趣的家庭菜园前置技能:树状数组。题解部分:如果我们知道了目标序列,我们就可以构造一个序列P,它的每一个元素就是目标序列这一位置的元素在原序列的位置,那么答案就是原位置序列[也就是{1,2,3,···,n}]通过冒泡排序达到目标序列所需的交换次数目。而冒泡排序的交换次数就是P的逆序对的数量。由于要满足那两个条件,那么最后得到的序列一定是一个单增,单减或是先...