19 自动驾驶车辆探测

发布时间 2023-10-08 16:18:08作者: 王哲MGG_AI
import numpy as np
import tensorflow as tf
# 需要安装pip install opencv-python==4.5.3.56
import cv2
from IPython.display import Image, display
from tensorflow.keras.models import load_model
from yolo_utils import read_classes, read_anchors, yolo_head, preprocess_image, generate_colors, draw_outputs


%matplotlib inline

这段代码看起来是一个Python脚本或者Jupyter Notebook的一部分。

  1. import numpy as np: 这一行导入了一个名为NumPy的Python库,并将其重命名为np。NumPy是用于科学计算的库,它提供了多维数组和矩阵的支持。

  2. import tensorflow as tf: 这一行导入了TensorFlow库,用于深度学习和神经网络的构建和训练。

  3. import cv2: 这一行导入了OpenCV库,OpenCV是一个计算机视觉库,用于图像处理和计算机视觉任务。

  4. from IPython.display import Image, display: 这一行从IPython的display模块中导入Imagedisplay函数,用于在Jupyter Notebook中显示图像。

  5. from tensorflow.keras.models import load_model: 这一行从TensorFlow的Keras模块中导入load_model函数,用于加载预训练的神经网络模型。

  6. from yolo_utils import read_classes, read_anchors, yolo_head, preprocess_image, generate_colors, draw_outputs: 这一行从一个名为yolo_utils的自定义模块中导入了一些函数,这些函数似乎与YOLO(You Only Look Once)目标检测模型相关。

  7. %matplotlib inline: 这是一个Jupyter Notebook的魔术命令,它用于在Notebook中嵌入Matplotlib图形,并且将图形显示在Notebook中而不是弹出一个新的窗口。

# 过滤掉那些概率低的边框
def yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold = .6):
    """
    box_confidence -- 装载着每个边框的pc
    boxes -- 装载着每个边框的坐标
    box_class_probs -- 装载着每个边框的80个种类的概率
    threshold -- 阈值,概率低于这个值的边框会被过滤掉
    
    返回值:
    scores -- 装载保留下的那些边框的概率
    boxes -- 装载保留下的那些边框的坐标
    classes -- 装载保留下的那些边框的种类的索引
    
    """
    
    # 将pc和c相乘,得到具体某个种类是否存在的概率
    box_scores = box_confidence * box_class_probs
    
    
    box_classes = tf.argmax(box_scores, axis=-1) # 获取概率最大的那个种类的索引
    box_class_scores = tf.reduce_max(box_scores, axis=-1) # 获取概率最大的那个种类的概率值

    
    # 创建一个过滤器。当某个种类的概率值大于等于阈值threshold时,
    # 对应于这个种类的filtering_mask中的位置就是true,否则就是false。
    # 所以filtering_mask就是[False, True, 。。。, False, True]这种形式。
    filtering_mask = tf.greater_equal(box_class_scores, threshold)

    
    # 用上面的过滤器来过滤掉那些概率小的边框。
    # 过滤完成后,scores和boxes,classes里面就只装载了概率大的边框的概率值和坐标以及种类索引了。
    scores = tf.boolean_mask(box_class_scores, filtering_mask)
    boxes = tf.boolean_mask(boxes, filtering_mask)
    classes = tf.boolean_mask(box_classes, filtering_mask)
    
    return scores, boxes, classes

这段代码定义了一个名为 yolo_filter_boxes 的函数,用于过滤掉目标检测模型输出的边框中概率低于指定阈值的部分。

  • box_confidence:这是一个张量,包含了每个边框的置信度(预测的边框中包含物体的概率)。

  • boxes:这是一个张量,包含了每个边框的坐标信息。

  • box_class_probs:这是一个张量,包含了每个边框的80个类别的概率分布,通常用于识别物体的类别。

  • threshold:这是一个阈值,用于确定哪些边框的置信度高于阈值,应该被保留下来,而哪些应该被过滤掉。

