机器学习周报第36期

目录

  • 一、文献阅读
    • 1.1 摘要
    • 1.2 论文背景
    • 1.3 论文背景
    • 1.4 视频处理特征传播
    • 1.5 论文方法
  • 二、相关代码

一、文献阅读

论文标题:Object Detection in Videos by High Quality Object Linking

1.1 摘要

与静态图像中的目标检测相比,视频中的目标检测由于图像质量下降而更具挑战性。许多以前的方法都通过链接视频中的相同对象以形成管状结构,并在管状结构中聚合分类得分,从而利用时间上下文信息。这些方法首先使用静态图像检测器来检测每帧中的对象,然后根据不同帧中对象框之间的空间重叠情况或预测相邻帧之间的对象移动情况,来链接这些检测到的对象。

在本文中,我们专注于获得高质量的对象链接结果以实现更好的分类。与以前通过检查相邻帧之间的框来链接对象的方法不同,我们建议在同一帧中链接。为了实现这一目标,我们在以下方面扩展了现有方法:(1)长方体提议网络,提取限制对象运动的时空候选长方体; (2)短tubelet检测网络,检测短视频片段中的短tubelet; (3)短管连接算法,其将时间上重叠的短管连接成长管。在 ImageNet VID 数据集上的实验表明,我们的方法优于静态图像检测器和之前的技术水平。特别是,对于快速移动的物体,我们的方法比静态图像检测器的结果提高了 8.8%。

1.2 论文背景

由于物体运动,同一物体在相邻帧中的位置和外观会发生变化,这可能导致相邻帧中同一物体的边界框之间的空间重叠不足,或者预测的对象移动不够准确。这会影响对象链接的质量,特别是对于快速移动的对象。相比之下,在同一帧内,如果两个边界框有足够的空间重叠,那么它们显然对应于同一物体。基于这些事实,我们提出在同一帧内链接对象,而不是在相邻帧之间,以实现高质量的对象链接。

许多以前的方法都通过链接视频中的相同对象以形成管状结构,并在管状结构中聚合分类得分,从而利用时间上下文信息。这些方法首先使用静态图像检测器来检测每帧中的对象,然后根据不同帧中对象框之间的空间重叠情况或预测相邻帧之间的对象移动情况,来链接这些检测到的对象。

1.3 论文背景

首先将长视频分割成一些时间上重叠的短视频片段。对于每个短视频片段,我们通过将静态图像的区域提议网络 扩展为短视频片段的立方体提议网络,提取出一组立方体提议,即时空候选立方体,它们能够界定对象的运动。位于同一立方体中的跨帧对象被视为同一对象。立方体提议的主要好处是能够在同一帧中实现对象链接,并且它本身就能带来较小的检测性能提升。

这里的静态图像区域提议网络(Region Proposal Network,RPN)是一种用于生成目标候选区域的深度神经网络结构,它通常与卷积神经网络(CNN)结合使用,以在静态图像中识别可能包含目标对象的区域。RPN的核心思想是通过在CNN特征图上的滑动窗口来生成一系列候选区域(也称为锚点或提议)。这些滑动窗口在特征图的不同位置和尺度上进行遍历,每个位置都生成多个不同尺度和长宽比的候选区域。每个候选区域都通过RPN输出一个分数,表示该区域包含目标对象的可能性,以及该区域的精确边界框坐标。RPN通常与Fast R-CNN或Faster R-CNN等目标检测算法结合使用。在这些算法中,RPN首先生成候选区域,然后这些区域被送入后续的卷积层进行分类和边界框回归,以得到最终的目标检测结果。RPN的设计使得目标检测算法能够高效地生成高质量的候选区域,从而提高了检测速度和精度。它已经成为了现代目标检测算法中不可或缺的一部分,并在许多计算机视觉任务中取得了显著的效果。

