卷积核flip+transpose+cv.imread+enumerate+np.pad+tqdm

卷积核翻转方法:

为什么卷积核要翻转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

参考博客

numpy数组transpose

图片一般读进来是(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)格式,并返回

cv2.imread()和cv2.cvtColor() 的使用

  1. cv2.imread()接口读图像,读进来直接是BGR 格式数据格式在 0~255
    需要特别注意的是图片读出来的格式是BGR,不是我们最常见的RGB格式,颜色肯定有区别。
  2. cv2.cvtColor(img, pattern) 是颜色空间转换函数,img是需要转换的图片,pattern是转换成何种格式。
    cv2.COLOR_BGR2RGB 将BGR格式转换成RGB格式
    cv2.COLOR_BGR2GRAY 将BGR格式转换成灰度图片
    卷积核flip+transpose+cv.imread+enumerate+np.pad+tqdm_第1张图片
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),单通道即可判断。
卷积核flip+transpose+cv.imread+enumerate+np.pad+tqdm_第2张图片

参考博客
参考博客

高斯滤波核的大小与 σ \sigma σ(标准差)之间的关系

这里记高斯核的大小为 f , f, f, f i l t e r filter filter的意思
通常取 f = 3 σ + 1 f = 3\sigma +1 f=3σ+1
理由如下:
3 σ \sigma σ的距离大概包含了99%的信息,如下图所示
卷积核flip+transpose+cv.imread+enumerate+np.pad+tqdm_第3张图片

为什么高斯核叫平滑滤波?

因为高斯平滑为加权平滑

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,x2xn)=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 xN(μ,σ2),σi0
多维正态分布的最终形式为:
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ρ2 1exp(2(1ρ2)1[σ12(xμ1)22ρ2σ1σ2(xμ1)(yμ2)+σ22(yμ2)2])=(2π )2σ1σ21ρ2 1exp(2(1ρ2)1[σ12(xμ1)22ρ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}

参考博客

python: enumerate()函数

enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中
语法:

enumerate(sequence, [start=0])
# sequence -- 一个序列、迭代器或其他支持迭代对象。
# start -- 下标起始位置的值。
# 返回 enumerate(枚举) 对象

卷积核flip+transpose+cv.imread+enumerate+np.pad+tqdm_第4张图片
参考博客

python: np.pad() 函数的用法

在卷积神经网络中,为了避免因为卷积运算导致输出图像缩小和图像边缘信息丢失,常常采用图像边缘填充技术,即在图像四周边缘填充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’——表示用原数组后面的值填充前面,前面的值填充后面

参考博客,讲的非常好!!!

python中tqdm(进度条模块) 详细用法及参数解释

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)):
    ...

卷积核flip+transpose+cv.imread+enumerate+np.pad+tqdm_第5张图片
Example2:

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)

在这里插入图片描述
参考博客
参考博客

你可能感兴趣的:(1024程序员节)