TensorFlow——图像定位与分割

常见图像处理的任务

  1. 分类(核心基础)
  2. 分类+定位
    知道对象是什么,还要确定对象所处的位置。在对象附近画一个边框。
  3. 语义分割
    对图像中的像素点进行分类,区分图像中每一个像素点。
  4. 目标检测
    回答图片中有什么,在什么位置。用矩形框框住。
  5. 实例分割
    目标检测与语义分割的结合。需要精确到物体的边缘。

图像定位

输出四个数字(x,y,w,h),图像中某一个点的坐标(x,y),以及图像的宽度和高度。
在这里插入图片描述

Oxford-IIIT数据集

在这里插入图片描述
在这里插入图片描述

图像定位示例

图片文件和对应文件信息如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

# 获取一张图片
img = tf.io.read_file('D:/Desktop/数据集/图片定位与分割数据集/images/images/Abyssinian_1.jpg')
# 对图片解码
img = tf.image.decode_jpeg(img)
# 显示图片
plt.imshow(img)

在这里插入图片描述

# 读取xml文件中的内容
xml = open('D:/Desktop/数据集/图片定位与分割数据集/annotations/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])
plt.imshow(img)
# 绘制矩形框,((x,y),h,w)    fill指定是否填充矩形框
rect = Rectangle((xmin,ymin),(xmax-xmin),(ymax-ymin),fill=False,color='red')
# 获取当前图像
ax = plt.gca()
# 添加矩形框
ax.axes.add_patch(rect)

在这里插入图片描述

图像定位与分类实例

对猫狗图像的头部进行定位并显示,并且将图像中的猫和狗进行分类,数据集同上。
保存了训练好的模型、可视化结果、打印了训练过程的log

实例代码:

导入需要使用到的库文件

import tensorflow as tf
import matplotlib.pyplot as plt
from lxml import etree  # 解析xml文件
import numpy as np
import glob
from matplotlib.patches import Rectangle  # 绘制矩形框
from tensorflow.keras.callbacks import CSVLogger

处理输入数据

def process_data():
    '''
    创建输入管道
    :return: 训练数据集和验证数据集
    '''

    #  读取所有的图像
    images = glob.glob(
        "F:\\dataset\\图片定位与分割\\images\\*.jpg")  # images[0] ===> F:\dataset\图片定位与分割\images\Abyssinian_1.jpg
    #  获取图像对应的目标xml文件
    xmls = glob.glob(
        "F:\\dataset\\图片定位与分割\\annotations\\xmls\\*.xml")  # xmls[0] ===> F:\dataset\图片定位与分割\annotations\xmls\Abyssinian_1.xml
    #  获取所有解析文件的名称
    names = [x.split('xmls\\')[1].split('.')[0] for x in xmls]
    #  取出有对应xml文件的图片作为训练集
    imgs_train = [img for img in images if img.split('images\\')[1].split('.')[0] in names]
    #  取出没有对应xml文件的图片作为测试集
    imgs_test = [img for img in images if img.split('images\\')[1].split('.')[0] not in names]
    # 根据文件名称进行排序
    imgs_train.sort(key=lambda x: x.split('images\\')[1].split('.')[0])
    xmls.sort(key=lambda x: x.split('xmls\\')[1].split('.')[0])

    #  获取所有xml文件的中的头部位置信息,位置信息作为图片信息的标签 ===> [xmin, ymin, xmax, ymax]
    site_labels = [xml_to_sitelabels(path) for path in xmls]
    #  将获取到的标签分为四个单独的列表 ===> zip(*)是zip的逆操作
    xmins, ymins, xmaxs, ymaxs = list(zip(*site_labels))
    #  将xmins等转为array
    xmins = np.array(xmins)
    ymins = np.array(ymins)
    xmaxs = np.array(xmaxs)
    ymaxs = np.array(ymaxs)
    #  获取所有的分类标签cat ===> 1,dog ===> 0
    class_labels = [xml_to_classlabels(path) for path in xmls]
    #  创建标签数据集,包括定位标签和分类标签
    label_dataset = tf.data.Dataset.from_tensor_slices(((xmins, ymins, xmaxs, ymaxs), class_labels))

    #  创建图片数据集
    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.shuffle(len(dataset))
    # 将dataset数据集中20%拿出来做验证集,80%做训练集
    train_size = int(len(dataset) * 0.8)
    val_size = len(dataset) - train_size
    train_dataset = dataset.skip(val_size)
    val_dataset = dataset.take(val_size)
    #  对train_dataset和val_dataset做预处理
    train_dataset = train_dataset.repeat().shuffle(len(train_dataset)).batch(32)
    val_dataset = val_dataset.batch(32)
    return train_dataset, val_dataset, train_size

从xml文件中解析定位信息,生成定位信息标签

def xml_to_sitelabels(path):
    '''
    解析xml文件中的信息,将xml中标记的头部位置的信息处理后返回
    :param path: xml文件存储的路径
    :return: xmin,ymin,xmax,ymax与图像尺寸的比值
    '''

    # 读取xml文件
    xml = open(path).read()
    #  创建一个选择器
    sel = etree.HTML(xml)
    #  解析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]

从xml文件中解析类别信息,生成分类信息标签

def xml_to_classlabels(path):
    '''
    解析xml文件获取所有的分类标签
    :param path: xml文件存储的路径
    :return: 分类标签编码 cat ===> 1,dog ===> 0
    '''
    # 读取xml文件
    xml = open(path).read()
    #  创建一个选择器
    sel = etree.HTML(xml)
    #  解析xml文件中的图片分类数据
    class_label = sel.xpath('//object/name/text()')[0]
    #  对分类标签进行编码 cat ===> 1,dog ===> 0
    return int(class_label == 'cat')

图片解码及预处理

def load_image(path):
    '''
    加载图片数据
    :param path: 图片存储的路径
    :return: 处理过的图片
    '''

    img = tf.io.read_file(path)
    img = tf.image.decode_jpeg(img, channels=3)
    img = tf.image.resize(img, (224, 224))
    #  归一化到-1到1之间
    img = img / 127.5 - 1
    return img

显示图像以及定位信息

def show(dataset, num):
    '''
    显示图片以及定位效果
    :param dataset: 数据集
    :param num: 需要显示的图片数量
    '''

    for imgs, labels in dataset.take(num):
        for i in range(num):
            # 显示图片 ===> 需要将tensor array对象转换为image
            plt.imshow(tf.keras.preprocessing.image.array_to_img(imgs[i]))
            xmin, ymin, xmax, ymax = np.array(labels[0][0])[i], np.array(labels[0][1])[i], np.array(labels[0][2])[i], \
                                     np.array(labels[0][3])[i]
        #  按照图片尺寸获取对应比例的xmin, ymin, xmax, ymax
        xmin, ymin, xmax, ymax = xmin * 224, ymin * 224, xmax * 224, ymax * 224
        # 绘制矩形框((x,y),h,w)  fill ===> 指定是否填充矩形框
        rect = Rectangle((xmin, ymin), (xmax - xmin), (ymax - ymin), fill=False, color='red')
        # 获取当前图像
        ax = plt.gca()
        # 给当前图像添加矩形框
        ax.axes.add_patch(rect)
        plt.show()

创建图像定位与分类模型

def createModel():
    '''
    创建图像定位模型
    :return: 创建好的模型
    '''

    #  使用预训练网络
    xception = tf.keras.applications.Xception(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
    #  将预训练网络设置为不可训练
    xception.trainable = False
    #  添加自定义网络层
    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)
    x1 = tf.keras.layers.Dense(256, activation='relu')(x)
    #  回归
    xmins = tf.keras.layers.Dense(1)(x1)
    ymins = tf.keras.layers.Dense(1)(x1)
    xmaxs = tf.keras.layers.Dense(1)(x1)
    ymaxs = tf.keras.layers.Dense(1)(x1)
    prediction_sites = [xmins, ymins, xmaxs, ymaxs]
    x2 = tf.keras.layers.Dense(256, activation='relu')(x)
    prediction_classes = tf.keras.layers.Dense(1, activation='sigmoid', name='class')(x2)
    model = tf.keras.models.Model(inputs=inputs, outputs=[prediction_sites, prediction_classes])
    model.summary()
    return model

对模型进行配置和编译

def train(model, train_dataset, train_size, val_dataset, epochs, BATCH_SIZE):
    '''
    配置、编译模型
    :param model: 模型
    :param train_dataset: 训练数据集
    :param val_dataset: 验证数据集
    :param epochs: 训练次数
    :return: 训练结果
    '''
    #  mse ===> 回归问题常用损失函数   mae ===> 绝对损失计算
    model.compile(tf.keras.optimizers.Adam(learning_rate=0.0001),
                  loss={'dense_2': 'mse', 'dense_3': 'mse', 'dense_4': 'mse', 'dense_5': 'mse',
                        'class': 'binary_crossentropy'},
                  metrics=['mae', 'acc'])
    #  保存训练结果
    loggger = CSVLogger('training.log', append=False)
    train_steps = train_size // BATCH_SIZE
    val_steps = len(val_dataset) // BATCH_SIZE
    history = model.fit(train_dataset, epochs=epochs, steps_per_epoch=train_steps, validation_data=val_dataset,
                        validation_steps=val_steps, callbacks=loggger)
    #  保存模型
    model.save('site_and_class_model.h5')
    return history

可视化模型训练结果

def showHistory(history):
    '''
    绘图显示模型训练结果
    :param history: 模型训练结果
    '''
    loss = history.history['loss']
    print(history.history.keys())
    class_acc = history.history['class_acc']
    epochs = range(EPOCHS)
    plt.figure()
    plt.plot(epochs, loss, 'r', label='Training loss')
    plt.plot(epochs, class_acc, 'b', label='Training class_acc')
    plt.title('Training and validation Loss and Class_acc')
    plt.xlabel('Epoch')
    plt.ylabel('Loss and Class_acc Value')
    plt.legend()
    plt.savefig('loss_and_acc.png')
    plt.show()

使用训练好保存的模型进行预测

def modelPredict(dataset, num):
    '''
    使用保存的模型进行预测
    :param dataset: 需要预测的数据集
    :param num: 预测的数量
    '''
    '''
    使用保存的模型进行预测
    :param dataset: 需要预测的数据集
    '''
    #  加载保存好的模型
    model = tf.keras.models.load_model('site_and_class_model.h5')
    #  创建一张画布
    for img, _ in dataset.take(1):
        pre = model.predict(img)
        for i in range(num):
            plt.imshow(tf.keras.preprocessing.image.array_to_img(img[i]))
            xmin, ymin, xmax, ymax = pre[0][0][i] * 224, pre[0][1][i] * 224, pre[0][2][i] * 224, pre[0][3][i] * 224
            # 绘制矩形框((x,y),h,w)  fill ===> 指定是否填充矩形框
            rect = Rectangle((xmin, ymin), (xmax - xmin), (ymax - ymin), fill=False, color='red')
            # 获取当前图像
            ax = plt.gca()
            # 给当前图像添加矩形框
            ax.axes.add_patch(rect)
            if pre[1][i] > 0.5:
                # 给当前图像添加title
                plt.title('cat')
            else:
                plt.title('dog')
            plt.show()

主方法

if __name__ == '__main__':
    #  获取训练数据集和验证数据集
    train_dataset, val_dataset, train_size = process_data()
    EPOCHS = 100
    BATCH_SIZE = 32
    # 显示指定数量的图片
    show(train_dataset, 3)
    #  创建图像定位模型
    model = createModel()
    #  模型配置和训练
    history = train(model, train_dataset, train_size, val_dataset, EPOCHS, BATCH_SIZE)
    #  绘制模型训练结果
    showHistory(history)
    #  使用保存好的模型进行预测
    modelPredict(train_dataset, 32)

实例预测效果:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

图像定位的优化

预测图像位置本质上是一个回归问题,直接回归出位置,有两个缺点:

  1. 回归位置不精确
  2. 泛化能力不好
  3. 目前算法只能预测单个实例

优化

  1. 先大后小:
    先在整张图片预测出关键点,然后再再预测出的关键点周边,进行二次预测。
  2. 滑动窗口的方式:
    用一个小的窗口在图片上滑动,每一次做两个预测:(1)是否有关键点(2)关键点位置。
  3. 针对不定个数的预测问题:
    可以先检测多个对象,再在多个对象上分别回归出位置
  4. 尝试使用全卷积网络,去掉全链接层,变回归为分类问题
  5. 自己去探索别的网络

图像定位的评价

使用IOU来评价图像定位的精度IOU的全称为交并比(Intersection over Union)。
IOU计算的是“预测的边框”和“真实的边框”的交集和并集的比值。
在这里插入图片描述
IOU的取值范围为[0,1]

图形定位的应用

在这里插入图片描述
在这里插入图片描述

该实例代码和用到的数据集已全部上传至GitHub 代码和数据集.存放在pycharm projects文件夹中。

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是安装tensorflow-gpu的步骤: 1. 安装CUDA Toolkit和cuDNN库 TensorFlow GPU版本需要CUDA Toolkit和cuDNN库的支持。请根据您的系统环境下载适合的版本。推荐使用CUDA 10.0和cuDNN 7.4.2。下载链接如下: - CUDA Toolkit 10.0:https://developer.nvidia.com/cuda-10.0-download-archive - cuDNN 7.4.2:https://developer.nvidia.com/cudnn 安装CUDA Toolkit和cuDNN库时,请注意设置环境变量,以便TensorFlow能够找到它们。 2. 创建conda虚拟环境 您可以使用conda创建一个虚拟环境来安装和管理TensorFlow GPU版本以及其他软件包。打开终端并运行以下命令: ```bash conda create -n tensorflow-gpu python=3.7 ``` 这个命令将创建一个名为“tensorflow-gpu”的conda虚拟环境,其中Python的版本是3.7。 3. 激活conda虚拟环境 使用以下命令激活conda虚拟环境: ```bash conda activate tensorflow-gpu ``` 4. 安装TensorFlow GPU版本 通过以下命令安装TensorFlow GPU版本: ```bash pip install tensorflow-gpu==2.0.0 ``` 这个命令将安装TensorFlow 2.0.0 GPU版本。 5. 验证安装 要验证TensorFlow GPU是否正确安装,请使用以下Python代码: ```python import tensorflow as tf print(tf.test.is_gpu_available()) ``` 如果输出的结果为True,则表示TensorFlow GPU版本安装正确。 提示:安装TensorFlow GPU版本之前,请确保您的GPU支持CUDA。您可以在以下链接中查找支持CUDA的GPU:https://developer.nvidia.com/cuda-gpus

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值