文章目录
- 一、卷积介绍
- 1、origination:
- 2、significance:
- 3、卷积计算
- a-、滤波器(卷积核)
- a、卷积例子
- b、卷积之padding填充
- c、步幅
- e、注意
- f、整体理解
- 二、图像处理基础
- 1、读取图像
- 2、撒点椒盐
- 3、图像二值化
- 4、分量提取
- 5、灰度图片
- 6、图像卷积处理之numpy
- 7、图像卷积处理之tensorflow
本文主要从卷积, 图像, 图像的卷积处理, 卷积神经网络CNN的构建三部分,从理论到代码应用
使用python3.6编译器, jupyter编辑器
未完待续…
一、卷积介绍
1、origination:
一个面积不变的长方形,底边被挤的窄窄的,高度被挤的高高的,在数学中它可以被挤到无限高,但即使它无限瘦、无限高、但它仍然保持面积不变;为了证实它的存在,可以对它进行积分。
2、significance:
- 意义1
假设system1, 时刻t输入为x(t), 输出为y(t), 系统响应时间为h(t), 按道理输入输出关系是y(y)=h(t)*x(t); however, 系统输出不仅与系统t时刻相关, 还与t时刻之前响应相关, 所以t时刻的输出应该为t时刻之前系统响应函数在各个时刻响应的叠加,这就是卷积,用数学公式表示就是y(s)=∫x(t)h(s-t)dt - 物理意义
卷积图像处理方面的应用
用一个模板和一幅图像进行卷积,对于图像上的一个点,让模板的原点和该点重合,然后模板上的点和图像上对应的点相乘,然后各点的积相加,就得到了该点的卷积值。对图像上的每个点都这样处理。由于大多数模板都是对称的,所以模板不旋转。卷积是一种积分运算,用来求两个曲线重叠区域面积。可以看作加权求和,可以用来消除噪声、特征增强。
把一个点的像素值用它周围的点的像素值的加权平均代替。
卷积是一种线性运算,图像处理中常见的mask运算都是卷积,广泛应用于图像滤波。
卷积在数据处理中用来平滑,卷积有平滑效应和展宽效应.
参考:卷积的本质及物理意义(全面理解卷积)
3、卷积计算
为了更好的理解, 直接上例子
a-、滤波器(卷积核)
a、卷积例子
b、卷积之padding填充
填充方法有:
补零填充
边界复制填充, 镜像填充, 块填充
c、步幅
### d、计算增加参数后, 卷积输出shape
e、注意
f、整体理解
1、读取图像
import numpy as np
import matplotlib.pyplot as plt
import sys,os
sys.path.append(os.pardir)
%matplotlib inline
img = np.array(plt.imread("../data/刘亦菲.jpg")) # 将图像格式转化np.array格式,方便后续处理
plt.figure("刘大姐")
plt.imshow(img) # 函数负责对图像进行处理,并显示其格式,但是不能显示
plt.axis("off")
plt.show()
print( img.shape )
print( img.dtype )
print( img.size )
print( type(img) )
print(img[0,0]) # 因为是RGB三通道
(1200, 1920, 3)
uint8
6912000
<class 'numpy.ndarray'>
[ 95 96 124]
2、撒点椒盐
#随机生成5000个椒盐
rows,cols,dims=img.shape
for i in range(5000):
x=np.random.randint(0,rows) # 在0-rows之间随便取值
y=np.random.randint(0,cols) #
img[x,y,:]=255 # 将这个随机点设置为白点, 即椒盐
plt.figure("beauty")
plt.imshow(img)
plt.axis('off')
plt.show()
3、图像二值化
# 图像二值化
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
img = np.array(Image.open("../data/刘亦菲.jpg").convert('L'))
rows, cols = img.shape
for i in range(rows):
for j in range(cols):
if (img[i, j] <= 128):
img[i, j] = 0
else:
img[i, j] = 1
plt.figure("Mona Lisa")
plt.imshow(img, cmap='gray')
plt.axis('off')
plt.show()
4、分量提取
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
img = np.array(plt.imread("../data/刘亦菲.jpg"))
plt.imshow(img[:, :, 0], cmap="gray") #L 分量转化为灰度图
plt.show()
plt.imshow(img[:, :, 1], cmap="gray") #G 分量转化为灰度图
plt.show()
plt.imshow(img[:, :, 1], ) # 只显示G 分量
plt.show()
5、灰度图片
from PIL import Image
img = np.array([1]) # 读取图片,并转换为灰度图片
img_1 = Image.open("../data/刘亦菲.jpg").convert('1') # 非黑即白
img = np.array(Image.open("../data/刘亦菲.jpg").convert('L')) # 0黑255白,其他数字灰度不同
plt.imshow(img_1, cmap="gray") # 图片只显示像素点为0或者255的值
plt.show()
plt.imshow(img, cmap="gray")
plt.show()
6、图像卷积处理之numpy
- 本部分的图像卷积处理使用的是科学计算包numpy , 利用numpy的广播功能, 能够很简单的进行矩阵运。
- 本部分的图像卷积, 是直接将图像的每一个像素点的三个通道的像素都进行了卷积处理,然后显示
# 图像卷积运算
import numpy as np
import matplotlib.pyplot as plt
import sys
sys.path.append("../")
%matplotlib inline
img = np.array(plt.imread("../data/刘亦菲.jpg"))
# 构建输出矩阵形状, 使用0填充,
def generate_dst(img, kernel, stride=1, padding=0): #默认步幅=1, 填充为0
m = (img.shape[0] + 2*padding - kernel.shape[0] + stride)/stride # 高
n = (img.shape[1] + 2*padding - kernel.shape[1] + stride)/stride # 长
rgb_channel = img.shape[2] # RGB三通道
print("新构建的图片形状%0.3f,%0.3f,%0.3f"%(m,n,rgb_channel))
return np.zeros((int(m),int(n),int(rgb_channel)),)
# 单个卷积核的运算
def div_convolution(img_block,kernel):
_img = np.array(img_block).flatten() #转化为一维
_kernel = np.array(kernel).flatten()
# return np.mean(_img*_kernel) #
return np.sum(_img*_kernel) # 正常的卷积运算是直接加和,并不进行均值计算
# 将图片按照convolution变换, 注意这里还没有对最终结果进行归一化
def convolution2dst(img,dst,kernel):
for i in range(dst.shape[0]):
for j in range(dst.shape[1]):
for k in range(dst.shape[2]): #通道
dst[i,j,k] = div_convolution(img[i:i+kernel.shape[0],
j:j+kernel.shape[1],k], # 与kernel一致的矩阵
kernel)
# 将图片归一化到256之间
def img2normalization_256(img_convolution):
_img = img_convolution.flatten()
_max = np.max(_img)
_min = np.min(_img)
_img = (_img-_min)*255/(_max-_min)
_img = np.array(_img, dtype="int64") # 将所有数据转化为int型
img_convolution_normalization = _img.reshape((img_convolution.shape[0],
img_convolution.shape[1],
img_convolution.shape[2]))
return img_convolution_normalization
def convolution(img,kernel,is_normalization=False):
dst = generate_dst(img,kernel)
convolution2dst(img,dst,kernel)
if not is_normalization:
return dst
else:
new_img = img2normalization_256(dst)
return new_img
img = np.array(plt.imread("../data/刘亦菲.jpg"))
test_kernel = np.array([[-1, -1, -1],
[-1, 9, -1],
[-1, -1, -1]])
img_convolution = convolution(img,test_kernel, True)
# 显示直接卷积后的结果
plt.figure("刘大姐")
plt.imshow(img_convolution)
plt.axis("off")
plt.show()
print(img_convolution[0,0])
# 显示处理完的图像
img_convolution = img2normalization_256(img_convolution)
plt.figure("刘大姐")
plt.imshow(img_convolution)
plt.axis("off")
plt.show()
7、图像卷积处理之tensorflow
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
%matplotlib inline
'''
tf.nn.conv2d(input=, # 输入图像 [batch, height, width, channels]
filter=, # 卷积核,
strides=, # 步幅 一维向量,长度为4
padding, # 扩展 SAME表示在扫描的时候,如果遇到卷积核比剩下的元素要大时,这个时候需要补0进行最后一次的行扫描或者列扫描
use_cudnn # 启用cudnn加速
name) # 执行该操作name
'''
img = np.array([1]) # 读取图片,并转换为灰度图片
Image.open("../data/刘亦菲.jpg").convert('1') # 非黑即白
img = np.array(Image.open("../data/刘亦菲.jpg").convert('L')) # 0黑255白,其他数字灰度不同
img_full = np.reshape(img, [1, img.shape[0], img.shape[1], 1])
print(img_full.shape) # (1, 1200, 1920, 1)
#创建占位
input_full = tf.Variable(tf.constant(1.0, shape=img_full.shape))
# input_full = tf.Variable(img_R_full, dtype=tf.float32) # 可以直接输入
# 创建卷积核
filter_kernel = tf.Variable(tf.constant([#[1.0, 2, 1], [0, 0, 0], [-1, -2, -1] # 水平边缘滤波器
#[0, -4, 0], [-4, 16, -4], [0, -4, 0] # 整体边缘滤波器
# [1, 0, -1], [2, 0, -2], [1, 0, -1] # 垂直边缘滤波器
[-1,-1,-1],[-1,9,-1],[-1,-1,-1]
],
shape = [3,3,1, 1], dtype="float32")) # 3卷积核格式为3*3 输入通道1, 输出通道1
op = tf.nn.conv2d(input_full, filter=filter_kernel, strides=[1,1,1,1], padding="VALID") # SAME是自动填充, 这里选择不自动填充的VALID
o=tf.cast(((op-tf.reduce_min(op))/(tf.reduce_max(op)-tf.reduce_min(op)) ) *255 ,tf.uint8) # 归一化, 因为经过卷积后像素会有不在0-255范围内的
with tf.Session() as sess:
sess.run(tf.global_variables_initializer() )
conv_img = sess.run(o, feed_dict={ input_full:img_full})
print(conv_img.shape)
conv_img = conv_img.reshape([conv_img.shape[1], conv_img.shape[2]])
plt.imshow(conv_img, cmap="gray") # 显示图片
plt.axis('off') # 不显示坐标轴
plt.show()
(1, 1200, 1920, 1)
(1, 1198, 1918, 1)