函数的主要功能可以总结为以下几个步骤:

  1. 计算每个边框的类别概率乘以置信度,以获得每个边框各类别的得分。这一步骤通过将 box_confidencebox_class_probs 相乘来实现。

  2. 对于每个边框,找到具有最高得分的类别索引(即最有可能的物体类别)和该类别的得分值。

  3. 创建一个过滤器 filtering_mask,其中每个元素表示对应边框的类别得分是否大于等于指定的阈值 threshold。如果得分高于阈值,相应位置的元素为True,否则为False。

  4. 使用 filtering_mask 过滤掉概率低于阈值的边框,从而得到满足条件的边框的概率值、坐标和类别索引。这是通过 TensorFlow 的 tf.boolean_mask 函数来实现的。

  5. 最后,函数返回被保留下来的边框的概率值、坐标和类别索引,这些信息可以进一步用于后续的处理或可视化。

这个函数在目标检测中用于提取置信度高于阈值的边框,从而过滤掉置信度较低的边框。这有助于减少假阳性检测并提高检测的准确性。

box_confidence = tf.random.normal([13, 13, 3, 1], mean=1, stddev=4, seed = 1)
boxes = tf.random.normal([13, 13, 3, 4], mean=1, stddev=4, seed = 1)
box_class_probs = tf.random.normal([13, 13, 3, 80], mean=1, stddev=4, seed = 1)
scores, boxes, classes = yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold = 0.5)
print("scores[2] = ",scores[2])
print("boxes[2] = " , boxes[2])
print("classes[2] = " , classes[2])
print("scores.shape = " , scores.shape)
print("boxes.shape = " , boxes.shape)
print("classes.shape = " , classes.shape)

这段代码用于演示 yolo_filter_boxes 函数的使用,通过传入一些随机生成的张量来过滤边框。

  1. box_confidenceboxesbox_class_probs:这些张量分别代表模拟的目标检测模型的置信度、边框坐标和类别概率分布。这些张量的形状都是 [13, 13, 3, ...],其中 13x13 表示输入图像被划分为 13x13 个网格,3 表示每个网格预测3个不同的边框,后续维度根据置信度、坐标和类别概率的需要而不同。

  2. scores, boxes, classes = yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold = 0.5):这一行调用了 yolo_filter_boxes 函数,将随机生成的置信度、边框坐标和类别概率分布作为参数传递给函数。阈值 threshold 设置为 0.5,表示只保留置信度大于等于0.5的边框。

  3. print("scores[2] = ",scores[2])print("boxes[2] = " , boxes[2])print("classes[2] = " , classes[2]):这些行用于打印出第三个保留下来的边框的概率值、坐标和类别索引。

  4. print("scores.shape = " , scores.shape)print("boxes.shape = " , boxes.shape)print("classes.shape = " , classes.shape):这些行用于打印出概率值、坐标和类别索引张量的形状。

总结一下,这段代码的目的是模拟目标检测模型的输出,并使用 yolo_filter_boxes 函数过滤出概率高于0.5的边框。然后,它打印出了第三个保留下来的边框的相关信息以及张量的形状信息。

# 用非最大值抑制技术过滤掉重叠的边框

def yolo_non_max_suppression(scores, boxes, classes, max_boxes = 20, iou_threshold = 0.5):
    """
    参数:
    scores -- 前面yolo_filter_boxes函数保留下的那些边框的概率值
    boxes -- 前面yolo_filter_boxes函数保留下的那些边框的坐标
    classes -- 前面yolo_filter_boxes函数保留下的那些边框的种类的索引
    max_boxes -- 最多想要保留多少个边框
    iou_threshold -- 交并比,这是一个阈值,也就是说交并比大于这个阈值的边框才会被进行非最大值抑制处理
    
    Returns:
    scores -- NMS保留下的那些边框的概率值
    boxes -- NMS保留下的那些边框的坐标
    classes -- NMS保留下的那些边框的种类的索引
    """
    
    # tensorflow为我们提供了一个NMS函数,我们直接调用就可以了tf.image.non_max_suppression()。
    # 这个函数会返回NMS后保留下来的边框的索引
    nms_indices = tf.image.non_max_suppression(boxes, scores, max_boxes, iou_threshold=iou_threshold)

    # 通过上面的索引来分别获取被保留的边框的相关概率值,坐标以及种类的索引
    scores = tf.gather(scores, nms_indices)
    boxes = tf.gather(boxes, nms_indices)
    classes = tf.gather(classes, nms_indices)
    
    return scores, boxes, classes

