python——对图像进行卷积操作,使用多个滤波器

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

  对图像和滤波矩阵进行逐个元素相乘再求和的操作就相当于将一个二维的函数移动到另一个二维函数的所有位置,这个操作就叫卷积或者协相关。卷积和协相关的差别是,卷积需要先对滤波矩阵进行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图像进行操作,下面是得到的结果:

原文地址:https://www.cnblogs.com/baby-lily/p/10759386.html

时间: 2024-10-12 07:11:04

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

卷积操作转化成矩阵乘法

参考:https://petewarden.com/2015/04/20/why-gemm-is-at-the-heart-of-deep-learning/ 平常都是无脑使用Pytorch提供的nn.Conv2d方法,但是并不关心具体该如何实现,原来是把卷积操作转化成矩阵乘法,而不是真的通过滑动卷积核来做卷积,下面做具体介绍. 首先看一下下面的示意图,左边是输入图像,右边是卷积核(为方便说明,只用了一个卷积核). 下面是用这个卷积核对输入图像做卷积操作,最后得到一个2维的平面 由下图可以看到卷

python基本图像操作

Python基本图像操作 使用python进行基本的图像操作与处理 前言: 与早期计算机视觉领域多数程序都是由 C/C++ 写就的情形不同.随着计算机硬件速度越来越快,研究者在考虑选择实现算法语言的时候会更多地考虑编写代码的效率和易用性,而不是像早年那样把算法的执行效率放在首位.这直接导致近年来越来越多的研究者选择 Python 来实现算法. 今天在计算机视觉领域,越来越多的研究者使用 Python 开展研究,所以有必要去学习一下十分易用的python在图像处理领域的使用,这篇博客将会介绍如何使

卷积操作的GPU粗粒度并行实现及测试

一.    算法基本思想: 1.           GPU中的一个线程产生一个卷积结果,有多少个结果就使用多少个Block; 2.           矩阵和卷积核存放在共享内存中,卷积结果存放在全局内存中: 3.           支持10000以内任意维度的二维矩阵,卷积核最大支持16x16. 4.           支持任意多幅图像的批处理. 二.    实验平台: CPU:Intel(R) Xeon(R) E5-2650 0 @2.00GHz 16核 32线程 GPU:NVIDIA

卷积操作的GPU粗粒度并行实现及测试(优化)

A.边界扩展: B.字块对齐. Matrix Size Number Kernel CPU(s) CPU2GPU GPU-Kernel GPU2CPU 5x4 1 5x4 <1ms <1ms <1ms <1ms 12x9 1 5x4 <1ms <1ms <1ms <1ms 18x19 1 5x4 <1ms <1ms <1ms <1ms 118x29 1 5x4 <1ms <1ms <1ms <1ms 138x5

八.使用OpenCv对图像进行平滑操作

1.cvSmooth函数 函数 cvSmooth 可使用简单模糊.简单无缩放变换的模糊.中值模糊.高斯模糊.双边滤波的任何一种方法平滑图像.每一种方法都有自己的特点以及局限. 没有缩放的图像平滑仅支持单通道图像,并且支持8位到16位的转换(与cvSoble和cvaplace相似)和32位浮点数到32位浮点数的变换格式. 简单模糊和高斯模糊支持 1- 或 3-通道, 8-比特 和 32-比特 浮点图像.这两种方法可以(in-place)方式处理图像. 中值和双向滤波工作于 1- 或 3-通道, 8

python实现图像膨胀和腐蚀算法

如果您觉得本文不错!记得点赞哦! 一. 图像形态学简介: 经验之谈:形态学操作一般作用于二值图像,来连接相邻的元素(膨胀)或分离成独立的元素(侵蚀).腐蚀和膨胀是针对图片中的白色(即前景)部分! 二. 图像形态学操作 膨胀和腐蚀的算法: 膨胀算法: 对于待操作的像素 f(x,y),不论 f(x,y-1) .f(x,y+1) .f(x-1,y) .f(x+1,y) 哪一个为255,则 f(x,y)=255. 膨胀操作 ↑ 换句话说:将待操作的图像像素与以下  4-近邻矩阵 相乘,结果大于255的话

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

近年来很多研究将nlp中的attention机制融入到视觉的研究中,得到很不错的结果,于是,论文侧重于从理论和实验去验证self-attention可以代替卷积网络独立进行类似卷积的操作,给self-attention在图像领域的应用奠定基础 论文: On the Relationship between Self-Attention and Convolutional Layers 论文地址:https://arxiv.org/abs/1911.03584 论文代码:https://githu

学习python对文件内容的操作

在Python中对文件的操作使用open(filename,"w"),这里filename是文件名称,w指写入操作,会自动覆盖文件中的所有内容,还有r读操作和a追加操作等. 需要注意的是:只能同时进行一项操作,比如写的时候不能读,即使你使用w+参数,也只是读出来空白内容,不过不会报错,所有执行完一项操作使用新的参数才能继续不同的操作,如: f = open(filename,'w')  #以写操作打开文件filename,文件存在则覆盖,不存在则建立 f.write('this is 

Python中列表list常见操作

主要涉及知识点 列表是我们python里面最常见的数据类型,我们主要有以下的操作. 1.索引 2.切片 3.追加 4.删除 5.长度 6.循环 (也称遍历) 7.包含 8.嵌套 例如定义列表: List2=['openstack','python','linux',"docker","zabbix","nginx","linux","linux","123","ww33##&q