为什么卷积核要翻转180°
1.围绕卷积核中心旋转180度
方法:把卷积核写在一张纸上,用笔尖固定住中心元素,旋转180度后就是翻转后的卷积核。
2.沿着两条对角线翻转两次
方法:设原始卷积核为:
1 2 3
4 5 6
7 8 9
第一次沿着左下角到右上角翻转,也就是3,5,7不变,2和4 交换。6和8交换,1和9交换
9 6 3
8 5 2
7 4 1
第二次沿着左上角到右下角翻转,也就是9,5,1不变,4和2交换。3和7交换,8和6交换
9 8 7
6 5 4
3 2 1
3.同时翻转行和列
1 2 3
4 5 6
7 8 9
第一次翻转行
7 8 9
4 5 6
1 2 3
第二次翻转列
9 8 7
6 5 4
3 2 1
参考博客
图片一般读进来是(H,W,C)的格式,height 0, width 1, channel 2
image = image.transpose((2, 0, 1)) # image.shape=(C, H, W)
用transpose来将通道数换到最前面,方便后面的enumerate进行一个通道一个通道来卷积的操作
def perform_numpy_convolution(image: np.ndarray, template: np.ndarray):
# Flip the template around both axes
inverted_template = np.flip(template) #绕卷积核中心旋转180度
# 实际上并不需要翻转,因为x,y的位置是对称的,而且在f(x,y)里面的x,y都要平方
x, y = len(image), len(image[0]) #307, 375
offset = int((len(template) - 1) / 2) # (41-1)/2 offset即padding
# 卷积后的图片大小= (n-f+2p)/s + 1
# 而这里的p = (f-1)/2, s=1, 即保证了卷积前后的图片大小不变
print(f'Original Shape: {np.shape(image)}') # image.shape=(H,W,C)
print(f'Transposed Shape: {np.shape(image.transpose((2, 0, 1)))}')# image.shape=(C,H,W),这是为了方便后面进行卷积操作才进行transpose操作
print(f'Un-Transposed Shape: {np.shape(image.transpose((2, 0, 1)).transpose((1, 2, 0)))}')# 又换回image.shape=(H,W,C)
# Original Shape: (307, 375, 3)
# Transposed Shape: (3, 307, 375)
# Un-Transposed Shape: (307, 375, 3)
if image.ndim == 2:
image = np.array(image)
else: # img.ndim=3
image = image.transpose((2, 0, 1)) # image.shape=(3, 307, 375)
# Now image can be looped through
new_image = np.zeros(shape=np.shape(image)).astype(int) # shape(3, 307, 375)用来存放三个通道卷积后的图片数值
for index, color_array in enumerate(image): # 把三个通道给分别拆开,并分布用卷积核来进行卷积
padded_color_array = np.pad(color_array, [offset, offset], mode='constant') # 第[0]轴和第[1]轴都填充0,填充后的大小为H,W=(327, 395)
new_color_array = np.zeros((x, y)).astype(int) # x, y分别表示H, W,307, 375,这个是用来存放一个通道卷积后的值
# tqdm就是显示进度条的,在 shell 中不断重写当前输出
for row in tqdm(range(0+offset, x+offset)): # row∈(20,327)
for column in range(0+offset, y+offset):
# 下面就是学的卷积核的操作,对应位置进行相乘并相加
section = np.array(padded_color_array[row-offset:row+offset+1,column-offset:column+offset+1])
new_color_array[row-offset][column-offset] = np.sum(np.multiply(section, inverted_template))
new_image[index] = new_color_array # 存放3个通道依次卷积后的结果
return new_image.transpose((1, 2, 0)) # 将卷积后的结果给转为(H,W,C)格式,并返回
import matplotlib.pyplot as plt
import cv2
# cv2.imread()接口读图像,读进来直接是BGR 格式数据格式在 0~255,通道格式为(W,H,C)
img_BGR = cv2.imread('../data/submarine.jpg')
plt.subplot(2,2,1)
plt.imshow(img_BGR)
plt.axis('off')
plt.title('BGR')
img_RGB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)
plt.subplot(2,2,2)
plt.imshow(img_RGB)
plt.axis('off')
plt.title('RGB')
img_GRAY = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY)
print(img_BGR.shape)
print(img_GRAY.shape)
print(type(img_GRAY))
print(img_GRAY.astype)
print(img_GRAY.dtype.name, img_BGR .dtype.name)
from skimage import io,data
img=data.chelsea()
print(img.dtype.name)
plt.subplot(2,2,3); plt.imshow(img_GRAY);plt.axis('off');plt.title('GRAY')
img_HSV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HSV)
plt.subplot(2,2,4); plt.imshow(img_HSV);plt.axis('off');plt.title('HSV')
plt.show()
通过我做的实验和在网上看别人实验的结果,发现转换后并不是通常意义上的黑白图片。根据我问别人后的结果,他说,灰度图片并不是指常规意义上的黑白图片,只用看是不是无符号八位整型(unit8),单通道即可判断。
参考博客
参考博客
这里记高斯核的大小为 f , f, f, 即 f i l t e r filter filter的意思
通常取 f = 3 σ + 1 f = 3\sigma +1 f=3σ+1
理由如下:
3 σ \sigma σ的距离大概包含了99%的信息,如下图所示
为什么高斯核叫平滑滤波?
因为高斯平滑为加权平滑
opencv中很多算子的高斯滤波函数只有一个参数 σ \sigma σ或者核的大小 f i l t e r filter filter
这可能是默认取 f = 3 σ + 1 f = 3\sigma +1 f=3σ+1,这样99%的信息基本都涵盖了,滤波效果比较好,(+1是为了保证滤波核为奇数)
参考博客
参考博客
一维正态分布(高斯分布)
N ( x ∣ μ , σ 2 ) = 1 σ 2 π exp { − 1 2 ( x − μ σ ) 2 } N\left(x \mid \mu, \sigma^{2}\right)=\frac{1}{\sigma\sqrt{2 \pi}} \exp \left\{-\frac{1}{2}(\frac{x-\mu}{\sigma})^{2}\right\} N(x∣μ,σ2)=σ2π1exp{−21(σx−μ)2}
拓展到高维时
多维正态分布
假设n维随机变量 x = [ x 1 , x 2 , ⋯ , x n ] T x=\left[x_{1}, x_{2}, \cdots, x_{n}\right]^{\mathrm{T}} x=[x1,x2,⋯,xn]T的各个维度之间互不相关,且服从正态分布(维度不相关多元正态分布),各个维度的均值为 E ( x ) = [ μ 1 , μ 2 , ⋯ , μ n ] T E(x)=\left[\mu_{1}, \mu_{2}, \cdots, \mu_{n}\right]^{\mathrm{T}} E(x)=[μ1,μ2,⋯,μn]T,各个维度的方差为 σ ( x ) = [ σ 1 , σ 2 , ⋯ , σ n ] T \sigma(x)=\left[\sigma_{1}, \sigma_{2}, \cdots, \sigma_{n}\right]^{\mathrm{T}} σ(x)=[σ1,σ2,⋯,σn]T
根据联合概率密度公式:
f ( x ) = p ( x 1 , x 2 … x n ) = p ( x 1 ) p ( x 2 ) … p ( x n ) = 1 2 π σ 1 exp ( − 1 2 ( x 1 − μ 1 σ 1 ) 2 ) 1 2 π σ 2 exp ( − 1 2 ( x 2 − μ 2 σ 2 ) 2 ) ⋯ 1 2 π σ n exp ( − 1 2 ( x n − μ n σ n ) 2 ) = 1 ( 2 π ) n σ 1 σ 2 ⋯ σ n exp ( − 1 2 [ ( x 1 − μ 1 σ 1 ) 2 + ( x 2 − μ 2 σ 2 ) 2 + ⋯ + ( x n − μ n σ n ) 2 ] ) \begin{array}{l} f(x)=p\left(x_{1}, x_{2} \ldots x_{n}\right)=p\left(x_{1}\right) p\left(x_{2}\right) \ldots p\left(x_{n}\right) \\ =\frac{1}{\sqrt{2 \pi} \sigma_{1}} \exp \left(-\frac{1}{2}\left(\frac{x_{1}-\mu_{1}}{\sigma_{1}}\right)^{2}\right) \frac{1}{\sqrt{2 \pi} \sigma_{2}} \exp \left(-\frac{1}{2}\left(\frac{x_{2}-\mu_{2}}{\sigma_{2}}\right)^{2}\right) \cdots \frac{1}{\sqrt{2 \pi} \sigma_{n}} \exp \left(-\frac{1}{2}\left(\frac{x_{n}-\mu_{n}}{\sigma_{n}}\right)^{2}\right)\\ =\frac{1}{(\sqrt{2 \pi})^{n} \sigma_{1} \sigma_{2} \cdots \sigma_{n}} \exp \left(-\frac{1}{2}\left[\left(\frac{x_{1}-\mu_{1}}{\sigma_{1}}\right)^{2}+\left(\frac{x_{2}-\mu_{2}}{\sigma_{2}}\right)^{2}+\cdots+\left(\frac{x_{n}-\mu_{n}}{\sigma_{n}}\right)^{2}\right]\right)\end{array} f(x)=p(x1,x2…xn)=p(x1)p(x2)…p(xn)=2πσ11exp(−21(σ1x1−μ1)2)2πσ21exp(−21(σ2x2−μ2)2)⋯2πσn1exp(−21(σnxn−μn)2)=(2π)nσ1σ2⋯σn1exp(−21[(σ1x1−μ1)2+(σ2x2−μ2)2+⋯+(σnxn−μn)2])
可以参看这篇《多维正态分布的极大似然估计》的推导过程,推导比较详细
经过一系列化简可以得到:
f ( x ) = 1 ( 2 π ) n σ 1 σ 2 ⋯ σ n exp ( − 1 2 [ ( x 1 − μ 1 σ 1 ) 2 + ( x 2 − μ 2 σ 2 ) 2 + ⋯ + ( x n − μ n σ n ) 2 ] ) = 1 ( 2 π ) n ∣ Σ ∣ exp ( − 1 2 ( x − μ ) T Σ − 1 ( x − μ ) ) = ( 2 π ) − n 2 ∣ Σ ∣ − 1 2 exp ( − 1 2 ( x − μ ) T Σ − 1 ( x − μ ) ) = f ( x ; μ , Σ ) \begin{aligned} f(x) &=\frac{1}{(\sqrt{2 \pi})^{n} \sigma_{1} \sigma_{2} \cdots \sigma_{n}} \exp \left(-\frac{1}{2}\left[\left(\frac{x_{1}-\mu_{1}}{\sigma_{1}}\right)^{2}+\left(\frac{x_{2}-\mu_{2}}{\sigma_{2}}\right)^{2}+\cdots+\left(\frac{x_{n}-\mu_{n}}{\sigma_{n}}\right)^{2}\right]\right) \\ &=\frac{1}{(\sqrt{2 \pi})^{n} \sqrt{|\Sigma|}} \exp \left(-\frac{1}{2}(x-\mu)^{\mathrm{T}} \Sigma^{-1}(x-\mu)\right) \\ &=(2 \pi)^{-\frac{n}{2}}|\Sigma|^{-\frac{1}{2}} \exp \left(-\frac{1}{2}(x-\mu)^{\mathrm{T}} \Sigma^{-1}(x-\mu)\right) \\ &=f(x ; \mu, \Sigma) \end{aligned} f(x)=(2π)nσ1σ2⋯σn1exp(−21[(σ1x1−μ1)2+(σ2x2−μ2)2+⋯+(σnxn−μn)2])=(2π)n∣Σ∣1exp(−21(x−μ)TΣ−1(x−μ))=(2π)−2n∣Σ∣−21exp(−21(x−μ)TΣ−1(x−μ))=f(x;μ,Σ)
n维相互独立的随机变量 x x x 服从正态分布:
x ∼ N ( μ , σ 2 ) , σ i ≥ 0 x \sim N\left(\mu, \sigma^{2}\right), \quad \sigma_{i} \geq 0 x∼N(μ,σ2),σi≥0
多维正态分布的最终形式为:
f ( x ) = f ( x ; μ , Σ ) f(x) = f(x ; \mu, \Sigma) f(x)=f(x;μ,Σ)
二维正态分布
(X,Y)服从参数为μ1, μ2, σ1, σ2, ρ的二维正态分布,记作(X, Y)~N(μ1, μ2, σ1, σ2, ρ),它的密度函数:
f ( x , y ) = 1 2 π σ 1 σ 2 1 − ρ 2 exp ( − 1 2 ( 1 − ρ 2 ) [ ( x − μ 1 ) 2 σ 1 2 − 2 ρ ( x − μ 1 ) ( y − μ 2 ) 2 σ 1 σ 2 + ( y − μ 2 ) 2 σ 2 2 ] ) = 1 ( 2 π ) 2 σ 1 σ 2 1 − ρ 2 exp ( − 1 2 ( 1 − ρ 2 ) [ ( x − μ 1 ) 2 σ 1 2 − 2 ρ ( x − μ 1 ) ( y − μ 2 ) 2 σ 1 σ 2 + ( y − μ 2 ) 2 σ 2 2 ] ) \begin{array}{l} f\left(x, y\right) \\ \quad=\frac{1}{2 \pi \sigma_{1} \sigma_{2} \sqrt{1-\rho^{2}}} \exp \left(-\frac{1}{2\left(1-\rho^{2}\right)}\left[\frac{\left(x-\mu_{1}\right)^{2}}{\sigma_{1}^{2}}-2 \rho \frac{\left(x-\mu_{1}\right)\left(y-\mu_{2}\right)}{2 \sigma_{1} \sigma_{2}}+\frac{\left(y-\mu_{2}\right)^{2}}{\sigma_{2}^{2}}\right]\right) \\ \quad=\frac{1}{(\sqrt{2 \pi})^{2} \sigma_{1} \sigma_{2} \sqrt{1-\rho^{2}}} \exp \left(-\frac{1}{2\left(1-\rho^{2}\right)}\left[\frac{\left(x-\mu_{1}\right)^{2}}{\sigma_{1}^{2}}-2 \rho \frac{\left(x-\mu_{1}\right)\left(y-\mu_{2}\right)}{2 \sigma_{1} \sigma_{2}}+\frac{\left(y-\mu_{2}\right)^{2}}{\sigma_{2}^{2}}\right]\right) \end{array} f(x,y)=2πσ1σ21−ρ21exp(−2(1−ρ2)1[σ12(x−μ1)2−2ρ2σ1σ2(x−μ1)(y−μ2)+σ22(y−μ2)2])=(2π)2σ1σ21−ρ21exp(−2(1−ρ2)1[σ12(x−μ1)2−2ρ2σ1σ2(x−μ1)(y−μ2)+σ22(y−μ2)2])
其中μ1是第1维度的均值,σ1是第1维度的方差,ρ是将两个维度的相关性规范到-1到+1之间的统计量,称为样本的相关系数,定义为:
ρ = COV ( X , Y ) σ 1 σ 2 , ∣ ρ ∣ < 1 \rho=\frac{\operatorname{COV}(X, Y)}{\sigma_{1} \sigma_{2}}, \quad|\rho|<1 ρ=σ1σ2COV(X,Y),∣ρ∣<1
对于二维正态随机变量(X,Y),X和Y相互独立的充要条件是二者的协方差为0,也就是参数ρ=0。由于一维随机变量没有是否独立一说,ρ一定是0,因此没有在一维随机变量的正态分布中体现ρ。
当 x , y x, y x,y为独立同分布时,即有 ρ = 0 , σ 1 = σ 2 = σ , μ 1 = μ 2 = μ \rho=0, \sigma_{1}=\sigma_{2}=\sigma, \mu_{1}=\mu_{2}=\mu ρ=0,σ1=σ2=σ,μ1=μ2=μ
f ( x , y ) = 1 2 π σ 2 exp ( − 1 2 [ ( x − μ σ ) 2 + ( y − μ σ ) 2 ] ) i f μ = 0 , t h e n = 1 2 π σ 2 exp { − x 2 + y 2 2 σ 2 } \begin{array}{l} f\left(x, y\right) \\ \quad=\frac{1}{2 \pi \sigma^{2}} \exp \left(-\frac{1}{2}\left[(\frac{x-\mu}{\sigma})^{2}+(\frac{y-\mu}{\sigma})^{2}\right]\right) \\ \quad \\ \quad if \mu=0, then \\ \quad\\ \quad=\frac{1}{2 \pi \sigma^{2}} \exp \left\{-\frac{x^{2}+y^{2}}{2\sigma^{2}}\right\} \\ \end{array} f(x,y)=2πσ21exp(−21[(σx−μ)2+(σy−μ)2])ifμ=0,then=2πσ21exp{−2σ2x2+y2}
参考博客
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中
语法:
enumerate(sequence, [start=0])
# sequence -- 一个序列、迭代器或其他支持迭代对象。
# start -- 下标起始位置的值。
# 返回 enumerate(枚举) 对象
在卷积神经网络中,为了避免因为卷积运算导致输出图像缩小和图像边缘信息丢失,常常采用图像边缘填充技术,即在图像四周边缘填充0,使得卷积运算后图像大小不会缩小,同时也不会丢失边缘和角落的信息。在Python的numpy库中,常常采用numpy.pad()进行填充操作,具体分析如下:
np.pad()函数
语法结构
pad(array, pad_width, mode, **kwargs)
# array——表示需要填充的数组;
# pad_width——表示每个轴(axis)边缘需要填充的数值数目。参数输入方式为:((before_1, after_1), … (before_N, after_N)),其中(before_1, after_1)表示第1轴两边缘分别填充before_1个和after_1个数值。取值为:{sequence, array_like, int}
# mode——表示填充的方式(取值:str字符串或用户提供的函数),总共有11种填充模式;
# 返回值:数组
填充方式详解
‘constant’——表示连续填充相同的值,每个轴可以分别指定填充值,constant_values=(x, y)时前面用x填充,后面用y填充,缺省值填充0
‘edge’——表示用边缘值填充
‘linear_ramp’——表示用边缘递减的方式填充
‘maximum’——表示最大值填充
‘mean’——表示均值填充
‘median’——表示中位数填充
‘minimum’——表示最小值填充
‘reflect’——表示对称填充
‘symmetric’——表示对称填充
‘wrap’——表示用原数组后面的值填充前面,前面的值填充后面
参考博客,讲的非常好!!!
tqdm
源自阿拉伯语 taqaddum (تقدّم) ,意思是进程( “progress”),也是西班牙语中 “I love you so much” (te quiero demasiado)的缩写,听着就浪漫~。
该模块的作用就是使循环(loop)过程展示一个进度条,能够通过装饰tqdm(iterable)任何可迭代的对象,比如列表(list)。
进度条 tqdm 库比较热门,声称比老版的 python-progressbar 库的单次响应时间提高了 10 倍以上。
其实进度条的原理十分的简单,无非就是在 shell 中不断重写当前输出。
Example1:
from tqdm import tqdm
for i in tqdm(range(100000000)):
...
from tqdm import tqdm
from time import sleep
text = ""
for char in tqdm(["a", "b", "c", "d"]):
sleep(0.25)
text = text + char
Example3:
from tqdm import tqdm
pbar = tqdm(range(300))#进度条
for i in pbar:
err = 'abc'
pbar.set_description("Reconstruction loss: %s" %(err))
iterable=None,
desc=None, 传入str类型,作为进度条标题(类似于说明)description
total=None, 预期的迭代次数
leave=True,
file=None,
ncols=None, 可以自定义进度条的总长度
mininterval=0.1, 最小的更新间隔
maxinterval=10.0, 最大更新间隔miniters=None, ascii=None, unit='it',unit_scale=False, dynamic_ncols=False, smoothing=0.3,bar_format=None, initial=0, position=None, postfix 以字典形式传入 详细信息 例如 速度= 10,
Example4:
from tqdm import tqdm
dict = {"a":123,"b":456}
for i in tqdm(range(10),total=10,desc = "WSX",ncols = 100,postfix = dict,mininterval = 0.3):
pass
Example5:
from tqdm import trange
from random import random, randint
from time import sleep
with trange(100) as t:
for i in t:
# Description will be displayed on the left
t.set_description('下载速度 %i' % i)
# Postfix will be displayed on the right,
# formatted automatically based on argument's datatype
t.set_postfix(loss=random(), gen=randint(1, 999), str='详细信息',
lst=[1, 2])
sleep(0.1)
参考博客
参考博客