对于每个立方体提议,我们调整Fast R-CNN来检测短管状物体。更具体地说,我们分别计算每帧中精确的边界框位置和分类得分,形成一个短管状物体,代表短视频片段中链接的对象边界框。我们通过聚合跨帧的边界框分类得分来计算管状物体的分类得分。此外,为了去除空间上冗余的短管状物体,我们将标准的非极大值抑制(NMS)扩展为管状物体重叠测量,这可以防止在逐帧NMS中可能发生的管状物体断裂。通过短管状物体考虑短距离时间上下文有助于检测。

最后,我们将具有足够重叠度的跨时间重叠的短视频片段中的短管状物体进行链接。如果两个盒子来自于两个相邻短管状物体的时间重叠帧(即同一帧),并且具有足够的空间重叠度,则这两个对应的短管状物体会被链接并合并。这里的“盒子”指的是在某一帧中检测到的对象的边界框。如果两个来自相邻短管状物体的盒子(即两个边界框)在时间上重叠的帧(即同一帧)中有足够的空间重叠,那么它们可能代表的是同一个对象。我们利用对象链接来提高分类质量,通过聚合链接管状物体的分类得分来提升正检测的分类得分。
在这里插入图片描述

1.4 视频处理特征传播

  • 特征传播无对象链接
    特征传播是一种技术,用于增强当前帧的特征信息。这通常是通过聚合从相邻帧中传播过来的特征来实现的。这样的方法有助于提升视频处理的准确性,因为它考虑了时间上的连续性,使得每一帧的特征信息不再孤立。无对象链接没有执行对象链接。对象链接是指将不同帧中检测到的同一对象进行关联,形成一个连贯的轨迹。这种链接有助于更准确地识别和跟踪视频中的对象。因此,尽管这些特征传播方法可以增强当前帧的特征信息,但它们并没有利用对象链接来进一步提升性能。
  • 带对象链接的特征传播
    管状物体提议网络首先通过在第一帧中生成静态对象提议,然后预测后续帧中这些对象的相对运动,来计算管状物体。通过使用CNN-LSTM网络,将管状物体中盒子的特征传播到每个盒子进行分类。除了无对象链接的特征传播外,还链接了相邻帧中的对象以进行特征传播。更具体地说,预测当前帧中每个提议在相邻帧中的相对运动,并将相邻帧中盒子的特征通过平均池化传播到当前帧中对应的盒子。与这些方法不同,我们在同一帧中链接对象,并在帧之间传播盒子得分而不是特征。此外,我们直接为视频片段生成时空立方体提议,而不是像中那样生成每帧提议。
  • 带对象链接的得分传播。
    第一种方式追踪当前帧中检测到的盒子到其相邻帧,以增强它们的原始检测结果,从而提高对象召回率。同时,得分也被传播以改善分类准确性。这种链接是基于盒子内的平均光流向量。第二种方式使用跟踪算法将对象链接成长管状物体,然后采用分类器来聚合管状物体中的检测得分。Seq-NMS方法通过检查相邻帧中盒子之间的空间重叠来链接对象,而不考虑运动信息,然后聚合链接对象的得分作为最终得分。在中的方法同时预测两个帧中的对象位置以及从前一帧到当前帧的对象运动。然后,他们使用这些运动信息将检测到的对象链接成管状物体。同一管状物体中的对象检测得分通过以某种方式聚合该管状物体中的得分来重新加权。

1.5 论文方法

阶段一:为短视频片段生成立方体提议

在这个阶段,系统针对每一个短视频片段(这些片段是原始视频在时间上的分段,且相互之间存在重叠部分),生成一组立方体(或称为容器)。这些立方体旨在跨越多帧绑定相同的对象,即它们表示了对象在连续帧中的可能位置和范围。这些立方体提议是后续处理的基础,帮助系统确定哪些区域可能包含需要关注的对象。

阶段二:短视频片段的短管状物体检测

