线性滤波可以说是图像处理最基本的方法,它可以允许我们对图像进行处理,产生很多不同的效果。做法很简单。首先,我们有一个二维的滤波器矩阵(有个高大上的名字叫卷积核)和一个要处理的二维图像。然后,对于图像的每一个像素点,计算它的邻域像素和滤波器矩阵的对应元素的乘积,然后加起来,作为该像素位置的值。这样就完成了滤波过程。

  对图像和滤波矩阵进行逐个元素相乘再求和的操作就相当于将一个二维的函数移动到另一个二维函数的所有位置,这个操作就叫卷积或者协相关。卷积和协相关的差别是,卷积需要先对滤波矩阵进行180的翻转,但如果矩阵是对称的,那么两者就没有什么差别了。

Correlation 和 Convolution可以说是图像处理最基本的操作,但却非常有用。这两个操作有两个非常关键的特点:它们是线性的,而且具有平移不变性shift-invariant。平移不变性指我们在图像的每个位置都执行相同的操作。线性指这个操作是线性的,也就是我们用每个像素的邻域的线性组合来代替这个像素。这两个属性使得这个操作非常简单,因为线性操作是最简单的,然后在所有地方都做同样的操作就更简单了。

实际上,在信号处理领域,卷积有广泛的意义,而且有其严格的数学定义,但在这里不关注这个。

2D卷积需要4个嵌套循环4-double loop,所以它并不快,除非我们使用很小的卷积核。这里一般使用3x3或者5x5。而且,对于滤波器,也有一定的规则要求:

1)滤波器的大小应该是奇数,这样它才有一个中心,例如3x3,5x5或者7x7。有中心了,也有了半径的称呼,例如5x5大小的核的半径就是2。

2)滤波器矩阵所有的元素之和应该要等于1,这是为了保证滤波前后图像的亮度保持不变。当然了,这不是硬性要求了。

3)如果滤波器矩阵所有元素之和大于1,那么滤波后的图像就会比原图像更亮,反之,如果小于1,那么得到的图像就会变暗。如果和为0,图像不会变黑,但也会非常暗。

4)对于滤波后的结构,可能会出现负数或者大于255的数值。对这种情况,我们将他们直接截断到0和255之间即可。对于负数,也可以取绝对值。

  常见的卷积核:

soble_x = np.array(([-1, 0, 1], [-2, 0, 2], [-1, 0, 1]))
soble_y = np.array(([-1, -2, -1], [0, 0, 0], [1, 2, 1]))
soble = np.array(([-1, -1, 0], [-1, 0, 1], [0, 1, 1]))
prewitt_x = np.array(([-1, 0, 1], [-1, 0, 1], [-1, 0, 1]))
prewitt_y = np.array(([-1, -1,-1], [0, 0, 0], [1, 1, 1]))
prewitt = np.array(([-2, -1, 0], [-1, 0, 1], [0, 1, 2]))
laplacian = np.array(([0, -1, 0], [-1, 4, -1], [0, -1, 0]))
laplacian2 = np.array(([-1, -1, -1], [-1, 8, -1], [-1, -1, -1]))

  不同的卷积核对图像进行滤波得到的效果是不同的,我们可以根据滤波器的特点分析出滤波器的功能,下面我们使用python代码对卷积操作进行实践:

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib as mpl def convolve(image, filt):
height, width = image.shape
h, w = filt.shape
height_new = height - h + 1
width_new = width - w + 1
image_new = np.zeros((height_new, width_new), dtype=np.float)
for i in range(height_new):
for j in range(width_new):
image_new[i,j] = np.sum(image[i:i+h, j:j+w] * filt)
image_new = image_new.clip(0, 255)
image_new = np.rint(image_new).astype('uint8')
return image_new if __name__ == "__main__":
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False path = './simplepython/convolve/lena.png'
A = Image.open(path, 'r')
a = np.array(A)
soble_x = np.array(([-1, 0, 1], [-2, 0, 2], [-1, 0, 1]))
soble_y = np.array(([-1, -2, -1], [0, 0, 0], [1, 2, 1]))
soble = np.array(([-1, -1, 0], [-1, 0, 1], [0, 1, 1]))
prewitt_x = np.array(([-1, 0, 1], [-1, 0, 1], [-1, 0, 1]))
prewitt_y = np.array(([-1, -1,-1], [0, 0, 0], [1, 1, 1]))
prewitt = np.array(([-2, -1, 0], [-1, 0, 1], [0, 1, 2]))
laplacian = np.array(([0, -1, 0], [-1, 4, -1], [0, -1, 0]))
laplacian2 = np.array(([-1, -1, -1], [-1, 8, -1], [-1, -1, -1]))
weight_list = ('soble_x', 'soble_y', 'soble', 'prewitt_x', 'prewitt_y', 'prewitt', 'laplacian', 'laplacian2')
plt.figure(figsize=(10,4))
i = 1
for weight in weight_list:
R = convolve(a[:, :, 0], eval(weight))
G = convolve(a[:, :, 1], eval(weight))
B = convolve(a[:, :, 2], eval(weight))
I = 255 - np.stack((R, G, B), 2) plt.subplot(2, 4, i)
i += 1
plt.title("滤波器: %s"%(weight))
plt.axis('off')
plt.imshow(I)
plt.tight_layout(2)
plt.subplots_adjust(top=0.92)
plt.suptitle('不同的图像卷积操作')
plt.show()

  上述代码中,image_new.clip(0, 255)函数的作用是将image_new中的值进行截断,小于等于0的置为0,大于等于255的置为255。np.rint(image_new).astype('uint8')的含义是将得到的图像矩阵转换为int型,在转换为uint8类型。eval(weight)函数的作用是将字符串值转换为对应的变量值。我们对lena图像进行操作,下面是得到的结果:

