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

  对图像和滤波矩阵进行逐个元素相乘再求和的操作就相当于将一个二维的函数移动到另一个二维函数的所有位置,这个操作就叫卷积或者协相关。卷积和协相关的差别是,卷积需要先对滤波矩阵进行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之间即可。对于负数,也可以取绝对值。

  常见的卷积核:

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

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

  1. import numpy as np
  2. from PIL import Image
  3. import matplotlib.pyplot as plt
  4. import matplotlib as mpl
  5.  
  6. def convolve(image, filt):
  7. height, width = image.shape
  8. h, w = filt.shape
  9. height_new = height - h + 1
  10. width_new = width - w + 1
  11. image_new = np.zeros((height_new, width_new), dtype=np.float)
  12. for i in range(height_new):
  13. for j in range(width_new):
  14. image_new[i,j] = np.sum(image[i:i+h, j:j+w] * filt)
  15. image_new = image_new.clip(0, 255)
  16. image_new = np.rint(image_new).astype('uint8')
  17. return image_new
  18.  
  19. if __name__ == "__main__":
  20. mpl.rcParams['font.sans-serif'] = ['SimHei']
  21. mpl.rcParams['axes.unicode_minus'] = False
  22.  
  23. path = './simplepython/convolve/lena.png'
  24. A = Image.open(path, 'r')
  25. a = np.array(A)
  26. soble_x = np.array(([-1, 0, 1], [-2, 0, 2], [-1, 0, 1]))
  27. soble_y = np.array(([-1, -2, -1], [0, 0, 0], [1, 2, 1]))
  28. soble = np.array(([-1, -1, 0], [-1, 0, 1], [0, 1, 1]))
  29. prewitt_x = np.array(([-1, 0, 1], [-1, 0, 1], [-1, 0, 1]))
  30. prewitt_y = np.array(([-1, -1,-1], [0, 0, 0], [1, 1, 1]))
  31. prewitt = np.array(([-2, -1, 0], [-1, 0, 1], [0, 1, 2]))
  32. laplacian = np.array(([0, -1, 0], [-1, 4, -1], [0, -1, 0]))
  33. laplacian2 = np.array(([-1, -1, -1], [-1, 8, -1], [-1, -1, -1]))
  34. weight_list = ('soble_x', 'soble_y', 'soble', 'prewitt_x', 'prewitt_y', 'prewitt', 'laplacian', 'laplacian2')
  35. plt.figure(figsize=(10,4))
  36. i = 1
  37. for weight in weight_list:
  38. R = convolve(a[:, :, 0], eval(weight))
  39. G = convolve(a[:, :, 1], eval(weight))
  40. B = convolve(a[:, :, 2], eval(weight))
  41. I = 255 - np.stack((R, G, B), 2)
  42.  
  43. plt.subplot(2, 4, i)
  44. i += 1
  45. plt.title("滤波器: %s"%(weight))
  46. plt.axis('off')
  47. plt.imshow(I)
  48. plt.tight_layout(2)
  49. plt.subplots_adjust(top=0.92)
  50. plt.suptitle('不同的图像卷积操作')
  51. 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. 快速开发框架,及库存管理系统,基于easyui框架和C#语言MVC、EntityFrameWork、T4模板技术。

    快速开发框架,及库存管理系统,基于easyui框架和C#语言MVC.EntityFrameWork.T4模板技术. 产品界面如下图所示: 源码结构: 开放全部源码,如有需要请联系,QQ:1107141 ...

  2. 前端应该了解的PWA

    一.传统web 应用 当前web应用在移动时代并没有达到其在桌面设备上流行的程度,下面有张图来对比与原生应用之间的差别. 究其原因,无外乎下面不可避免的几点: 移动设备网络限制-不可忽略的加载时间 w ...

  3. 基于分支限界法的旅行商问题(TSP)一

    旅行推销员问题(英语:Travelling salesman problem, TSP)是这样一个问题:给定一系列城市和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路.它是组合优化 ...

  4. 学习Android过程中的一些博客或工具收集

    android studio中使用SlidingMenu: 超简单Android Studio导入第三方库(SlidingMenu)教程绝对傻瓜版 android 更新sdk23以后,报错提示Floa ...

  5. larave5.4自定义公共函数的创建

    原文地址:http://blog.csdn.net/qq_38125058/article/details/76862151 公共函数,简单来说就是在任何地方都可以直接使用这个函数.简单介绍两种实现方 ...

  6. Python(Django)项目与Apache的管理

    (开开心心每一天~ ---虫瘾师) Python(Django)项目交给Apache的管理(一) 准备:Django的环境(Python).Apache.Wsgi(必须文件) 首先需要电脑有Pytho ...

  7. Python_自定义栈

    customStack.py '''栈:是一种运算受限的线性表,其特点在于仅允许在一端进行元素的插入和删除操作,最后入栈的最先出栈,而最先入栈的元素最后出栈''' s = [] s.append(3) ...

  8. 记录几个经典的字符串hash算法

    记录几个经典的字符串hash算法,方便以后查看: 推荐一篇文章: http://www.partow.net/programming/hashfunctions/# (1)暴雪字符串hash #inc ...

  9. 渐进式Web应用(PWA)入门教程(上)

    最近关于渐进式Web应用有好多讨论,有一些人还在质疑渐进式Web应用是否就是移动端未来. 但在这篇文章中我并不会将渐进式APP和原生的APP进行比较,但有一点是可以肯定的,这两种APP的目标都是使用户 ...

  10. onConfigurationChanged方法的使用

    在日常生活中,手机会有很多种配置放生改变的情况,当然,有些时候需要监听他们并对他们进行处理,这就涉及到了onConfiguration方法的使用,我大致说一下,这个方法需要发生在屏幕切换横竖屏,或者选 ...