在有了立方体提议之后,系统进入第二个阶段。对于每一个立方体提议,系统尝试回归(即调整边界框的位置和大小以更准确地匹配对象)并分类一个短管状物体。这个短管状物体实际上是一个边界框的序列,每个边界框都对应视频中的一帧,并定位了那一帧中的对象。为了避免冗余和重叠,系统还会使用非极大值抑制技术来去除那些在空间上过于接近的短管状物体。这些短管状物体代表了短视频片段中对象跨帧的连续存在。

阶段三:整个视频的短管状物体链接

在完成了前两个阶段之后,系统进入第三个阶段,即链接整个视频中的短管状物体。由于视频被分为了时间上重叠的短视频片段,每个片段都生成了自己的短管状物体。在这一阶段,系统需要将这些时间上重叠的短管状物体连接起来,以形成跨整个视频的对象轨迹。这样做可以确保对象在整个视频中的连续性和一致性。同时,通过链接短管状物体,系统还可以进一步优化和细化对象的分类得分,提高对象检测的准确性。

综上,这三个阶段构成了一个完整的视频对象检测与链接流程。前两个阶段为对象检测提供了基础,而第三个阶段则确保了对象在整个视频中的连续跟踪和准确分类。这种方法的优点在于它能够处理视频中的时间连续性和对象运动,从而提高了对象检测的准确性和可靠性。
在这里插入图片描述

二、相关代码

yolov5检测代码如下:

import argparse
import time
from pathlib import Path

import cv2
import torch
import torch.backends.cudnn as cudnn
from numpy import random

from models.experimental import attempt_load
from utils.datasets import LoadStreams, LoadImages
from utils.general import check_img_size, check_requirements, check_imshow, non_max_suppression, apply_classifier, \
    scale_coords, xyxy2xywh, strip_optimizer, set_logging, increment_path
from utils.plots import plot_one_box
from utils.torch_utils import select_device, load_classifier, time_synchronized


