常见图像处理的任务
图像定位
图像定位网络架构
Oxford-IIIT数据集
代码
import tensorflow as tf
import matplotlib.pyplot as plt
%matplotlib inline
from lxml import etree
import numpy as np
import glob
from matplotlib.patches import Rectangle
import os
gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
tf.config.experimental.set_virtual_device_configuration(gpus[0],[tf.config.experimental.VirtualDeviceConfiguration(memory_limit=2000)])
gpu_ok = tf.test.is_gpu_available()
print("tf version:", tf.__version__)
print("use GPU", gpu_ok) # 判断是否使用gpu进行训练
图像定位示例
# 读取一张图片
img = tf.io.read_file("F:/py/ziliao/数据集/图片定位与分割数据集/images/Abyssinian_1.jpg")
img = tf.image.decode_jpeg(img)# 解码
img.shape
plt.imshow(img)
# 读取头部位置轴的文件
xml = open("F:/py/ziliao/数据集/图片定位与分割数据集/annotations/xmls/Abyssinian_1.xml").read()
sel = etree.HTML(xml)
# 页面解析 取出宽度和高度
width = int(sel.xpath('//size/width/text()')[0])
height = int(sel.xpath('//size/height/text()')[0])
# 取出原定义好的头部位置值
xmin = int(sel.xpath('//bndbox/xmin/text()')[0])
xmax = int(sel.xpath('//bndbox/xmax/text()')[0])
ymin = int(sel.xpath('//bndbox/ymin/text()')[0])
ymax = int(sel.xpath('//bndbox/ymax/text()')[0])
print((width,height),(xmin,xmax,ymin,ymax))
# 绘制矩形框
plt.imshow(img)
rect = Rectangle((xmin,ymin),(xmax-xmin),(ymax-ymin),fill = False,color="red")
# 给定 x,y 最小值 宽度=x轴最大值减去x轴最小值
# 高度=y轴最大值减去y轴最小值 fill = False 不填充color="red" 红色框
ax = plt.gca() # 把框花在当前图像上
ax.axes.add_patch(rect) # 添加矩形框
改变图片大小并绘制头像框
# 读取一张图片
img1 = tf.io.read_file("F:/py/ziliao/数据集/图片定位与分割数据集/images/Abyssinian_1.jpg")
img1 = tf.image.decode_jpeg(img1)# 解码
img1.shape
# 页面解析 取出宽度和高度
width = int(sel.xpath('//size/width/text()')[0])
height = int(sel.xpath('//size/height/text()')[0])
# 取出原定义好的头部位置值
xmin = int(sel.xpath('//bndbox/xmin/text()')[0])
xmax = int(sel.xpath('//bndbox/xmax/text()')[0])
ymin = int(sel.xpath('//bndbox/ymin/text()')[0])
ymax = int(sel.xpath('//bndbox/ymax/text()')[0])
print((width,height),(xmin,xmax,ymin,ymax))
# 因图像大小不一 所以我们需要对图像进行变形
img1 = tf.image.resize(img1,[224,224]) #改变形状
img1 = img1/255 # 归一化
plt.imshow(img1) # 绘制变形后的图像
# 因图像大小改变了,所以需要对头部定位数据进行比值变化
# 根据最初图片的高,宽,及 x轴和y轴 最大最小值 及改变后图片的像素值进行比例计算
xmin = (xmin/width)*224
ymin = (ymin/height)*224
xmax = (xmax/width)*224
ymax = (ymax/height)*224
# 绘制矩形框
plt.imshow(img1)
rect = Rectangle((xmin,ymin),(xmax-xmin),(ymax-ymin),fill = False,color="red")
# 给定 x,y 最小值 宽度=x轴最大值减去x轴最小值
# 高度=y轴最大值减去y轴最小值 fill = False 不填充color="red" 红色框
ax = plt.gca() # 把框花在当前图像上
ax.axes.add_patch(rect) # 添加矩形框
创建输入管道
# 读取该路径下的所有jpg后缀的文件
images = glob.glob("F:/py/ziliao/数据集/图片定位与分割数据集/images/*.jpg")
len(images)
images[:5]
# 获取头部目标值
xmls = glob.glob("F:/py/ziliao/数据集/图片定位与分割数据集/annotations/xmls/*.xml")
len(xmls)
# 因为定位好的头部数据只有3686份 ,目标值和图像名字是对应的 使用目标值名字到图片路径提取出对应的图像
xmls[-5:]
names = [x.split("\")[-1].split(".")[-2] for x in xmls] # 通过切割提取出名称
# 对images中所有图片路径进行迭代 如果分割后的路径在names中存在就保留
imgs_train = [img for img in images if img.split("\")[-1].split(".")[-2] in names]
len(imgs_train)
imgs_train[-5:]
imgs_train.sort(key=lambda x:x.split("\")[-1].split(".")[-2]) # 排序防止文件不对应
xmls.sort(key=lambda x:x.split("\")[-1].split(".")[-2])
def to_labels(path):
xml = open("{}".format(path)).read()
sel = etree.HTML(xml)
# 页面解析 取出宽度和高度
width = int(sel.xpath('//size/width/text()')[0])
height = int(sel.xpath('//size/height/text()')[0])
# 取出原定义好的头部位置值
xmin = int(sel.xpath('//bndbox/xmin/text()')[0])
xmax = int(sel.xpath('//bndbox/xmax/text()')[0])
ymin = int(sel.xpath('//bndbox/ymin/text()')[0])
ymax = int(sel.xpath('//bndbox/ymax/text()')[0])
return [xmin/width,ymin/height,xmax/width,ymax/height]
labels = [to_labels(path) for path in xmls]
out1,out2,out3,out4 = list(zip(*labels))
out1[0],out2[0],out3[0],out4[0]
out1 = np.array(out1)
out2 = np.array(out2)
out3 = np.array(out3)
out4 = np.array(out4)
# 创建label的数据集
label_dataset = tf.data.Dataset.from_tensor_slices((out1,out2,out3,out4))
def load_image(path):
img = tf.io.read_file(path)
img = tf.image.decode_jpeg(img,channels=3)
img = tf.image.resize(img,[224,224])
img = img/127.5 - 1 # 图片像素范围是0-255 我们用255的一半在减去1 归一化到0-1之间
return img
image_dataset = tf.data.Dataset.from_tensor_slices(imgs_train)
image_dataset = image_dataset.map(load_image)
dataset = tf.data.Dataset.zip((image_dataset,label_dataset)) # 合并数据
dataset = dataset.repeat().shuffle(len(imgs_train)).batch(32)
# 取出一张图片 一份label 进行头像框绘制
for img,labels in dataset.take(1):
plt.imshow(tf.keras.preprocessing.image.array_to_img(img[0]))
out1,out2,out3,out4 = labels
xmin,ymin,xmax,ymax = out1[0].numpy()*224,out2[0].numpy()*224,out3[0].numpy()*224,out4[0].numpy()*224
rect = Rectangle((xmin,ymin),(xmax-xmin),(ymax-ymin),fill = False,color="red")
ax = plt.gca() # 把框画在当前图像上
ax.axes.add_patch(rect) # 添加矩形框
plt.show()
# 划分数据集
test_count = int(len(imgs_train)*0.2)
train_count = len(imgs_train)-test_count
test_count,train_count
dataset_train =dataset.skip(test_count)
dataset_test = dataset.take(test_count)
创建图像定位的模型
xception = tf.keras.applications.Xception(weights="imagenet",
include_top = False,
input_shape=(224,224,3))
inputs = tf.keras.layers.Input(shape=(224,224,3))
x = xception(inputs)
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x = tf.keras.layers.Dense(2048,activation = "relu")(x)
x = tf.keras.layers.Dense(256,activation="relu")(x)
out1 = tf.keras.layers.Dense(1)(x)
out2 = tf.keras.layers.Dense(1)(x)
out3 = tf.keras.layers.Dense(1)(x)
out4 = tf.keras.layers.Dense(1)(x)
prediction = [out1,out2,out3,out4]
model = tf.keras.models.Model(inputs=inputs,outputs=prediction)
# 编译模型
model.compile(tf.keras.optimizers.Adam(learning_rate=0.0001),
loss="mse",
metrics=["mae"]
)
# 训练步数
EPOCHS = 20
BATCH_SIZE = 4
STEPS_PER_EPOCH = train_count//BATCH_SIZE
VALIDATION_STEPS = test_count//BATCH_SIZE
# 训练
history = model.fit(dataset_train,
epochs=EPOCHS,
steps_per_epoch=STEPS_PER_EPOCH,
validation_steps=VALIDATION_STEPS,
validation_data=dataset_test
)
# 保存模型:此方法保存以下所有内容:
# 1.权重值 2.模型配置(架构) 3.优化器配置
model.save("./save/txfg.h5")
new_model = tf.keras.models.load_model("./save/txfg.h5")
# 预测结果 (因显存不够只训练了5次所以误差较大)
plt.figure(figsize=(8,24))
for img,_ in dataset_test.take(1):
out1,out2,out3,out4 = new_model.predict(img)
for i in range(3):
plt.subplot(3,1,i+1)
plt.imshow(tf.keras.preprocessing.image.array_to_img(img[i]))
xmin,ymin,xmax,ymax = out1[i]*224,out2[i]*224,out3[i]*224,out4[i]*224
rect = Rectangle((xmin,ymin),(xmax-xmin),(ymax-ymin),fill = False,color="red")
ax = plt.gca() # 把框画在当前图像上
ax.axes.add_patch(rect) # 添加矩形框
图像定位优化
图像定位的应用
图运算模式
我们只需要在最后一个函数上添加 @tf.function 这样构成了一个图运算就会提高读取图片的效率
GPU的使用与分配
获得当前主机上运算设备列表
列出当前设备的所有gpu,gpus[0:2]表示只对前两块可见
显存使用策略