1、绪论
1.1 KerasCV概念
KerasCV是一个模块化计算机视觉组件库,它可与TensorFlow、JAX或PyTorch原生配合使用。这些模型、层、指标、回调等基于Keras Core构建,可以在任何框架中进行训练和序列化,并在另一个框架中重复使用,而无需进行昂贵的迁移。
KerasCV可以理解为Keras API的水平扩展:组件是新的第一方Keras对象,它们过于专业化,无法添加到核心Keras中。这些组件获得与核心Keras API相同级别的完善和向后兼容性保证,并且由Keras团队维护。
KerasCV的API协助执行常见的计算机视觉任务,例如数据增强、分类、对象检测、分割、图像生成等。应用计算机视觉工程师可以利用KerasCV为所有这些常见任务快速组装生产级、最先进的训练和推理管道。
KerasCV主要支持TensorFlow框架,因为它是基于Keras构建的,而Keras是TensorFlow的高级API之一。然而,由于KerasCV的模块化设计,它的一些组件和功能可能也可以与其他兼容Keras的框架(如JAX或某些版本的PyTorch)一起使用,但这需要进一步的验证和确认。
尽管KerasCV主要关注TensorFlow,但它提供的工具和库可以跨多个框架进行迁移和使用,为计算机视觉工程师提供了灵活性和选择性。
KerasCV是一个专注于计算机视觉任务的模块化组件库,它基于Keras构建,可以与TensorFlow、JAX或PyTorch等框架配合使用。以下是KerasCV的一些主要应用场景:
-
图像分类:KerasCV提供了丰富的预训练模型和工具,可以轻松地实现图像分类任务,例如识别照片中的动物、物体等。
-
目标检测:在图像中识别和定位多个对象,如人脸检测、车辆检测等。KerasCV提供了多种目标检测算法和模型,可以帮助用户快速构建高效的目标检测系统。
-
语义分割:将图像分割成多个具有特定语义含义的区域,例如将街道图像分割成道路、建筑、车辆等部分。KerasCV中的语义分割模型可以处理这类任务。
-
图像生成:利用生成对抗网络(GAN)等技术生成逼真的图像。KerasCV中的相关组件可以简化这类模型的构建和训练过程。
-
图像增强:通过对图像进行各种变换和增强操作,提高模型的泛化能力和鲁棒性。KerasCV提供了多种图像增强技术,如随机裁剪、旋转、缩放等。
-
视频处理:虽然KerasCV主要关注静态图像处理,但也可以将其应用于视频处理任务,如视频分类、目标跟踪等。通过处理视频帧,可以实现对视频内容的分析和理解。
-
医学图像处理:在医学领域,KerasCV可以用于处理和分析医学图像,如X光片、CT扫描等。通过构建相应的模型,可以帮助医生更准确地诊断疾病。
-
自动驾驶:在自动驾驶系统中,KerasCV可以用于实现车辆的感知功能,如道路检测、行人检测等。这些功能对于确保车辆的安全行驶至关重要。
1.2 研究KerasCV的意义
研究KerasCV的意义在于深入了解和掌握这个专注于计算机视觉任务的模块化组件库,从而更高效地处理与图像和视频相关的任务。以下是研究KerasCV的具体意义:
- 提高计算机视觉任务的效率:KerasCV提供了丰富的预训练模型和工具,可以大大简化计算机视觉任务的实现过程,减少开发时间,提高工作效率。
- 扩展和定制功能:KerasCV允许用户轻松地添加新的模型或自定义注意力模块,以满足特定任务的需求。这使得研究人员和开发者能够根据自己的需求来定制和优化模型,提高模型的性能和准确性。
- 易于理解和使用:KerasCV的组件都封装在统一的接口中,易于理解和使用。这使得研究人员和开发者能够更快地掌握和使用这个工具,从而更快地推进计算机视觉领域的研究和应用。
- 与主流框架的兼容性:KerasCV可以与TensorFlow、JAX或PyTorch等主流深度学习框架配合使用,这意味着用户可以利用这些框架的强大功能和资源来加速模型的训练和推理过程。
- 持续更新和同步最新研究成果:KerasCV项目保持与最新研究成果同步,持续引入新的模型和改进。这使得研究人员和开发者能够利用最新的技术和算法来改进他们的模型,提高模型的性能和准确性。
- 支持多种应用场景:从图像分类、目标检测、语义分割到图像生成和增强,KerasCV可以应用于各种计算机视觉任务。这使得研究人员和开发者能够利用这个工具来处理各种复杂和多样化的应用场景。
研究KerasCV对于提高计算机视觉任务的效率、扩展和定制功能、易于理解和使用、与主流框架的兼容性、持续更新和同步最新研究成果以及支持多种应用场景等方面都具有重要的意义。
1.3 使用 KerasCV 进行目标检测的概念和应用场景
使用KerasCV进行目标检测涉及在图像中找出所有感兴趣的目标(物体),确定它们的类别和位置。这是计算机视觉领域中的核心问题之一,对于各种应用场景具有重要意义。
1.3.1概念:
目标检测的任务是找出图像或视频帧中的目标物体,这些目标可能是人、车辆、动物或其他任何有特定形状和大小的物体。这通常涉及两个主要步骤:首先是定位,即确定目标物体在图像中的位置(如边界框);其次是分类,即确定该位置上的物体属于哪个类别。目标检测是计算机视觉和数字图像处理的一个热门方向,广泛应用于各种领域。
1.3.2应用场景:
- 机器人导航:机器人需要能够识别和理解其周围环境中的物体,以便进行导航和避障。目标检测可以帮助机器人识别出路径上的障碍物、路标或其他重要物体。
- 智能视频监控:在监控系统中,目标检测可以用于自动检测异常事件,如入侵者、交通事故或火灾等。此外,它还可以用于人数统计、行为分析等任务。
- 工业检测:在制造业中,目标检测可以用于产品质量控制、自动化生产线上的物体识别和分类等任务。
- 航空航天:在航空航天领域,目标检测可以用于卫星图像分析、无人机自主导航和避障等任务。
- 医疗影像分析:在医疗领域,目标检测可以帮助医生自动识别和定位医学影像(如X光片、CT扫描等)中的病变区域,提高诊断效率和准确性。
KerasCV作为一个为计算机视觉任务设计的库,提供了丰富的工具和预训练模型,使得目标检测的实现变得更加简单和高效。通过使用KerasCV,研究人员和开发人员可以更快地构建出高性能的目标检测模型,并应用于各种实际场景中。
2、使用KerasCV进行目标检测
2.1 系统设置
!pip install -q --upgrade keras-cv
!pip install -q --upgrade keras # Upgrade to Keras 3.
import os
os.environ["KERAS_BACKEND"] = "jax" # @param ["tensorflow", "jax", "torch"]
from tensorflow import data as tf_data
import tensorflow_datasets as tfds
import keras
import keras_cv
import numpy as np
from keras_cv import bounding_box
import os
from keras_cv import visualization
import tqdm
2.2 目标检测概念
目标检测是在给定的图像中识别、分类和定位对象的过程。通常,输入是图像,而程序员的标签则是带有可选类别标签的边界框。目标检测可以看作是分类的扩展,但不同于仅为图像提供一个类别标签,需要检测和定位任意数量的类别。
图像通常可以用代码进行如下的描述
image = [height, width, 3]
bounding_boxes = {
"classes": [0], # 0 is an arbitrary class ID representing "cat"
"boxes": [[0.25, 0.4, .15, .1]]
# bounding box is in "rel_xywh" format
# so 0.25 represents the start of the bounding box 25% of
# the way across the image.
# The .15 represents that the width is 15% of the image width.
}
自从 You Only Look Once(简称 YOLO)问世以来,目标检测主要通过深度学习来解决。大多数深度学习架构通过将目标检测问题巧妙地转化为多个小分类问题和多个回归问题的组合来实现这一点。
更具体地说,这是通过在输入图像上生成许多不同形状和大小的锚框(anchor boxes),并为每个锚框分配一个类别标签以及 x、y、宽度和高度偏移量来完成的。模型被训练来预测每个锚框的类别标签,以及被预测为目标的每个锚框的 x、y、宽度和高度偏移量。这些偏移量表示了锚框与实际目标边界框之间的调整量,从而使得模型能够精确地定位和识别图像中的对象。
目标检测是一个技术上复杂的问题,但幸运的是,我们提供了一种可靠的方法来获得出色的结果。这通常涉及使用预训练的深度学习模型,如YOLO、SSD或Faster R-CNN,这些模型已经在大量数据上进行了训练,并学会了如何有效地检测图像中的对象。
2.3使用预训练模型进行目标检测
在KerasCV的目标检测API中,最高级别的API是keras_cv.models。这个API包含了完全预训练的目标检测模型,比如keras_cv.models.YOLOV8Detector。
pretrained_model = keras_cv.models.YOLOV8Detector.from_preset(
"yolo_v8_m_pascalvoc", bounding_box_format="xywh"
)
在目标检测中,bounding_box_format
是一个重要的参数,因为它定义了边界框坐标的表示方式。常见的边界框格式包括:
-
(x_min, y_min, width, height)
: 左上角坐标((x_min, y_min)
)和宽度、高度定义了边界框的位置和大小。这是很多目标检测算法使用的格式,包括 YOLO 系列。 -
(x_min, y_min, x_max, y_max)
: 左上角和右下角的坐标定义了边界框的位置。 -
(center_x, center_y, width, height)
: 边界框的中心点坐标和宽度、高度定义了边界框的位置和大小。 -
归一化坐标: 上述任何格式的坐标都可以被归一化,即坐标值被缩放为相对于图像宽度的比例(对于 x 坐标)和相对于图像高度的比例(对于 y 坐标)。这通常在将坐标传递给深度学习模型之前进行,因为模型通常期望输入在特定范围内(如 0 到 1)。
当你使用 keras_cv.models.YOLOV8Detector
或其他目标检测模型时,确保你了解模型期望的边界框格式,并在预处理和后处理数据时相应地调整它们。
如果你在使用 keras_cv.models.YOLOV8Detector
并且需要设置 bounding_box_format
参数(尽管这个参数在标准的 KerasCV API 中可能不存在,因为它通常是模型内部处理的),你可能需要查阅该模型的特定文档或源代码来了解如何正确地处理和解释边界框坐标。
在实际应用中,你还需要注意后处理步骤,如非极大值抑制(NMS),它用于过滤重叠的边界框并仅保留最自信的预测。这些步骤通常依赖于特定的边界框格式。
bounding_boxes = {
"classes": [num_boxes],
"boxes": [num_boxes, 4]
}
“boxes” 字段在标签字典中的值所采取的格式,xywh
格式指的是边界框由其左上角坐标 (x, y)
和宽度 w
、高度 h
来定义。
因此,一个左上角坐标在 (100, 100)
、宽度为 55
、高度为 70
的边界框在 xywh
格式下会被表示为:
[100, 100, 55, 70]
这里的列表包含了四个元素,分别对应 x 坐标、y 坐标、宽度和高度。在目标检测任务中,这样的边界框表示方式很常见,特别是在 YOLO(You Only Look Once)系列的检测器中。当处理或准备数据集以进行训练或评估时,确保边界框数据以正确的格式提供。
尽管这看起来很简单,但它是KerasCV目标检测API中至关重要的一部分!每个处理边界框的组件都需要一个bounding_box_format
参数。您可以在API文档中关于KerasCV边界框格式的信息。
这是因为边界框没有唯一的正确格式!不同流程中的组件期望不同的格式,因此通过要求指定这个参数,我们确保组件保持可读性、可重用性和清晰性。边界框格式转换错误可能是目标检测流程中最常见的错误类型之一——通过要求这个参数,我们可以减少这些错误(尤其是当代码来自多个来源时)。
接下来,让我们加载一张图像:
filepath = keras.utils.get_file(origin="https://i.imgur.com/gCNcJJI.jpg")
image = keras.utils.load_img(filepath)
image = np.array(image)
visualization.plot_image_gallery(
np.array([image]),
value_range=(0, 255),
rows=1,
cols=1,
scale=5,
)
使用带有ResNet50骨干网的YOLOV8Detector架构时,您需要将图像调整为64的倍数大小。这是为了确保与ResNet中卷积层执行的下采样操作数量相兼容。
如果调整大小的操作改变了输入的纵横比,模型的性能将会显著下降。对于我们正在使用的预训练“yolo_v8_m_pascalvoc”预设,如果使用简单的调整大小操作,pascalvoc/2012评估集上的最终平均精度均值(Mean Average Precision, mAP)会从0.38下降到0.15。
此外,如果您像在分类任务中那样裁剪图像以保持纵横比,您的模型可能会完全错过一些边界框。因此,在运行对象检测模型的推理时,我们建议使用填充以达到所需的大小,同时调整最长边的大小以匹配原始图像的纵横比。
KerasCV使正确的调整大小操作变得简单;只需将pad_to_aspect_ratio=True
传递给keras_cv.layers.Resizing
层即可。
这可以通过一行代码实现:
inference_resizing = keras_cv.layers.Resizing(
640, 640, pad_to_aspect_ratio=True, bounding_box_format="xywh"
)
这也可以作为我们的推理预处理流程来使用:
image_batch = inference_resizing([image])
keras_cv.visualization.plot_bounding_box_gallery()
函数支持一个 class_mapping
参数,用于突出显示每个边界框被分配到的类别。现在,让我们来创建一个类别映射。
class_ids = [
"Aeroplane",
"Bicycle",
"Bird",
"Boat",
"Bottle",
"Bus",
"Car",
"Cat",
"Chair",
"Cow",
"Dining Table",
"Dog",
"Horse",
"Motorbike",
"Person",
"Potted Plant",
"Sheep",
"Sofa",
"Train",
"Tvmonitor",
"Total",
]
class_mapping = dict(zip(range(len(class_ids)), class_ids))
就像任何其他 keras.Model 一样,您可以使用 model.predict() API 来预测边界框。
y_pred = pretrained_model.predict(image_batch)
# y_pred is a bounding box Tensor:
# {"classes": ..., boxes": ...}
visualization.plot_bounding_box_gallery(
image_batch,
value_range=(0, 255),
rows=1,
cols=1,
y_pred=y_pred,
scale=5,
font_scale=0.7,
bounding_box_format="xywh",
class_mapping=class_mapping,
)
为了支持这种简单且直观的推理工作流程,KerasCV 在 YOLOV8Detector 类内部执行了非极大值抑制(Non-Maximum Suppression,NMS)。非极大值抑制是一种传统的计算算法,用于解决模型为同一对象检测多个边界框的问题。
非极大值抑制是一种高度可配置的算法,在大多数情况下,您可能需要自定义模型中非极大值抑制操作的设置。这可以通过覆盖 prediction_decoder
参数来实现。
为了展示这个概念,让我们暂时在我们的 YOLOV8Detector 上禁用非极大值抑制。这可以通过写入 prediction_decoder
属性来完成。
# The following NonMaxSuppression layer is equivalent to disabling the operation
prediction_decoder = keras_cv.layers.NonMaxSuppression(
bounding_box_format="xywh",
from_logits=True,
iou_threshold=1.0,
confidence_threshold=0.0,
)
pretrained_model = keras_cv.models.YOLOV8Detector.from_preset(
"yolo_v8_m_pascalvoc",
bounding_box_format="xywh",
prediction_decoder=prediction_decoder,
)
y_pred = pretrained_model.predict(image_batch)
visualization.plot_bounding_box_gallery(
image_batch,
value_range=(0, 255),
rows=1,
cols=1,
y_pred=y_pred,
scale=5,
font_scale=0.7,
bounding_box_format="xywh",
class_mapping=class_mapping,
)
接下来,让我们根据我们的用例重新配置 keras_cv.layers.NonMaxSuppression
!在这种情况下,我们将把 iou_threshold
调整为 0.2,把 confidence_threshold
调整为 0.7。
提高 confidence_threshold
会使模型仅输出具有较高置信度分数的边界框。iou_threshold
控制了两个边界框之间的交并比(Intersection over Union, IoU)阈值,以便在 IoU 超过该阈值时,其中一个边界框会被剪枝掉。关于这些参数的更多信息,可以在 TensorFlow API 文档中找到。
prediction_decoder = keras_cv.layers.NonMaxSuppression(
bounding_box_format="xywh",
from_logits=True,
# Decrease the required threshold to make predictions get pruned out
iou_threshold=0.2,
# Tune confidence threshold for predictions to pass NMS
confidence_threshold=0.7,
)
pretrained_model = keras_cv.models.YOLOV8Detector.from_preset(
"yolo_v8_m_pascalvoc",
bounding_box_format="xywh",
prediction_decoder=prediction_decoder,
)
y_pred = pretrained_model.predict(image_batch)
visualization.plot_bounding_box_gallery(
image_batch,
value_range=(0, 255),
rows=1,
cols=1,
y_pred=y_pred,
scale=5,
font_scale=0.7,
bounding_box_format="xywh",
class_mapping=class_mapping,
)
2.4 训练自定义的目标检测模型
训练一个自定义的目标检测模型(Train a custom object detection model)指的是使用特定的数据集(通常包含标注的目标边界框)来训练一个深度学习模型,使其能够识别并定位图像或视频中的特定对象。这个训练过程通常涉及到选择或构建一个合适的神经网络架构(如 Faster R-CNN、YOLO、SSD 等),然后使用大量带有标注的图像数据来训练模型,使其学习到如何识别并定位图像中的目标对象。
在训练过程中,模型会不断调整其参数(或权重),以最小化预测结果与实际标注之间的差异。这通常通过优化算法(如梯度下降)来实现,该算法会计算预测结果与实际标注之间的误差(或损失),并使用这个误差来指导模型参数的更新。
一旦模型训练完成,它就可以用于新的、未见过的图像数据,以检测并定位其中的目标对象。这种技术在许多领域都有广泛的应用,包括安全监控、自动驾驶、医疗影像分析等。
无论是目标检测的新手还是经验丰富的老手,从头开始组装一个目标检测流程都是一项艰巨的任务。幸运的是,KerasCV 的所有目标检测 API 都是作为模块化组件构建的。无论您需要一个完整的流程、仅一个目标检测模型,还是仅需要一个转换工具来将您的边界框从 xywh 格式转换为 xyxy 格式,KerasCV 都为您提供了支持。
在本文中,我们将为 KerasCV 目标检测模型组装一个完整的训练流程。这包括数据加载、数据增强、指标评估和推理!
首先,让我们整理好所有的导入并定义全局配置参数。
BATCH_SIZE = 4
2.4.1 数据加载
首先,让我们讨论数据加载和边界框格式。KerasCV 为边界框定义了一种预定义的格式。为了遵守这个格式,您应该将您的边界框打包成一个符合以下规范的字典:
bounding_boxes = {
# num_boxes may be a Ragged dimension
'boxes': Tensor(shape=[batch, num_boxes, 4]),
'classes': Tensor(shape=[batch, num_boxes])
}
bounding_boxes[‘boxes’] 包含了 KerasCV 支持的边界框格式中的边界框坐标。KerasCV 在所有处理边界框的组件中都要求一个 bounding_box_format 参数。这是为了最大化您将各个组件插入到目标检测流程中的能力,同时也为了让目标检测流程中的代码能够自我文档化。
为了匹配 KerasCV API 的风格,当您编写自定义数据加载器时,也推荐您支持 bounding_box_format 参数。这会让调用您数据加载器的人清楚地知道边界框的格式。在这个例子中,我们将我们的边界框格式化为 xywh 格式。
train_ds, ds_info = your_data_loader.load(
split='train', bounding_box_format='xywh', batch_size=8
)
上述代码清楚地产生了 xywh 格式的边界框。这样数据以 {“images”: images, “bounding_boxes”: bounding_boxes} 的格式加载。这种格式在所有 KerasCV 预处理组件中都是受支持的。
现在让我们加载一些数据,并验证数据是否符合我们的预期。
def visualize_dataset(inputs, value_range, rows, cols, bounding_box_format):
inputs = next(iter(inputs.take(1)))
images, bounding_boxes = inputs["images"], inputs["bounding_boxes"]
visualization.plot_bounding_box_gallery(
images,
value_range=value_range,
rows=rows,
cols=cols,
y_true=bounding_boxes,
scale=5,
font_scale=0.7,
bounding_box_format=bounding_box_format,
class_mapping=class_mapping,
)
def unpackage_raw_tfds_inputs(inputs, bounding_box_format):
image = inputs["image"]
boxes = keras_cv.bounding_box.convert_format(
inputs["objects"]["bbox"],
images=image,
source="rel_yxyx",
target=bounding_box_format,
)
bounding_boxes = {
"classes": inputs["objects"]["label"],
"boxes": boxes,
}
return {"images": image, "bounding_boxes": bounding_boxes}
def load_pascal_voc(split, dataset, bounding_box_format):
ds = tfds.load(dataset, split=split, with_info=False, shuffle_files=True)
ds = ds.map(
lambda x: unpackage_raw_tfds_inputs(x, bounding_box_format=bounding_box_format),
num_parallel_calls=tf_data.AUTOTUNE,
)
return ds
train_ds = load_pascal_voc(
split="train", dataset="voc/2007", bounding_box_format="xywh"
)
eval_ds = load_pascal_voc(split="test", dataset="voc/2007", bounding_box_format="xywh")
train_ds = train_ds.shuffle(BATCH_SIZE * 4)
接下来,让我们将数据分批处理。
在 KerasCV 的目标检测任务中,建议使用参差不齐的批次输入。这是因为 PascalVOC 中的图像可能具有不同的尺寸,并且每个图像的边界框数量也可能不同。
为了在 tf.data 管道中构造一个参差不齐的数据集,可以使用 ragged_batch()
方法。
train_ds = train_ds.ragged_batch(BATCH_SIZE, drop_remainder=True)
eval_ds = eval_ds.ragged_batch(BATCH_SIZE, drop_remainder=True)
让我们确保我们的数据集遵循 KerasCV 所期望的格式。通过使用 visualize_dataset()
函数,您可以直观地验证您的数据是否符合 KerasCV 所需的格式。如果边界框不可见或显示在错误的位置,这表明您的数据格式不正确。
visualize_dataset(
train_ds, bounding_box_format="xywh", value_range=(0, 255), rows=2, cols=2
)
对于评估集(eval set):
visualize_dataset(
eval_ds,
bounding_box_format="xywh",
value_range=(0, 255),
rows=2,
cols=2,
# If you are not running your experiment on a local machine, you can also
# make `visualize_dataset()` dump the plot to a file using `path`:
# path="eval.png"
)
2.4.2 数据增强
在构建目标检测流程时,最具有挑战性的任务之一是数据增强。图像增强技术必须了解底层的边界框,并相应地更新它们。
幸运的是,KerasCV 自带了一个丰富的数据增强层库,可以原生支持边界框增强。下面的代码加载了 Pascal VOC 数据集,并在一个 tf.data 管道中进行了实时的、对边界框友好的数据增强。
augmenters = [
keras_cv.layers.RandomFlip(mode="horizontal", bounding_box_format="xywh"),
keras_cv.layers.JitteredResize(
target_size=(640, 640), scale_factor=(0.75, 1.3), bounding_box_format="xywh"
),
]
def create_augmenter_fn(augmenters):
def augmenter_fn(inputs):
for augmenter in augmenters:
inputs = augmenter(inputs)
return inputs
return augmenter_fn
augmenter_fn = create_augmenter_fn(augmenters)
train_ds = train_ds.map(augmenter_fn, num_parallel_calls=tf_data.AUTOTUNE)
visualize_dataset(
train_ds, bounding_box_format="xywh", value_range=(0, 255), rows=2, cols=2
)
这样现在有了一个支持边界框的数据增强流程。以下将使用确定性的 keras_cv.layers.Resizing()
层评估数据集格式化为与之匹配。而不要使用 JitteredResize
。
inference_resizing = keras_cv.layers.Resizing(
640, 640, bounding_box_format="xywh", pad_to_aspect_ratio=True
)
eval_ds = eval_ds.map(inference_resizing, num_parallel_calls=tf_data.AUTOTUNE)
由于训练数据集使用的 JitteredResize()
层和推理数据集使用的 layers.Resizing(pad_to_aspect_ratio=True)
层在调整图像大小时存在差异,因此可视化这两个数据集是一个好习惯:
visualize_dataset(
eval_ds, bounding_box_format="xywh", value_range=(0, 255), rows=2, cols=2
)
最后,让我们从预处理字典中提取我们的输入,并准备将这些输入输入到我们的模型中。为了与 TPU 兼容,边界框张量需要是 Dense 而不是 Ragged。
def dict_to_tuple(inputs):
return inputs["images"], bounding_box.to_dense(
inputs["bounding_boxes"], max_boxes=32
)
train_ds = train_ds.map(dict_to_tuple, num_parallel_calls=tf_data.AUTOTUNE)
eval_ds = eval_ds.map(dict_to_tuple, num_parallel_calls=tf_data.AUTOTUNE)
train_ds = train_ds.prefetch(tf_data.AUTOTUNE)
eval_ds = eval_ds.prefetch(tf_data.AUTOTUNE)
2.5 优化器
本文主要介绍使用标准的 SGD 优化器,并依赖 keras.callbacks.ReduceLROnPlateau 回调来降低学习率。
在训练目标检测模型时,始终希望包含一个 global_clipnorm
。这是为了修复在训练目标检测模型时经常出现的梯度爆炸问题。
base_lr = 0.005
# including a global_clipnorm is extremely important in object detection tasks
optimizer = keras.optimizers.SGD(
learning_rate=base_lr, momentum=0.9, global_clipnorm=10.0
)
为了在你的数据集上获得最佳结果,程序员可能需要手动设计一个 PiecewiseConstantDecay
学习率调度器。虽然 PiecewiseConstantDecay
调度器通常表现更好,但它们并不适用于所有问题。
2.5.1 损失函数
程序员可能不熟悉“ciou”损失。虽然在其他模型中不常见,但这种损失有时在目标检测领域中使用。
简而言之,“Complete IoU”是交并比(Intersection over Union)损失的一种变体,由于其收敛特性而被使用。
在 KerasCV 中,程序员可以通过向 compile()
函数传递字符串 “ciou” 来简单地使用这种损失。我们还对类别头使用标准的二元交叉熵损失。
pretrained_model.compile(
classification_loss="binary_crossentropy",
box_loss="ciou",
)
2.5.2 度量评估
最流行的目标检测度量是 COCO 度量,它与 MSCOCO 数据集一同发布。KerasCV 提供了一套易于使用的 COCO 度量套件,位于 keras_cv.callbacks.PyCOCOCallback
符号下。请注意,我们使用 Keras 回调而不是 Keras 度量来计算 COCO 度量。这是因为计算 COCO 度量需要在内存中一次性存储模型对整个评估数据集的所有预测,这在训练期间是不切实际的。
coco_metrics_callback = keras_cv.callbacks.PyCOCOCallback(
eval_ds.take(20), bounding_box_format="xywh"
)
2.6 模型创建
接下来,让我们使用 KerasCV API 来构建一个未经训练的 YOLOV8Detector
模型。本文我们使用 ImageNet 数据集上预训练的 ResNet50 主干网络。
KerasCV 使得使用 KerasCV 主干网络构建 YOLOV8Detector
变得非常简单。只需选择您想要使用的架构预设之一即可!
例如:
model = keras_cv.models.YOLOV8Detector.from_preset(
"resnet50_imagenet",
# For more info on supported bounding box formats, visit
# https://keras.io/api/keras_cv/bounding_box/
bounding_box_format="xywh",
num_classes=20,
)
这就是构建 KerasCV YOLOv8 所需的全部内容。YOLOv8 接受密集图像张量和边界框字典的元组来进行 fit()
和 train_on_batch()
。
这与我们上面构建的输入管道相匹配。
2.7 训练模型
接下来要做的就是训练我们的模型。KerasCV 目标检测模型遵循标准的 Keras 工作流程,利用 compile()
和 fit()
方法。
让我们来编译我们的模型:
model.compile(
classification_loss="binary_crossentropy",
box_loss="ciou",
optimizer=optimizer,
)
如果你想完全训练模型,请从所有数据集引用(以下以及度量回调的初始化中)中删除 .take(20)
。
model.fit(
train_ds.take(20),
# Run for 10-35~ epochs to achieve good scores.
epochs=1,
callbacks=[coco_metrics_callback],
)
2.8 推理和绘制结果
KerasCV 使得目标检测推理变得简单。model.predict(images)
返回一个边界框的张量。默认情况下,YOLOV8Detector.predict()
将为你执行非极大值抑制操作。
在本节中,我们将使用 KerasCV 提供的预设:
model = keras_cv.models.YOLOV8Detector.from_preset(
"yolo_v8_m_pascalvoc", bounding_box_format="xywh"
)
接下来,为了方便起见,构造一个具有较大批次的数据集:
visualization_ds = eval_ds.unbatch()
visualization_ds = visualization_ds.ragged_batch(16)
visualization_ds = visualization_ds.shuffle(8)
创建一个简单的函数来绘制我们的推理结果
def visualize_detections(model, dataset, bounding_box_format):
images, y_true = next(iter(dataset.take(1)))
y_pred = model.predict(images)
visualization.plot_bounding_box_gallery(
images,
value_range=(0, 255),
bounding_box_format=bounding_box_format,
y_true=y_true,
y_pred=y_pred,
scale=4,
rows=2,
cols=2,
show=True,
font_scale=0.7,
class_mapping=class_mapping,
)
有时可能需要配置您的非极大值抑制(Non-Maximum Suppression, NMS)操作以获得视觉上吸引人的结果
model.prediction_decoder = keras_cv.layers.NonMaxSuppression(
bounding_box_format="xywh",
from_logits=True,
iou_threshold=0.5,
confidence_threshold=0.75,
)
visualize_detections(model, dataset=visualization_ds, bounding_box_format="xywh")
在 Keras 的 keras.callbacks.Callback 中可视化检测结果以监控训练过程
class VisualizeDetections(keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs):
visualize_detections(
self.model, bounding_box_format="xywh", dataset=visualization_ds
)
KerasCV 使得构建最先进的目标检测管道变得容易。在本指南中,我们首先使用 KerasCV 边界框规范编写了一个数据加载器。接下来,我们使用 KerasCV 预处理层在不到 50 行代码的情况下组装了一个生产级别的数据增强管道。
KerasCV 的目标检测组件可以独立使用,但彼此之间也有深度集成。KerasCV 使得编写生产级别的边界框增强、模型训练、可视化和度量评估变得容易。
以下示例可以展示kerasCV提供的API的强大的功能
stable_diffusion = keras_cv.models.StableDiffusionV2(512, 512)
images = stable_diffusion.text_to_image(
prompt="A zoomed out photograph of a cool looking cat. The cat stands in a beautiful forest",
negative_prompt="unrealistic, bad looking, malformed",
batch_size=4,
seed=1231,
)
encoded_predictions = model(images)
y_pred = model.decode_predictions(encoded_predictions, images)
visualization.plot_bounding_box_gallery(
images,
value_range=(0, 255),
y_pred=y_pred,
rows=2,
cols=2,
scale=5,
font_scale=0.7,
bounding_box_format="xywh",
class_mapping=class_mapping,
)
3、总结
当使用KerasCV进行目标检测时,整个过程可以分为以下几个关键步骤:
-
数据准备:
- 首先,你需要准备一个包含目标边界框标注的图像数据集。这通常涉及收集图像,然后使用如LabelImg之类的工具手动标注目标,或者使用自动标注工具。
- 数据集应被划分为训练集、验证集(可选)和测试集。训练集用于训练模型,验证集用于在训练过程中监控模型的性能,而测试集则用于评估最终模型的性能。
-
构建模型:
- KerasCV支持多种目标检测模型,如YOLO、SSD等。你可以选择一个适合你任务需求的模型,并在KerasCV中实现它。
- 这些模型通常是基于卷积神经网络(CNN)的架构,它们通过卷积层、池化层、全连接层等结构来提取图像特征,并预测目标的边界框和类别。
-
编写数据生成器:
- 为了训练模型,你需要编写一个数据生成器来加载并处理数据集。数据生成器应该能够将图像和标注框传递给模型,并生成训练所需的批次数据。
- 在数据生成器中,你可以进行一系列的数据预处理操作,如缩放、归一化、数据增强(如随机翻转、裁剪等)等,以提高模型的泛化能力。
-
编译模型:
- 在模型构建完成后,你需要编译模型以配置训练过程。这包括选择优化器(如Adam、SGD等)、损失函数(如边界框回归损失和分类损失的组合)和评估指标(如mAP、准确率等)。
-
训练模型:
- 使用训练数据对模型进行训练。你可以使用Keras的
fit()
方法来执行训练过程,设置适当的批次大小、迭代次数和学习率等超参数。 - 在训练过程中,模型将学习从图像中识别目标并预测其边界框和类别。你可以通过验证集来监控模型的性能,并根据需要进行调整。
- 使用训练数据对模型进行训练。你可以使用Keras的
-
评估模型:
- 在训练完成后,使用测试集来评估模型的性能。计算mAP或其他相关指标来评估模型在目标检测任务上的准确性。
- 你还可以对模型进行可视化分析,查看模型的预测结果和标注结果之间的差异,以便进一步改进模型。
-
使用模型:
- 一旦模型训练完成并经过验证,你就可以使用它来对新的图像进行目标检测了。将模型应用于新的图像,并获取预测的目标边界框和类别标签。
- 你可以将模型集成到应用程序中,实现实时的目标检测功能,或者将检测结果用于其他任务(如物体追踪、图像分析等)。
总结起来,使用KerasCV进行目标检测涉及数据准备、模型构建、数据生成器编写、模型编译、训练、评估和使用等多个步骤。通过合理配置和调整这些步骤中的参数和组件,你可以构建出高性能的目标检测模型,并应用于各种实际场景中。