def detect(save_img=False):
    source, weights, view_img, save_txt, imgsz = opt.source, opt.weights, opt.view_img, opt.save_txt, opt.img_size
    save_img = not opt.nosave and not source.endswith('.txt')  # save inference images
    webcam = source.isnumeric() or source.endswith('.txt') or source.lower().startswith(
        ('rtsp://', 'rtmp://', 'http://', 'https://'))

    # Directories
    save_dir = Path(increment_path(Path(opt.project) / opt.name, exist_ok=opt.exist_ok))  # increment run
    (save_dir / 'labels' if save_txt else save_dir).mkdir(parents=True, exist_ok=True)  # make dir

    # Initialize
    set_logging()
    device = select_device(opt.device)
    half = device.type != 'cpu'  # half precision only supported on CUDA

    # Load model
    model = attempt_load(weights, map_location=device)  # load FP32 model
    stride = int(model.stride.max())  # model stride
    imgsz = check_img_size(imgsz, s=stride)  # check img_size
    if half:
        model.half()  # to FP16

    # Second-stage classifier
    classify = False
    if classify:
        modelc = load_classifier(name='resnet101', n=2)  # initialize
        modelc.load_state_dict(torch.load('weights/resnet101.pt', map_location=device)['model']).to(device).eval()

    # Set Dataloader
    vid_path, vid_writer = None, None
    if webcam:
        view_img = check_imshow()
        cudnn.benchmark = True  # set True to speed up constant image size inference
        dataset = LoadStreams(source, img_size=imgsz, stride=stride)
    else:
        dataset = LoadImages(source, img_size=imgsz, stride=stride)

    # Get names and colors
    names = model.module.names if hasattr(model, 'module') else model.names
    colors = [[random.randint(0, 255) for _ in range(3)] for _ in names]

    # Run inference
    if device.type != 'cpu':
        model(torch.zeros(1, 3, imgsz, imgsz).to(device).type_as(next(model.parameters())))  # run once
    t0 = time.time()
    for path, img, im0s, vid_cap in dataset:
        img = torch.from_numpy(img).to(device)
        img = img.half() if half else img.float()  # uint8 to fp16/32
        img /= 255.0  # 0 - 255 to 0.0 - 1.0
        if img.ndimension() == 3:
            img = img.unsqueeze(0)

        # Inference
        t1 = time_synchronized()
        pred = model(img, augment=opt.augment)[0]

        # Apply NMS
        pred = non_max_suppression(pred, opt.conf_thres, opt.iou_thres, classes=opt.classes, agnostic=opt.agnostic_nms)
        t2 = time_synchronized()

        # Apply Classifier
        if classify:
            pred = apply_classifier(pred, modelc, img, im0s)

        # Process detections
        for i, det in enumerate(pred):  # detections per image
            if webcam:  # batch_size >= 1
                p, s, im0, frame = path[i], '%g: ' % i, im0s[i].copy(), dataset.count
            else:
                p, s, im0, frame = path, '', im0s, getattr(dataset, 'frame', 0)

            p = Path(p)  # to Path
            save_path = str(save_dir / p.name)  # img.jpg
            txt_path = str(save_dir / 'labels' / p.stem) + ('' if dataset.mode == 'image' else f'_{frame}')  # img.txt
            s += '%gx%g ' % img.shape[2:]  # print string
            gn = torch.tensor(im0.shape)[[1, 0, 1, 0]]  # normalization gain whwh
            if len(det):
                # Rescale boxes from img_size to im0 size
                det[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0.shape).round()

                # Print results
                for c in det[:, -1].unique():
                    n = (det[:, -1] == c).sum()  # detections per class
                    s += f"{n} {names[int(c)]}{'s' * (n > 1)}, "  # add to string

                # Write results
                for *xyxy, conf, cls in reversed(det):
                    if save_txt:  # Write to file
                        xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist()  # normalized xywh
                        line = (cls, *xywh, conf) if opt.save_conf else (cls, *xywh)  # label format
                        with open(txt_path + '.txt', 'a') as f:
                            f.write(('%g ' * len(line)).rstrip() % line + '\n')

                    if save_img or view_img:  # Add bbox to image
                        label = f'{names[int(cls)]} {conf:.2f}'
                        plot_one_box(xyxy, im0, label=label, color=colors[int(cls)], line_thickness=3)

            # Print time (inference + NMS)
            print(f'{s}Done. ({t2 - t1:.3f}s)')

            # Stream results
            if view_img:
                cv2.imshow(str(p), im0)
                cv2.waitKey(1)  # 1 millisecond

            # Save results (image with detections)
            if save_img:
                if dataset.mode == 'image':
                    cv2.imwrite(save_path, im0)
                else:  # 'video' or 'stream'
                    if vid_path != save_path:  # new video
                        vid_path = save_path
                        if isinstance(vid_writer, cv2.VideoWriter):
                            vid_writer.release()  # release previous video writer
                        if vid_cap:  # video
                            fps = vid_cap.get(cv2.CAP_PROP_FPS)
                            w = int(vid_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
                            h = int(vid_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
                        else:  # stream
                            fps, w, h = 30, im0.shape[1], im0.shape[0]
                            save_path += '.mp4'
                        vid_writer = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))
                    vid_writer.write(im0)

    if save_txt or save_img:
        s = f"\n{len(list(save_dir.glob('labels/*.txt')))} labels saved to {save_dir / 'labels'}" if save_txt else ''
        print(f"Results saved to {save_dir}{s}")

    print(f'Done. ({time.time() - t0:.3f}s)')


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', nargs='+', type=str, default='yolov5s.pt', help='model.pt path(s)')
    parser.add_argument('--source', type=str, default='data/images', help='source')  # file/folder, 0 for webcam
    parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)')
    parser.add_argument('--conf-thres', type=float, default=0.25, help='object confidence threshold')
    parser.add_argument('--iou-thres', type=float, default=0.45, help='IOU threshold for NMS')
    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--view-img', action='store_true', help='display results')
    parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
    parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
    parser.add_argument('--nosave', action='store_true', help='do not save images/videos')
    parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 0 2 3')
    parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
    parser.add_argument('--augment', action='store_true', help='augmented inference')
    parser.add_argument('--update', action='store_true', help='update all models')
    parser.add_argument('--project', default='runs/detect', help='save results to project/name')
    parser.add_argument('--name', default='exp', help='save results to project/name')
    parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
    opt = parser.parse_args()
    print(opt)
    check_requirements(exclude=('pycocotools', 'thop'))

    with torch.no_grad():
        if opt.update:  # update all models (to fix SourceChangeWarning)
            for opt.weights in ['yolov5s.pt', 'yolov5m.pt', 'yolov5l.pt', 'yolov5x.pt']:
                detect()
                strip_optimizer(opt.weights)
        else:
            detect()