这段代码定义了一个名为 yolo_non_max_suppression 的函数,用于使用非最大值抑制(Non-Maximum Suppression,NMS)技术来过滤掉重叠的边框。

  • scores:这是一个包含保留下来的边框的概率值的张量,通常是从 yolo_filter_boxes 函数中获得的。

  • boxes:这是一个包含保留下来的边框的坐标信息的张量,也通常是从 yolo_filter_boxes 函数中获得的。

  • classes:这是一个包含保留下来的边框的类别索引的张量,同样也是从 yolo_filter_boxes 函数中获得的。

  • max_boxes:这是一个整数,表示最多要保留多少个边框。如果 NMS 后的边框数超过这个值,将根据得分进行排序并选择前 max_boxes 个。

  • iou_threshold:这是一个交并比(IoU)阈值,用于确定何时认为两个边框重叠。如果两个边框的交并比大于等于该阈值,则其中一个边框将被抑制。

函数的主要功能可以总结为以下几个步骤:

  1. 使用 TensorFlow 的 tf.image.non_max_suppression 函数,传入 boxesscoresmax_boxesiou_threshold 参数,来执行非最大值抑制操作。该函数将返回被保留下来的边框的索引。

  2. 根据上一步获得的索引,从原始的 scoresboxesclasses 张量中分别提取被保留下来的边框的概率值、坐标和类别索引。

  3. 最后,函数返回经过NMS处理后的概率值、坐标和类别索引。

这个函数通常用于去除重叠的边框,以便在目标检测结果中保留最具代表性和有价值的边框。

scores = tf.random.normal([54,], mean=1, stddev=4, seed = 1)
boxes = tf.random.normal([54, 4], mean=1, stddev=4, seed = 1)
classes = tf.random.normal([54,], mean=1, stddev=4, seed = 1)
scores, boxes, classes = yolo_non_max_suppression(scores, boxes, classes)
print("scores[2] = ", scores[2])
print("boxes[2] = " , boxes[2])
print("classes[2] = " , classes[2])
print("scores.shape = ", scores.shape)
print("boxes.shape = ", boxes.shape)
print("classes.shape = " , classes.shape)

这段代码用于演示 yolo_non_max_suppression 函数的使用,通过传入一些随机生成的张量来进行非最大值抑制操作。

  1. scoresboxesclasses:这些张量分别代表模拟的目标检测模型的概率值、边框坐标和类别索引。这些张量的形状都是 [54, ...],其中 54 表示输入的边框数,后续维度根据数据的需要而不同。

  2. scores, boxes, classes = yolo_non_max_suppression(scores, boxes, classes):这一行调用了 yolo_non_max_suppression 函数,将随机生成的概率值、边框坐标和类别索引作为参数传递给函数。函数会执行非最大值抑制操作,并返回经过NMS处理后的概率值、坐标和类别索引。

  3. print("scores[2] = ", scores[2])print("boxes[2] = " , boxes[2])print("classes[2] = " , classes[2]):这些行用于打印出第三个保留下来的边框的概率值、坐标和类别索引。

  4. print("scores.shape = ", scores.shape)print("boxes.shape = ", boxes.shape)print("classes.shape = " , classes.shape):这些行用于打印出概率值、坐标和类别索引张量的形状。

总结一下,这段代码的目的是模拟目标检测模型的输出,并使用 yolo_non_max_suppression 函数对边框进行非最大值抑制操作。然后,它打印出了第三个保留下来的边框的相关信息以及张量的形状信息。

# 这个函数里面整合了前面我们实现的两个过滤函数。将YOLO模型的输出结果输入到这个函数后,这个函数会将多余边框过滤掉