python——对图像进行卷积操作,使用多个滤波器的更多相关文章

  1. 用python实现对图像的卷积(滤波)

    之前在看卷积神经网络,很好奇卷积到底是什么,最后看到了这篇文章http://blog.csdn.net/zouxy09/article/details/49080029,讲得很清楚,这篇文章中提到了对 ...

  2. 对抗生成网络-图像卷积-mnist数据生成(代码) 1.tf.layers.conv2d(卷积操作) 2.tf.layers.conv2d_transpose(反卷积操作) 3.tf.layers.batch_normalize(归一化操作) 4.tf.maximum(用于lrelu) 5.tf.train_variable(训练中所有参数) 6.np.random.uniform(生成正态数据

    1. tf.layers.conv2d(input, filter, kernel_size, stride, padding) # 进行卷积操作 参数说明:input输入数据, filter特征图的 ...

  3. Python机器学习笔记:卷积神经网络最终笔记

    这已经是我的第四篇博客学习卷积神经网络了.之前的文章分别是: 1,Keras深度学习之卷积神经网络(CNN),这是开始学习Keras,了解到CNN,其实不懂的还是有点多,当然第一次笔记主要是给自己心中 ...

  4. ubuntu之路——day17.1 卷积操作的意义、边缘检测的示例、filter与padding的关系、卷积步长

    感谢吴恩达老师的公开课,以下图片均来自于吴恩达老师的公开课课件 为什么要进行卷积操作? 我们通过前几天的实验已经做了64*64大小的猫图片的识别. 在普通的神经网络上我们在输入层上输入的数据X的维数为 ...

  5. ubuntu之路——day17.2 RGB图像的卷积、多个filter的输出、单个卷积层的标记方法

    和单层图像的卷积类似,只需要对每一个filter构成的三层立方体上的每一个数字与原图像对应位置的数字相乘相加求和即可. 在这个时候可以分别设置filter的R.G.B三层,可以同时检测纵向或横向边缘, ...

  6. 【Python | opencv+PIL】常见操作(创建、添加帧、绘图、读取等)的效率对比及其优化

    一.背景 本人准备用python做图像和视频编辑的操作,却发现opencv和PIL的效率并不是很理想,并且同样的需求有多种不同的写法并有着不同的效率.见全网并无较完整的效率对比文档,遂决定自己丰衣足食 ...

  7. ICLR 2020 | 抛开卷积,multi-head self-attention能够表达任何卷积操作

    近年来很多研究将nlp中的attention机制融入到视觉的研究中,得到很不错的结果,于是,论文侧重于从理论和实验去验证self-attention可以代替卷积网络独立进行类似卷积的操作,给self- ...

  8. 比CNN表现更好,CV领域全新卷积操作OctConv厉害在哪里?

    CNN卷积神经网络问世以来,在计算机视觉领域备受青睐,与传统的神经网络相比,其参数共享性和平移不变性,使得对于图像的处理十分友好,然而,近日由Facebook AI.新家坡国立大学.360人工智能研究 ...

  9. python 文件及文件夹操作

    python 文件.目录操作(新增.移动.删除等) python 文件夹与文件操作 mport string, os, sys dir = '/var' print '----------- no s ...

随机推荐

  1. Django模型层之字段查询参数及聚合函数

    该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. 字段查询是指如何指定SQL WHERE子句的 ...

  2. CSS学习笔记五:display,position区别

    最近常用css,经常在位置方面使用导display与position这两个属性,所以想要弄清楚它们之间的意思. 一.display 作用是规定元素应该生成的框的类型.意思是定义建立布局时元素生成的显示 ...

  3. 计算机的Cache和Memory访问时Write-back,Write-through及write allocate的区别

    计算机的存储系统采用Register,Cache,Memory和I/O的方式来构成存储系统,无疑是一个性能和经济性的妥协的产物.Cache和Memory机制是计算机硬件的基础内容,这里就不再啰嗦.下面 ...

  4. 基于java的ES开发

    3.1 环境配置 Jdk 1.8及以上 Elasticsearch.client 5.5.2(与服务器版本一致) Log4j 2.7及以下 maven工程必要的jar包依赖 <project x ...

  5. Unity文档阅读 第三章 依赖注入与Unity

    Introduction 简介In previous chapters, you saw some of the reasons to use dependency injection and lea ...

  6. Linux内核中的算法和数据结构

    算法和数据结构纷繁复杂,但是对于Linux Kernel开发人员来说重点了解Linux内核中使用到的算法和数据结构很有必要. 在一个国外问答平台stackexchange.com的Theoretica ...

  7. DCOS实践分享(4):如何基于DC/OS整合SMACK(Spark, Mesos, Akka, Cassandra, Kafka)

    这篇文章入选CSDN极客头条 http://geek.csdn.net/news/detail/71572 当前,要保证业务的市场竞争力,仅靠设计一个可用并且好看的产品,已经完全不能满足要求.全球消费 ...

  8. Java开源生鲜电商平台-监控模块的设计与架构(源码可下载)

    Java开源生鲜电商平台-监控模块的设计与架构(源码可下载) 说明:Java开源生鲜电商平台-监控模块的设计与架构,我们谈到监控,一般设计到两个方面的内容: 1. 服务器本身的监控.(比如:linux ...

  9. Intellij IDEA 安装lombok及使用详解

    项目中经常使用bean,entity等类,绝大部分数据类类中都需要get.set.toString.equals和hashCode方法,虽然eclipse和idea开发环境下都有自动生成的快捷方式,但 ...

  10. scrapy分布式爬虫scrapy_redis一篇

    分布式爬虫原理 首先我们来看一下scrapy的单机架构:     可以看到,scrapy单机模式,通过一个scrapy引擎通过一个调度器,将Requests队列中的request请求发给下载器,进行页 ...