- FCN简介
FCN实际上就是利用CNN底层反卷积上采样得到图像轮廓实现实例分割的过程。博客上已经有很多解析整个过程的技术文章。详见[https://blog.csdn.net/qq_36269513/article/details/80420363]。
(https://blog.csdn.net/qq_36269513/article/details/80420363)
- 上采样解析过程如下
- 数据源
随便百度获取猪只图像。利用labelme进行数据处理
实现过程
- 数据预处理
导入相关库
from keras.layers import Conv2D,MaxPool2D,UpSampling2D,Conv2DTranspose,Input,add,MaxPooling2D,concatenate,ZeroPadding2D
from keras.models import Model,Sequential
import os
import numpy as np
import matplotlib.pyplot as plt
import cv2
import sys
import os.path as osp
from PIL import Image
导入数据并padding图像一致尺寸
img_data=[]
label_data=[]
for i in range(1,11):
i = str(i)
img = plt.imread('./voc_data/pig/img'+i+'.png')
label = plt.imread('./voc_data/pig/label'+i+'.png')
img_data.append(np.array(img))
label_data.append(np.array(label))
def padding_data(x,y):
sz = (320, 320)
n_img = x
n_label =y
for i in range(len(x)):
n_img[i] = cv2.resize(x[i], sz, interpolation = cv2.INTER_CUBIC)
n_label[i] = cv2.resize(y[i], sz, interpolation = cv2.INTER_CUBIC)
nor_img = [] # 转换后图像
nor_label = [] # 转换后的标签, 又新建一个 list 是因为这样可以重复运行这个 cell,
# 如果你内存小就不要新建这个 list, 在原来的数据上操作
for i in range(len(n_img)):
# PngImageFile 转换成 np.array
nor_img.append(np.array(n_img[i]))
#nor_img[i] = nor_img[i].astype(np.float32) / 255.0
# 这里没有先把 label_data[i] 转换成 np.array 是因为在读入的时候已经转换过了
nor_label.append(n_label[i])
# 因为标签图像的值就已经是 0 和 1 了, 就不再除以 255
# 后面会讲多分类问题怎么处理
nor_label[i] = nor_label[i].astype(np.float32)
return nor_img,nor_label
FCN32s
FCN32s直接利用最后一层上采样32倍;
channels = 3
std_shape = (320,320,3)
model1 = Sequential()
model1.add(Conv2D(32,(3,3),activation='relu',padding='same',input_shape=std_shape))
model1.add(MaxPool2D(2,2))
model1.add(Conv2D(64,(3,3),activation='relu',padding='same',input_shape=std_shape))
model1.add(MaxPool2D(2,2))
model1.add(Conv2D(128,(3,3),activation='relu',padding='same',input_shape=std_shape))
model1.add(MaxPool2D(2,2))
model1.add(Conv2D(256,(3,3),activation='relu',padding='same',input_shape=std_shape))
model1.add(MaxPool2D(2,2))
model1.add(Conv2D(512,(3,3),activation='relu',padding='same',input_shape=std_shape))
model1.add(MaxPool2D(2,2))
model1.add(UpSampling2D((32,32),interpolation = "nearest"))
model1.add(Conv2D(3,(3,3),activation='sigmoid',padding='same'))
model1.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])
model1.summary()
FCN 32s模型结构
FCN16s
利用倒数第二层上采样16倍;
#FCN_16s
up6 = Conv2DTranspose(256,kernel_size=(3,3),strides=(2,2),padding='same',kernel_initializer='he_normal',name='upsamping_6')(max_pool_5)
_16s = add([max_pool_4,up6])
up7 = UpSampling2D((16,16),interpolation='bilinear',name='upsamping_7')(_16s)
conv_11 = Conv2D(3,(3,3),activation='sigmoid',padding='same',name='conv_11')(up7)
model = Model(img_input,conv_11,name='FCN_16S')
model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])
model.summary()
FCN16s模型结构
FCN8s
利用倒数第三层上采样8倍;
up6 = Conv2DTranspose(256,(3,3),strides=(2,2),padding='same',kernel_initializer='he_normal',name='upsamping_6')(max_pool_5)
_16s = add([max_pool_4,up6])
up_16s = Conv2DTranspose(128,(3,3),strides=(2,2),padding='same',kernel_initializer='he_normal',name='conv2dtranspose_16s')(_16s)
_8s = add([max_pool_3,up_16s])
up7 = UpSampling2D((8,8),interpolation='bilinear',name='upsamping_7')(_8s)
conv_11 = Conv2D(3,(3,3),activation='sigmoid',padding='same',name='conv_11')(up7)
model_8s = Model(img_input,conv_11)
model_8s.compile(loss='binary_crossentropy',metrics=['accuracy'],optimizer='adam')
model_8s.summary()
FCN8s模型结构
**
- 图像结果展现
**
分割好的模型结果展示:对物体标上不同颜色
def plot_(model,i,color_max):
d=model.predict(nor_img)
img_marked = nor_img[i].copy()
img_mask = np.zeros((320,320,3),dtype = np.uint8)
for r in range(img_marked.shape[0]):
for c in range(img_marked.shape[1]):
if d[i][r][c] > color_max: # 阈值
img_marked[r][c] += [3, 0, 0] # 在 img_marked 上标记为红色
# 三个值分别是 RGB 颜色, 值越小越透明
img_mask[r][c] = 255
plt.imshow(img_marked)
plt.show()
plt.imshow(img_mask)
plt.show()
#plt.imshow(nor_label_[i])
plt.show()
#plt.imshow(d[i])
return d[i]
结果
可以看到FCN32s模型取得的结果上色像素成块状,FCN8s结果效果更好。
- 结语
本文训练集数据只有10张图片(电脑无GPU显卡,大量本数据训练不起来),训练单只猪只效果尚可,实际运用远远达不到。