def yolo_eval(outputs, max_boxes=20, score_threshold=.5, iou_threshold=.5):
    """
    参数:
    yolo_outputs -- YOLO模型的输出结果
    max_boxes -- 你希望最多识别出多少个边框
    score_threshold -- 概率值阈值
    iou_threshold -- 交并比阈值
    
    Returns:
    scores -- 最终保留下的那些边框的概率值
    boxes -- 最终保留下的那些边框的坐标
    classes -- 最终保留下的那些边框的种类的索引
    """
    #建立3个空list
    s, b, c = [], [], []
    
    # 我们后面我们调用的Yolov3使用了3个规格的网格(13*13,26*26,52*52)进行预测。所以有3组output。
    for output in outputs:
        
        ### 将YOLO输出结果分成3份,分别表示概率值,坐标,种类索引
        box_confidence, boxes,  box_class_probs = output

        # 使用我们前面实现的yolo_filter_boxes函数过滤掉概率值低于阈值的边框
        scores, boxes, classes = yolo_filter_boxes(box_confidence, boxes, box_class_probs, 
                                                   threshold = score_threshold)
        
        s.append(scores)
        b.append(boxes)
        c.append(classes)
    
    #将3组output的结果整合到一起
    scores = tf.concat(s, axis=0)
    boxes = tf.concat(b, axis=0)
    classes = tf.concat(c, axis=0)
    

    # 使用我们前面实现的yolo_non_max_suppression过滤掉重叠的边框
    scores, boxes, classes = yolo_non_max_suppression(scores, boxes, classes, max_boxes = max_boxes, 
                                                      iou_threshold = iou_threshold)
      
    return scores, boxes, classes

这段代码定义了一个名为 yolo_eval 的函数,该函数整合了之前实现的两个过滤函数 yolo_filter_boxesyolo_non_max_suppression,用于处理YOLO模型的输出结果并最终返回一组过滤后的边框。

  • outputs:这是一个包含YOLO模型的输出结果的列表。通常,YOLO模型会生成多个输出,每个输出对应于不同尺度的检测。每个输出是一个三元组,包含了概率值、边框坐标和类别概率分布。

  • max_boxes:这是一个整数,表示最多要保留多少个边框。

  • score_threshold:这是一个概率值阈值,用于过滤掉置信度低于阈值的边框。

  • iou_threshold:这是一个交并比(IoU)阈值,用于非最大值抑制,确定何时认为两个边框重叠。

函数的主要功能可以总结为以下几个步骤:

  1. 建立三个空列表 sbc,用于分别存储概率值、坐标和类别索引。

  2. 遍历 outputs 列表中的每个输出,将每个输出分成概率值、坐标和类别概率分布。

  3. 对每个输出,使用 yolo_filter_boxes 函数过滤掉概率值低于阈值的边框,并将结果存储在 scoresboxesclasses 中。

  4. 将不同尺度的输出结果整合到一起,通过 tf.concat 函数将 scoresboxesclasses 沿指定的轴(axis=0)连接在一起。

  5. 使用 yolo_non_max_suppression 函数对整合后的边框进行非最大值抑制操作,以过滤掉重叠的边框,并返回最终保留下来的概率值、坐标和类别索引。

最终,函数返回经过所有过滤操作后的最终边框结果。

这个函数的主要目的是将YOLO模型的输出结果整合和过滤,以获得最终的检测结果。

yolo_output = (tf.random.normal([13, 13, 3, 1], mean=1, stddev=4, seed = 1),
                tf.random.normal([13, 13, 3, 4], mean=1, stddev=4, seed = 1),
                tf.random.normal([13, 13, 3, 80], mean=1, stddev=4, seed = 1))
yolo_output1 = (tf.random.normal([26, 26, 3, 1], mean=1, stddev=4, seed = 2),
                tf.random.normal([26, 26, 3, 4], mean=1, stddev=4, seed = 2),
                tf.random.normal([26, 26, 3, 80], mean=1, stddev=4, seed = 2))