运行结果如图:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/521227.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

瑞_Redis_商户查询缓存_添加Redis缓存缓存更新策略

文章目录 项目介绍1 短信登录2 商户查询缓存2.1 什么是缓存2.1.1 缓存的应用场景2.1.2 为什么要使用缓存2.1.3 Web应用中缓存的作用2.1.4 Web应用中缓存的成本 2.2 添加Redis缓存2.2.1 背景2.2.2 缓存模型和思路2.2.3 代码实现2.2.4 测试附:IDEA控制台输出自动换行设…

专注项目管理的Mac工具 - Project Office Pro 最新版

Project Office Pro for Mac是一款功能强大的项目管理软件,旨在帮助用户更好地管理和跟踪项目进展,提高工作效率和质量。以下是该软件的主要功能介绍: 项目创建与编辑:用户可以根据自己的需求自定义项目计划,包括设置…

如何在 Ubuntu 上安装和配置 Tomcat 服务器?

简介:最近有粉丝朋友在问如何在 Ubuntu 上安装和配置 Tomcat 服务器?今天特地写这篇文章进行解答,希望能够帮助到大家。 文章目录 Ubuntu上安装和配置Tomcat的详细步骤Tomcat在Linux环境下的安装与配置一、下载并上传Tomcat压缩包二、启动To…

《图解Vue3.0》- 调试

如何对vue3项目进行调试 调试是开发过程中必备的一项技能,掌握了这项技能,可以很好的定义bug所在。一般在开发vue3项目时,有三种方式。 代码中添加debugger;使用浏览器调试:sourcemap需启用vs code 调试:先开启node服…

735.小行星碰撞

题目:给定一个整数数组 asteroids,表示在同一行的小行星。 对于数组中的每一个元素,其绝对值表示小行星的大小,正负表示小行星的移动方向(正表示向右移动,负表示向左移动)。每一颗小行星以相同…

【智能排班系统】雪花算法生成分布式ID

文章目录 雪花算法介绍起源与命名基本原理与结构优势与特点应用场景 代码实现代码结构自定义机器标识RandomWorkIdChooseLocalRedisWorkIdChooselua脚本 实体类SnowflakeIdInfoWorkCenterInfo 雪花算法类配置类雪花算法工具类 说明 雪花算法介绍 在复杂而庞大的分布式系统中&a…

Pnpm + Turbo 搭建 Web Component Monorepo 组件库

技术选型 使用 Pnpm Turbo 搭建 Web Component Monorepo项目 stencil-component-ui 组件库 pnpm 作为包管理器Turborepo 作为构建系统Vitepress 管理文档 pnpm 技术 什么是 pnpm? 它有哪些优势? pnpm 跟 npm、yarn一样,都是用于管理Node包依赖的管…

构建连接世界的高校海外系统:功能架构解析与思考

随着全球化的深入发展,越来越多的高校开始面向海外拓展,建立起跨国合作与交流的桥梁。而为了更好地管理和服务海外学生、教职员工以及校友,高校海外系统的功能架构显得尤为重要。本文将深入探讨高校海外系统的功能架构设计,以及如…

免注册,ChatGPT可即时访问了!

