卷积常用于特征提取
实验过程中注意认真体会“特征提取”,弄清楚为什么卷积能够提取特征。
一、概念
用自己的语言描述“卷积、卷积核、特征图、特征选择、步长、填充、感受野”。
卷积
卷积:卷积是一种数学运算,它通过将输入数据与卷积核进行逐元素相乘,并对结果进行求和来生成输出特征图。
看下面这个动图生动形象嘞
卷积核
卷积核:卷积核是一个用于在卷积操作中提取特征的二维矩阵,每个卷积核都具有一组参数,可以通过训练来优化以提取不同类型的特征(又称滤波器)。通俗的来说就是类似我们之前学过的加权求和的权值,通过这些权值计算出新的图像和矩阵。
这个动图里粉色和红色的就是卷积核
特征图
特征图:特征图是由一系列卷积核对输入图像进行卷积操作得到的结果。它可以看作是原始图像的抽象表示,每个特征图代表了输入数据中某些特定的特征。
特征选择
特征选择:是指从原始数据中选择最具有代表性和相关性的特征,是从原始特征中选择出一些最有效特征以降低数据集维度的过程,是提高学习算法性能的一个重要手段,也是模式识别中关键的数据预处理步骤。在卷积神经网络中,每个卷积核负责提取输入数据的某些特定特征,因此可以视为一种特征选择的方法。
我感觉特征选择就是就是将自己需要的特征突出出来,比如课上讲的,需要将眼镜进行特征选择,就在对眼睛进行卷积时,是眼睛则为1,反之为0。
图片来自于:卷积神经网络工作原理的直观理解
步长
步长:是指卷积操作中滑动卷积核的步幅
填充
填充: 在输入数据周围添加额外的值(通常是0)以扩展输入的大小。填充可以用于控制卷积操作后输出特征图的尺寸,并且还有助于保留原始数据边缘信息。
感受野
感受野:在卷积神经网络中,感受野的定义是卷积神经网络每一层输出的特征图上的像素点在输入图片上映射的区域大小。再通俗点的解释是,卷积神经网络中每个输出单元对应输入数据的区域大小。
二、探究不同卷积核的作用
1. 图1分别使用卷积核,输出特征图
图1使用卷积核,输出特征图:(卷积层要写的时候进行反转)
import matplotlib.pyplot as plt import numpy as np # 生成图1 p1 = np.array([[0, 0, 0, 255, 255, 255], [0, 0, 0, 255, 255, 255], [0, 0, 0, 255, 255, 255], [0, 0, 0, 255, 255, 255]], dtype='float32') def cov2(img,kernel,strde): inw,inh = img.shape w,h=kernel.shape outw = int((inw -w )/strde + 1) outh = int((inh -h )/strde + 1) arr = np.zeros((outw, outh)) for g in range(outw): for t in range(outh): s= 0 for i in range(w): for j in range(h): s+=img[i+g*strde][j+t*strde]*kernel[i][j] # s = img[i][j] * f[i][j] arr[g][t]=s return arr # 问题1 kernel1 = np.array([[-1, 1]]) # 注意二维矩阵要用两个中括号 卷积层要反转 t1 = cov2(p1, kernel1, 1) print('图1使用卷积核(1,-1)后:') print(t1) # 绘制图像 plt.figure(1) plt.subplot(3, 1, 1) plt.title('tu1') plt.imshow(p1, cmap='gray') plt.subplot(3, 1, 3) plt.title('(1,-1)') plt.imshow(t1, cmap='gray') plt.show()
2. 图1使用卷积核,输出特征图(注意:这是2*1的矩阵作为卷积核)
import matplotlib.pyplot as plt import numpy as np # 生成图1 p1 = np.array([[0, 0, 0, 255, 255, 255], [0, 0, 0, 255, 255, 255], [0, 0, 0, 255, 255, 255], [0, 0, 0, 255, 255, 255]], dtype='float32') def cov2(img,kernel,strde): inw,inh = img.shape w,h=kernel.shape outw = int((inw -w )/strde + 1) outh = int((inh -h )/strde + 1) arr = np.zeros((outw, outh)) for g in range(outw): for t in range(outh): s= 0 for i in range(w): for j in range(h): s+=img[i+g*strde][j+t*strde]*kernel[i][j] # s = img[i][j] * f[i][j] arr[g][t]=s return arr # 问题1 kernel2 = np.array(([[1],[-1]])) # 注意二维矩阵要用两个中括号 卷积层要反转 t1 = cov2(p1, kernel2, 1) print('图1使用卷积核(1,-1)后:') print(t1) # 绘制图像 plt.figure(1) plt.subplot(3, 1, 1) plt.title('tu1') plt.imshow(p1, cmap='gray') plt.subplot(3, 1, 3) plt.title('([[1],[-1]])') plt.imshow(t1, cmap='gray') plt.show()
2. 图2分别使用卷积核,输出特征图
import matplotlib.pyplot as plt import numpy as np # 生成图1 p2 = np.array([[0, 0, 0, 0, 255, 255, 255, 255], [0, 0, 0, 0, 255, 255, 255, 255], [0, 0, 0, 0, 255, 255, 255, 255], [0, 0, 0, 0, 255, 255, 255, 255], [255, 255, 255, 255, 0, 0, 0, 0], [255, 255, 255, 255, 0, 0, 0, 0], [255, 255, 255, 255, 0, 0, 0, 0], [255, 255, 255, 255, 0, 0, 0, 0]], dtype='float32') def cov2(img,kernel,strde): inw,inh = img.shape w,h=kernel.shape outw = int((inw -w )/strde + 1) outh = int((inh -h )/strde + 1) arr = np.zeros((outw, outh)) for g in range(outw): for t in range(outh): s= 0 for i in range(w): for j in range(h): s+=img[i+g*strde][j+t*strde]*kernel[i][j] # s = img[i][j] * f[i][j] arr[g][t]=s return arr # 问题3 kernel3 = np.array([[-1, 1]]) # 注意二维矩阵要用两个中括号 t3 = cov2(p2, kernel3, 1) print('图2使用卷积核(1,-1)后:') print(t3) # 问题4 kernel4 = np.array([[-1,],[1]]) # 注意二维矩阵要用两个中括号 t4 = cov2(p2,kernel4,1) print('图2使用卷积核(1,-1)的转置后:') print(t4) # 绘制图像 plt.figure(1) plt.subplot(3, 1, 1) plt.title('tu2') plt.imshow(p2, cmap='gray') plt.subplot(3, 1, 2) plt.title('(1,-1)') plt.imshow(t3, cmap='gray') plt.subplot(3, 1, 3) plt.title('kernel = (1,-1)T') plt.imshow(t4,cmap='gray') plt.subplots_adjust(hspace=0.5) plt.show()
3. 图3分别使用卷积核,, ,输出特征图
import matplotlib.pyplot as plt import numpy as np p3 = np.zeros((9, 9)) for i in range(1, 5): p3[i, i] = 255 p3[i, 8-i] = 255 p3[8-i, i] = 255 p3[8-i, 8-i] = 255 def cov2(img,kernel,strde): inw,inh = img.shape w,h=kernel.shape outw = int((inw -w )/strde + 1) outh = int((inh -h )/strde + 1) arr = np.zeros((outw, outh)) for g in range(outw): for t in range(outh): s= 0 for i in range(w): for j in range(h): s+=img[i+g*strde][j+t*strde]*kernel[i][j] # s = img[i][j] * f[i][j] arr[g][t]=s return arr # 问题5 kernel5_1 = np.array([[-1, 1]]) # 注意二维矩阵要用两个中括号 kernel5_2 = np.array([[-1], [1]]) kernel5_3 = np.array([[1, -1], [-1, 1]]) t5_1 = cov2(p3, kernel5_1, 1) t5_2 = cov2(p3, kernel5_2, 1) t5_3 = cov2(p3, kernel5_3, 1) print('图3使用卷积核(1,-1)后:') print(t5_1) print('图3使用卷积核(1,-1)的转置后:') print(t5_2) print('图3使用第三个卷积核后:') print(t5_3) plt.figure(6) plt.subplot(2, 2, 1) plt.title('kernel = (1,-1)') plt.imshow(t5_1, cmap='gray') plt.subplot(2, 2, 2) plt.title('kernel = (1,-1)T') plt.imshow(t5_2, cmap='gray') plt.subplot(2, 2, 3) plt.title('kernel = [1, -1], [-1, 1]') plt.imshow(t5_3, cmap='gray') plt.subplot(2, 2, 4) plt.title('p3') plt.imshow(p3, cmap='gray') plt.show()
4. 实现灰度图的边缘检测、锐化、模糊。
参考链接:Image Kernels explained visually (setosa.io)
模糊: (卷积核显而易见3*3的)
我的代码实现:
import matplotlib.pyplot as plt import torch from PIL import Image import numpy as np def cov2(picture, kernel, strde): # picture 为原图像,kernel 为卷积核,strde 为步长 # x,y为矩阵的行列数 x1, y1 = picture.shape x2, y2 = kernel.shape # x_count,y_count是计算在行列上卷积核与原图像的乘积次数,也是卷积后矩阵的行列数 x3 = int((x1 - x2) / strde + 1) y3 = int((y1 - y2) / strde + 1) # 卷积后生成的新矩阵arr arr = np.zeros((x3, y3)) # 先行后列进行卷积 for i in range(0, y3): for j in range(0, x3): s = 0 for m in range(0, x2): for n in range(0, y2): s = s + picture[m + j * strde][n + i * strde] * kernel[m][n] arr[j][i] = s return arr im = Image.open('C:\\Users\\hp\\Desktop\\33.jpg').convert('L') # 以灰度图形式读入图像 im = np.array(im, dtype='float') # 将原图转化为矩阵形式 plt.figure(1) plt.subplot(1, 2, 1) plt.title('im') plt.imshow(im,cmap='gray') # 模糊 # 定义卷积核 kernel2 = np.array([[0.0625, 0.125, 0.0625], [0.125, 0.25, 0.125], [0.0625, 0.125, 0.0625]]) # 开始卷积 t2 = cov2(im, kernel2, 1) plt.subplot(1, 2, 2) plt.title('blur') plt.imshow(t2, cmap='gray') plt.show()
锐化:
代码类似,改变一下卷积核就行了
结果:
边缘检测
这张图对卷积核显而易见,但是我做实验有疑问,就是我做实验卷积核,用的上面那个但是我的边缘检测结果很浅
然后询问chat
又看了上届学姐的代码,将卷积核里面的一个8改成9以后效果显著
5. 总结不同卷积核的特征和作用。
底部边缘检测卷积核(Bottom Sobel)它通常用于图像处理中的边缘检测任务,以识别并突出显示图像中底部边缘的位置。
left_sobel左部边缘卷积核: 左侧邻域的像素被赋予更高的权重,以识别并突出显示图像中左部边缘的位置。
Right Sobel(右部边缘卷积核):用于检测图像中的右部边缘。
Top Sobel(顶部边缘卷积核): 用于检测图像中的顶部边缘。
锐化卷积核:用于增强图像的细节和边缘。
模糊卷积核:模糊卷积核用于减少图像中的噪声和细节。
Emboss(突出图像轮廓)卷积核:可用于突出图像的轮廓,产生一种浮雕效果
Outline(检测边缘轮廓)卷积核:用于检测图像中的边缘轮廓。
实验总结:
1、这次实验,也是处理图像,在数字图像处理实验中,用的matlab,需要将图片先转换成灰色来提高计算准确率和速度,这次是python,我尝试不转,然后我就得到了
彩色图像经过卷积操作后,并不会直接变成绿色。卷积是一种在图像处理中常用的操作,它通过使用一个滤波器(也称为卷积核)来改变图像的特定特征。滤波器可以进行边缘检测、模糊等处理。
卷积操作通常在每个像素上进行,并将其与周围像素进行计算。对于彩色图像,这个操作会分别应用到每个颜色通道上(如红色、绿色和蓝色)。因此,在经过卷积操作后,每个颜色通道的像素值可能会发生变化。
如果你在卷积操作后看到的结果是绿色,可能有以下几个原因:
- 滤波器或卷积核的设计选择了与绿色相关的特征。例如,如果滤波器被设计用于检测绿色边缘,那么输出图像可能会更加突出绿色。
- 图像的颜色分布偏向绿色。如果输入图像本身在绿色通道上具有较高的像素值,那么经过卷积操作后,输出图像可能会保持或加强原先的绿色。
此外,卷积操作通常会对图像进行多次迭代,以便提取更多的特征信息。因此,最终输出图像的颜色可能是由多个卷积操作和滤波器共同决定的,而不仅仅是单个卷积操作造成的。
2、官网上给的卷积核不一定适配所有的图片,要根据实际情况,不断调整卷积核,从而得到最好的结果,没有免费的午餐定理。