yolo_output2 = (tf.random.normal([52, 52, 3, 1], mean=1, stddev=4, seed = 3),
                tf.random.normal([52, 52, 3, 4], mean=1, stddev=4, seed = 3),
                tf.random.normal([52, 52, 3, 80], mean=1, stddev=4, seed = 3))
yolo_outputs = (yolo_output, yolo_output1, yolo_output2)
scores, boxes, classes = yolo_eval(yolo_outputs)
print("scores[2] = ", scores[2])
print("boxes[2] = " , boxes[2])
print("classes[2] = ", classes[2])
print("scores.shape = ", scores.shape)
print("boxes.shape = ", boxes.shape)
print("classes.shape = " , classes.shape)

这段代码用于演示 yolo_eval 函数的使用,通过传入一些随机生成的 YOLO 模型的输出结果来进行边框处理和过滤。让我逐行解释代码的执行过程:

  1. yolo_outputyolo_output1yolo_output2:这些变量分别代表模拟的 YOLO 模型在不同尺度下的输出结果。每个输出是一个三元组,包含了概率值、边框坐标和类别概率分布。

  2. yolo_outputs:这是一个包含了上述不同尺度下的 YOLO 模型输出的元组。

  3. scores, boxes, classes = yolo_eval(yolo_outputs):这一行调用了 yolo_eval 函数,将 yolo_outputs 作为参数传递给函数。函数会执行整合和过滤操作,最终返回一组过滤后的概率值、坐标和类别索引。

  4. print("scores[2] = ", scores[2])print("boxes[2] = " , boxes[2])print("classes[2] = ", classes[2]):这些行用于打印出第三个保留下来的边框的概率值、坐标和类别索引。

  5. print("scores.shape = ", scores.shape)print("boxes.shape = ", boxes.shape)print("classes.shape = " , classes.shape):这些行用于打印出概率值、坐标和类别索引张量的形状。

总结一下,这段代码的目的是模拟 YOLO 模型的输出,并使用 yolo_eval 函数对输出结果进行整合和过滤,以获得最终的检测结果。

class_names = read_classes("model_data/coco_classes.txt")
anchors = read_anchors("model_data/yolo_anchors.txt") 

这两行代码用于加载类别名称和锚点信息。

  1. class_names = read_classes("model_data/coco_classes.txt"):这行代码通过调用名为 read_classes 的函数从文件 "model_data/coco_classes.txt" 中读取类别名称。通常,这个文件包含了模型训练所用的数据集的类别名称列表。这些类别名称可能包括"猫"、"狗"、"汽车"等。加载类别名称是为了在目标检测结果中标识检测到的物体属于哪个类别。

  2. anchors = read_anchors("model_data/yolo_anchors.txt"):这行代码通过调用名为 read_anchors 的函数从文件 "model_data/yolo_anchors.txt" 中读取锚点信息。锚点是用于辅助物体检测的一组预定义的边框尺寸。YOLO模型会使用这些锚点来生成不同尺度的边框,并用于预测物体的位置和大小。加载锚点信息是为了配置模型的检测参数。

这两行代码的目的是为模型提供必要的配置信息,以便进行物体检测。在后续的代码中,这些配置信息将用于解释模型的输出结果和可视化检测结果。

yolo_model = load_model("model_data/yolo_model.h5")

这行代码用于加载已经训练好的YOLO模型。

  • yolo_model = load_model("model_data/yolo_model.h5"):这行代码使用 TensorFlow 的 load_model 函数从文件 "model_data/yolo_model.h5" 中加载已经训练好的YOLO模型。这个模型包含了模型的架构、权重和其他相关参数,使得你可以在其上进行物体检测任务。

加载已经训练好的模型通常需要一些时间,因为模型的参数和架构都需要被还原。一旦模型被成功加载,你就可以使用它来进行物体检测、预测和推断。

在加载模型后,你可以使用它来处理图像、视频或摄像头流,以进行目标检测。

yolo_model.summary()