AI又有啥进展?一起看看吧 Apple进军个人家用机器人 Apple在放弃自动驾驶汽车项目并推出混合现实头显后,正在进军个人机器人领域,处于开发家用环境机器人的早期阶段 报告中提到了两种可能的机器人设计。一种是移动机器人,可以跟…

【STM32】存储器和位带映射(bit band mapping)

文章目录 0 前言1 关于地址和存储器2 STM32内部存储器3 位带映射(bit band mapping)4 扩展:IAP 0 前言 最近在研究stm32标准库,对使用宏定义实现位操作的函数非常感兴趣,简单的一句PAout(1) 0;就能实现某个引脚电平的…

lua学习笔记7(函数的学习)

print("*****************************函数的学习*******************************") print("*****************************无参数无返回值函数的学习*******************************") function f1()print("f1函数") end f1() f2function()--…

隐私计算实训营学习九:隐语多方安全计算在安全核对的行业实践

文章目录 一、业务背景:安全核对产生的土壤二、产品方案:从试点到规模化的路三、技术共建:与隐语的共同成长 一、业务背景:安全核对产生的土壤 业务背景:很多粗放使用数据的方式被新出台的法律法规所规范,…

【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(七)- 向量算术指令格式

1. 引言 以下是《riscv-v-spec-1.0.pdf》文档的关键内容: 这是一份关于向量扩展的详细技术文档,内容覆盖了向量指令集的多个关键方面,如向量寄存器状态映射、向量指令格式、向量加载和存储操作、向量内存对齐约束、向量内存一致性模型、向量…

【unity】【C#】延时调用(协程)和场景管理

文章目录 什么是协程协程的应用 - IEnumerator如何控制协程的暂停协程的另一种写法 - Invoke场景管理 多看代码块中的注释 什么是协程 A coroutine alows vou to spreacwhere it left off on the following anc return control toolinencoeframe. 协程允许您将任务分布在多个帧…

拦截器抛出异常无法被全局异常处理器捕获问题

文章目录 基本说明问题描述问题原因解决方法前端执行的所有请求都通过Controller,而不是直接访问html定义一个/error路径的方法 总结 基本说明 我的前后端项目是放在一起的,前后端都是由springMVC进行控制,但是现在我在拦截器的preHandle方法…

HAL STM32主从定时器联级使用

HAL STM32主从定时器联级使用 具体介绍参考STM32参考手册 🌿主从定时器联级:使用一个定时器作为另一个定时器的预分频器。 🍁时钟关系: 🌿TIM1 和TIM8 控制寄存器 2(TIMx_CR2)相关位: 🔖主…

Redis性能管理及主从复制、哨兵的配置与部署

一、redis性能管理 1.1 查看Redis内存使用 1.2 内存碎片率 1.3 内存使用率 1.3.1 避免内存交换发生的方法 1.4 内回收key 1.4.1 配置文件中修改 maxmemory-policy 属性值 1.5 缓存穿透 1.5.1 原因 1.5.2 条件 1.5.3 解决方案 1.6 缓存击穿 1.6.1 原因 1.6.2 现象…

移位运算与乘法

描述 题目描述: 已知d为一个8位数,请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效(d给出的信号的上升沿表示写入有效) 信号示意图: 波形示意图: 输入描述&#…

Leetcode 215. 数组中的第K个最大元素

心路历程: 这道题本质上是排序不完全的过程,而且这道题有bug,直接用python的排序算法其实就能AC。 可以按照快排排到找到k-1个large元素的思维去做,不过这道题需要考虑空间复杂度,所以需要用指针快排。 其实也可以考虑…

SUPS:一种用于自动驾驶的仿真地下泊车场景数据集

SUPS:一种用于自动驾驶的仿真地下泊车场景数据集 附赠自动驾驶学习资料和量产经验:链接 摘要 本文介绍了SUPS:一种用于自动驾驶的仿真地下泊车场景数据集。随着自动驾驶的范围扩大,自动地下泊车引起了人们极大的关注。自动驾驶汽…