yolo_model.summary() 方法用于获取已加载的YOLO模型的摘要信息,该摘要信息包含有关模型的各个层次结构和参数数量的详细信息。这对于了解模型的架构以及查看模型的层次结构和参数数量非常有用。通常,模型摘要信息会显示每个层次结构的名称、输出形状(尺寸)、参数数量等。

可以运行 yolo_model.summary() 来查看已加载的YOLO模型的摘要信息,以便更好地理解模型的结构和配置。这对于调试和优化模型非常有帮助,特别是在进行迁移学习或微调模型时。

img_raw, img = preprocess_image("test.jpg", model_image_size = (416, 416))
yolo_outputs = yolo_model(img)

这两行代码用于准备图像并通过已加载的YOLO模型进行目标检测。

  1. img_raw, img = preprocess_image("test.jpg", model_image_size=(416, 416)):这行代码首先使用名为 preprocess_image 的函数加载和预处理图像。具体来说,它从文件 "test.jpg" 中加载原始图像,并将其调整为指定的模型输入尺寸 (416, 416)。img_raw 保存原始图像,而 img 包含了经过预处理的图像,通常会进行归一化等操作,以便输入到模型中。

  2. yolo_outputs = yolo_model(img):这行代码将经过预处理的图像 img 通过已加载的YOLO模型 yolo_model 进行推断。yolo_model 接受图像作为输入,并生成目标检测结果。yolo_outputs 包含了模型的输出结果,通常是一组包含概率值、边框坐标和类别概率分布的张量。

通过执行这两行代码,你已经成功将图像输入到YOLO模型中,并获得了模型的输出结果,这些输出结果可以用于后续的目标检测和可视化。

outputs = yolo_head(yolo_outputs, anchors, len(class_names))

这行代码用于将 YOLO 模型的输出结果 yolo_outputs 通过 yolo_head 函数进行处理,以获得最终的目标检测结果。

  • outputs = yolo_head(yolo_outputs, anchors, len(class_names)):这行代码调用了名为 yolo_head 的函数,将 YOLO 模型的输出结果 yolo_outputs、锚点信息 anchors 以及类别数量 len(class_names) 作为参数传递给函数。len(class_names) 是已加载的类别名称列表的长度,用于确定有多少个类别需要检测。

yolo_head 函数的主要功能是对模型的输出进行后处理,包括解码边框坐标、计算类别概率分布以及应用阈值等操作,以便生成最终的检测结果。输出 outputs 通常包含了以下信息:

  • boxes:包含了检测到的物体的边框坐标信息。
  • scores:包含了每个边框的概率值。
  • classes:包含了每个边框所属的类别索引。

这个输出可以用于后续的可视化或进一步的处理,以获得最终的目标检测结果。

out_scores, out_boxes, out_classes = yolo_eval(outputs)

这一行代码用于调用 yolo_eval 函数来执行目标检测结果的最终过滤和筛选。

  • out_scores, out_boxes, out_classes = yolo_eval(outputs):这行代码将 outputs 作为参数传递给 yolo_eval 函数,以进行最终的目标检测结果的处理。yolo_eval 函数会执行整合和过滤操作,最终返回一组过滤后的概率值 out_scores、坐标 out_boxes 和类别索引 out_classes

这些输出包含了最终的目标检测结果,已经过滤掉了低概率的边框和非最大值抑制。通常,你可以使用这些输出来进行目标检测结果的可视化或进一步的应用,例如在图像或视频中绘制边框以标识检测到的物体。

def img_show(image_file, out_scores, out_boxes, out_classes, class_names):
    img_raw = tf.image.decode_image(open('./images/'+image_file, 'rb').read(), channels=3)
    img = cv2.cvtColor(img_raw.numpy(), cv2.COLOR_RGB2BGR)
    colors = generate_colors(class_names)
    print('Found {} boxes for {}'.format(len(out_boxes), image_file))
    img = draw_outputs(img, out_scores, out_boxes, out_classes, colors, class_names)
    display(Image(data=bytes(cv2.imencode('.jpg', img)[1]), width=800))
    file_name = [x for x in image_file.split('.')]
    cv2.imwrite('./out/'+file_name[0]+'_out.'+file_name[1], img)
    return img

这段代码定义了一个名为 img_show 的函数,该函数用于显示和保存检测结果,并返回包含了绘制边框的图像。

  • image_file:传入的图像文件名。
  • out_scores:检测结果中的概率值。
  • out_boxes:检测结果中的边框坐标。
  • out_classes:检测结果中的类别索引。
  • class_names:类别名称列表,用于标识检测到的物体所属的类别。

函数的主要步骤:

  1. 使用 TensorFlow 的 tf.image.decode_image 函数解码图像文件(通过读取文件的方式),并将其转换为 NumPy 数组。然后,使用 OpenCV 将图像从 RGB 格式转换为 BGR 格式,因为 OpenCV 通常使用 BGR 格式来处理图像。

  2. 使用 generate_colors 函数生成一组颜色,这些颜色将用于为不同类别的物体绘制不同的边框颜色。

  3. 打印出检测到的边框数量以及图像文件的信息。

  4. 使用 draw_outputs 函数将检测结果绘制在图像上,包括边框和类别标签。

  5. 使用 IPython 的 display 函数将绘制了边框的图像显示在 Jupyter Notebook 中。

  6. 将绘制了边框的图像保存到指定路径。

  7. 最后,返回包含了绘制边框的图像。

这个函数的目的是将检测结果可视化并保存到文件,以便进一步分析和展示检测到的物体。

img = img_show('test.jpg', out_scores, out_boxes, out_classes, class_names)

这行代码调用了之前定义的 img_show 函数,用于显示和保存检测结果,并将返回的包含了绘制边框的图像赋值给变量 img。具体来说,它将检测结果 out_scoresout_boxesout_classes 和类别名称 class_names 传递给 img_show 函数,以便可视化和保存检测结果。

执行这行代码后,会在 Jupyter Notebook 或类似的环境中显示带有边框的图像,并将其保存到指定的输出文件中。这个图像包含了检测到的物体、其概率值和类别标签。

# 使用前面构建好的graph来探测图片中的车辆
def predict(model, image_file, anchors, class_names):
    img_raw, img = preprocess_image(image_file, model_image_size = (416, 416))
    yolo_outputs = yolo_model(img)
    outputs = yolo_head(yolo_outputs, anchors, len(class_names))
    out_scores, out_boxes, out_classes = yolo_eval(outputs)
    img = img_show(image_file, out_scores, out_boxes, out_classes, class_names)
    return img

这段代码定义了一个名为 predict 的函数,用于使用已构建的模型来探测图像中的车辆。

  • model:已加载的YOLO模型。
  • image_file:要进行目标检测的输入图像文件名。
  • anchors:锚点信息,用于模型输出解码。
  • class_names:类别名称列表,用于标识检测到的物体所属的类别。

函数的主要步骤:

  1. 使用 preprocess_image 函数对输入图像进行预处理,包括加载图像文件、调整尺寸和归一化等操作,以便输入到模型中。

  2. 使用已加载的YOLO模型 model 对预处理后的图像进行目标检测,获得模型的输出结果。

  3. 使用 yolo_head 函数对模型的输出结果进行后处理,包括解码边框坐标、计算类别概率分布以及应用阈值等操作。

  4. 使用 img_show 函数将检测结果绘制在图像上,并返回包含了绘制边框的图像。

  5. 最后,返回包含了绘制边框的图像。

这个函数的目的是将输入图像中的车辆进行目标检测,并返回带有检测结果的图像。你可以调用这个函数来执行车辆检测,并查看检测结果的可视化。

img = predict(yolo_model, '0070.jpg', anchors, class_names)

这行代码调用了之前定义的 predict 函数,用于使用已加载的YOLO模型来探测图像中的车辆。具体来说,它将已加载的YOLO模型 yolo_model、输入图像文件 "0070.jpg"、锚点信息 anchors 和类别名称列表 class_names 传递给 predict 函数。

执行这行代码后,函数将会执行目标检测操作,然后返回一个包含了检测结果的图像 img,该图像显示了检测到的车辆边框、概率值和类别标签。