Python 使用 Detectron2 进行目标检测 (Detectron2, CenterNet2, Detic)

news2024/9/24 1:20:17

代码说明

代码主要是一个用来演示如何使用 Detectron2 进行目标检测的脚本。它可以从摄像头或视频文件中读取图像,并应用指定的配置文件进行目标检测。其中,Detectron2 结合了 CenterNet2 和 Detic 进行目标检测。
 
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

 
 

主要库介绍

Detectron2

Detectron2是由Facebook AI Research开发的一个用于目标检测和实例分割的开源库。它提供了一系列预训练模型和灵活的配置系统,使得用户可以方便地进行模型训练和推理。

主要功能:

  • 支持多种目标检测和分割任务,如Faster R-CNN、Mask R-CNN等。
  • 提供模块化设计,易于扩展和定制。
  • 高效的训练和推理性能,支持GPU加速。

 

CenterNet2

CenterNet2是一个基于单阶段检测器CenterNet的目标检测框架。它通过在CenterNet的基础上添加更多特性和优化,进一步提升了检测性能和准确率。

主要功能:

  • 单阶段检测,速度快。
  • 通过热力图进行目标中心点定位。
  • 支持多个检测任务,如物体检测、姿态估计等。

 

Detic

Detic是一个用于开放词汇表目标检测的库。它允许用户在推理时使用自定义的词汇表,而不需要重新训练模型。这使得它在处理新的目标类别时更加灵活和高效。

主要功能:

  • 支持开放词汇表目标检测。
  • 可以在推理时动态加载自定义词汇表。
  • 兼容Detectron2框架,易于集成和使用。

 
 

主要代码

# Copyright (c) Facebook, Inc. and its affiliates.
import argparse
import glob
import multiprocessing as mp
import numpy as np
import os
import tempfile
import time
import warnings
import cv2
import tqdm
import sys
import mss

# 导入Detectron2配置和工具
from detectron2.config import get_cfg
from detectron2.data.detection_utils import read_image
from detectron2.utils.logger import setup_logger

sys.path.insert(0, 'third_party/CenterNet2/')  # 添加CenterNet2库路径
from centernet.config import add_centernet_config  # 导入CenterNet2配置函数
from detic.config import add_detic_config  # 导入Detic配置函数

from detic.predictor import VisualizationDemo  # 导入Detic可视化演示类

# Fake a video capture object OpenCV style - half width, half height of first screen using MSS
# 模拟一个OpenCV风格的视频捕获对象 - 使用MSS库截取屏幕的一部分
class ScreenGrab:
    def __init__(self):
        self.sct = mss.mss()  # 初始化MSS库
        m0 = self.sct.monitors[0]  # 获取主屏幕信息
        self.monitor = {'top': 0, 'left': 0, 'width': m0['width'] / 2, 'height': m0['height'] / 2}  # 设置捕获屏幕的区域(宽度和高度减半)

    def read(self):
        img =  np.array(self.sct.grab(self.monitor))  # 捕获屏幕区域图像
        nf = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)  # 转换图像颜色格式
        return (True, nf)

    def isOpened(self):
        return True  # 模拟摄像头打开状态
    def release(self):
        return True  # 模拟摄像头释放资源

# 常量定义
WINDOW_NAME = "Detic"

def setup_cfg(args):
    cfg = get_cfg()  # 获取Detectron2默认配置
    if args.cpu:
        cfg.MODEL.DEVICE = "cpu"  # 设置使用CPU
    add_centernet_config(cfg)  # 添加CenterNet2配置
    add_detic_config(cfg)  # 添加Detic配置
    cfg.merge_from_file(args.config_file)  # 从文件合并配置
    cfg.merge_from_list(args.opts)  # 从命令行参数合并配置
    # 设置模型的阈值
    cfg.MODEL.RETINANET.SCORE_THRESH_TEST = args.confidence_threshold
    cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = args.confidence_threshold
    cfg.MODEL.PANOPTIC_FPN.COMBINE.INSTANCES_CONFIDENCE_THRESH = args.confidence_threshold
    cfg.MODEL.ROI_BOX_HEAD.ZEROSHOT_WEIGHT_PATH = 'rand'  # 后续加载
    if not args.pred_all_class:
        cfg.MODEL.ROI_HEADS.ONE_CLASS_PER_PROPOSAL = True  # 每个提案只检测一个类别
    cfg.freeze()  # 冻结配置
    return cfg

def get_parser():
    parser = argparse.ArgumentParser(description="Detectron2 demo for builtin configs")  # 创建参数解析器
    parser.add_argument(
        "--config-file",
        default="configs/quick_schedules/mask_rcnn_R_50_FPN_inference_acc_test.yaml",
        metavar="FILE",
        help="path to config file",  # 配置文件路径
    )
    parser.add_argument("--webcam", help="Take inputs from webcam.")  # 摄像头输入
    parser.add_argument("--cpu", action='store_true', help="Use CPU only.")  # 使用CPU
    parser.add_argument("--video-input", help="Path to video file.")  # 视频文件输入路径
    parser.add_argument(
        "--input",
        nargs="+",
        help="A list of space separated input images; "
        "or a single glob pattern such as 'directory/*.jpg'",  # 输入图像列表或模式
    )
    parser.add_argument(
        "--output",
        help="A file or directory to save output visualizations. "
        "If not given, will show output in an OpenCV window.",  # 输出结果保存路径
    )
    parser.add_argument(
        "--vocabulary",
        default="lvis",
        choices=['lvis', 'openimages', 'objects365', 'coco', 'custom'],
        help="Vocabulary type for Detic",  # 词汇表类型
    )
    parser.add_argument(
        "--custom_vocabulary",
        default="",
        help="Path to custom vocabulary file",  # 自定义词汇表路径
    )
    parser.add_argument("--pred_all_class", action='store_true')  # 预测所有类别
    parser.add_argument(
        "--confidence-threshold",
        type=float,
        default=0.5,
        help="Minimum score for instance predictions to be shown",  # 置信度阈值
    )
    parser.add_argument(
        "--opts",
        help="Modify config options using the command-line 'KEY VALUE' pairs",
        default=[],
        nargs=argparse.REMAINDER,
    )
    return parser

def test_opencv_video_format(codec, file_ext):
    with tempfile.TemporaryDirectory(prefix="video_format_test") as dir:  # 创建临时目录
        filename = os.path.join(dir, "test_file" + file_ext)
        writer = cv2.VideoWriter(
            filename=filename,
            fourcc=cv2.VideoWriter_fourcc(*codec),
            fps=float(30),
            frameSize=(10, 10),
            isColor=True,
        )
        [writer.write(np.zeros((10, 10, 3), np.uint8)) for _ in range(30)]  # 写入空白帧
        writer.release()
        if os.path.isfile(filename):
            return True  # 如果文件存在,返回True
        return False  # 否则返回False

if __name__ == "__main__":
    mp.set_start_method("spawn", force=True)  # 设置多进程启动方式
    args = get_parser().parse_args()  # 解析命令行参数
    setup_logger(name="fvcore")  # 设置日志记录器
    logger = setup_logger()  # 获取日志记录器
    logger.info("Arguments: " + str(args))  # 记录参数信息

    cfg = setup_cfg(args)  # 设置配置

    demo = VisualizationDemo(cfg, args)  # 创建可视化演示对象

    if args.input:  # 如果有输入图像
        if len(args.input) == 1:
            args.input = glob.glob(os.path.expanduser(args.input[0]))  # 获取输入图像路径
            assert args.input, "The input path(s) was not found"
        for path in tqdm.tqdm(args.input, disable=not args.output):  # 遍历输入图像
            img = read_image(path, format="BGR")  # 读取图像
            start_time = time.time()
            predictions, visualized_output = demo.run_on_image(img)  # 运行检测
            logger.info(
                "{}: {} in {:.2f}s".format(
                    path,
                    "detected {} instances".format(len(predictions["instances"]))
                    if "instances" in predictions
                    else "finished",
                    time.time() - start_time,
                )
            )

            if args.output:  # 如果有输出路径
                if os.path.isdir(args.output):
                    assert os.path.isdir(args.output), args.output
                    out_filename = os.path.join(args.output, os.path.basename(path))  # 构建输出文件名
                else:
                    assert len(args.input) == 1, "Please specify a directory with args.output"
                    out_filename = args.output
                visualized_output.save(out_filename)  # 保存可视化结果
            else:
                cv2.namedWindow(WINDOW_NAME, cv2.WINDOW_NORMAL)  # 创建窗口
                cv2.imshow(WINDOW_NAME, visualized_output.get_image()[:, :, ::-1])  # 显示图像
                if cv2.waitKey(0) == 27:
                    break  # 按Esc键退出
    elif args.webcam:  # 如果从摄像头读取
        assert args.input is None, "Cannot have both --input and --webcam!"
        assert args.output is None, "output not yet supported with --webcam!"
        if args.webcam == "screen":
            cam = ScreenGrab()  # 使用屏幕捕获
        else:
            cam = cv2.VideoCapture(int(args.webcam))  # 打开摄像头
        for vis in tqdm.tqdm(demo.run_on_video(cam)):  # 遍历视频帧
            cv2.namedWindow(WINDOW_NAME, cv2.WINDOW_NORMAL)  # 创建窗口
            cv2.imshow(WINDOW_NAME, vis)  # 显示视频帧
            if cv2.waitKey(1) == 27:
                break  # 按Esc键退出
        cam.release()
        cv2.destroyAllWindows()  # 释放资源
    elif args.video_input:  # 如果从视频文件读取
        video = cv2.VideoCapture(args.video_input)  # 打开视频文件
        width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))  # 获取视频宽度
        height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 获取视频高度
        frames_per_second = video.get(cv2.CAP_PROP_FPS)  # 获取视频帧率
        num_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))  # 获取视频帧数
        basename = os.path.basename(args.video_input)  # 获取视频文件名
        codec, file_ext = (
            ("x264", ".mkv") if test_opencv_video_format("x264", ".mkv") else ("mp4v", ".mp4")
        )
        if codec == ".mp4v":
            warnings.warn("x264 codec not available, switching to mp4v")  # 切换到mp4v编码
        if args.output:
            if os.path.isdir(args.output):
                output_fname = os.path.join(args.output, basename)  # 输出文件路径
                output_fname = os.path.splitext(output_fname)[0] + file_ext
            else:
                output_fname = args.output
            assert not os.path.isfile(output_fname), output_fname
            output_file = cv2.VideoWriter(
                filename=output_fname,
                fourcc=cv2.VideoWriter_fourcc(*codec),
                fps=float(frames_per_second),
                frameSize=(width, height),
                isColor=True,
            )
        assert os.path.isfile(args.video_input)
        for vis_frame in tqdm.tqdm(demo.run_on_video(video), total=num_frames):
            if args.output:
                output_file.write(vis_frame)  # 写入视频文件
            else:
                cv2.namedWindow(basename, cv2.WINDOW_NORMAL)  # 创建窗口
                cv2.imshow(basename, vis_frame)  # 显示输出
                if cv2.waitKey(1) == 27:
                    break  # 按ESC退出
        video.release()  # 释放视频文件
        if args.output:
            output_file.release()  # 释放输出文件
        else:
            cv2.destroyAllWindows()  # 销毁所有窗口

 
 
 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UMG文本控件(UTextBlock)超过边界区域以后显示省略号

测试版本:UE5.4.1 UMG文本控件超过边界区域以后显示省略号

基于springboot+vue+uniapp的校园快递平台小程序

开发语言:Java框架:springbootuniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包&#…

【打家劫舍】python刷题记录

R3-递归篇。第100篇blog. 思路: 和爬楼梯有点相似,每次隔1格,2格,3格----(隔3格就亏了,所以还是类似爬楼梯问题,1格或者2格) class Solution:def rob(self, nums: List[int]) -> int:cur,pre0,0for nu…

科普文:Linux目录详解

在 Linux/Unix 操作系统中,一切都是文件,甚至目录也是文件,文件是文件,鼠标、键盘、打印机等设备也是文件。 这篇文章,我们将一起学习 Linux 中的目录结构及文件。 Linux 的文件类型 Linux系统中的文件系统&#xf…

图片太大怎么压缩变小?图片太大压缩变小的几个方法

图片太大怎么压缩变小?在当今数字化时代,图像的处理和分享已经成为日常工作和生活中不可或缺的一部分。然而,有时我们会遇到一个普遍的问题:图片文件太大,需要压缩以便于存储、传输或发布。为什么要压缩图片呢&#xf…

【PCB prepreg】PP 参数比选 四 <预浸料树脂流>

预浸料树脂在压力下加热时会熔化和流动。这通常被称为树脂流动。树脂的流动取决于压力和树脂使用的热量。树脂可以自由流动的时间有限。在成为流体一段时间后,树脂会变成凝胶。 预浸料树脂的流动性对层压操作至关重要,而层压条件会影响这种流动性。此外…

程序员修炼之路

成为一名优秀的程序员,需要广泛而深入地学习多个领域的知识。这些课程不仅帮助建立扎实的编程基础,还培养了问题解决、算法设计、系统思维等多方面的能力。以下是一些核心的必修课: 计算机基础 计算机组成原理:理解计算机的硬件组…

国内备受好评PostgreSQL数据库性能如何?

为什么国内很多数据库采用PostgreSQL数据库作为基础,再次开发自己的产品呢?不仅仅是因为PostgreSQL数据库开源免费、PostgreSQL 数据库的性能也是相当出色的,具有以下几个方面的特点: 1. 处理大规模数据: - 能够有效地管理和处…

外设购物平台

目 录 一、系统分析 二、系统设计 2.1 系统功能设计 2.2 数据库设计 三、系统实现 3.1 注册功能 3.2 登录功能 3.3 分页查询所有商品信息功能 3.4 分页条件(精确、模糊)查询商品信息功能 3.5 购物车功能 3.6 订单管理功能 四、项…

javafx的ListView代入项目的使用

目录 1. 创建一个可观察的列表,用于存储ListView中的数据,这里的User是包装了用户的相关信息。 2.通过本人id获取friendid,及好友的id,然后用集合接送,更方便直观一点。 3.用for遍历集合,逐个添加。 4.渲染器&…

css各种使用案例合集(二)

1、hover动画 场景1&#xff1a;要求有旋转、变色&#xff0c;有变化过程 场景结果&#xff1a; 代码示例&#xff1a; <div class"box"><div class"headUp"></div><div class"head"></div><div class"mo…

全面整理人工智能(AI)学习路线图及资源推荐

在人工智能&#xff08;AI&#xff09;飞速发展的今天&#xff0c;掌握AI技术已经成为了许多高校研究者和职场人士的必备技能。从深度学习到强化学习&#xff0c;从大模型训练到实际应用&#xff0c;AI技术的广度和深度不断拓展。作为一名AI学习者&#xff0c;面对浩瀚的知识海…

FPC焊接座子和FPC线的线序问题,弄个转接口

焊接fpc底座 可以发现&#xff0c;也可以焊接上&#xff0c;但在原理图中的顺序连接不同可能导致顺序完全相反 FPC线顺序也可能不同 所以还是弄个转换接口&#xff0c;可是临时测试使用

智能制造有哪些发展阶段?企业推进数字化制造容易走进什么误区?

随着智能制造的浪潮席卷全球&#xff0c;我们正目睹一场前所未有的工业变革。智能制造这一集精益生产、柔性制造、敏捷制造和云制造等先进范式于一体的全新制造模式&#xff0c;正在重塑制造业的未来。 本文将深入探讨智能制造的三个发展阶段&#xff1a;数字化制造、网络化制…

Studying-代码随想录训练营day49| 42. 接雨水、84.柱状图中最大的矩形

第49天&#xff0c;单调栈part02&#xff0c;两个很经典的例题&#xff0c;编程语言&#xff1a;C 目录 42. 接雨水 84.柱状图中最大的矩形 总结&#xff1a; 42. 接雨水 文档讲解&#xff1a;代码随想录接雨水 视频讲解&#xff1a;手撕接雨水 题目&#xff1a; 42. 接雨…

轻松上手Scikit-learn——评估模型性能(准确率、精确率、召回率、ROC和AUC)

轻松上手Scikit-learn——评估模型性能&#xff08;准确率、精确率、召回率、ROC和AUC&#xff09; 安装scikit——learn pip install -U scikit-learn常用模型性能评估指标 在开始介绍之前先规定几个表示&#xff1a; 模型预测正确的正样本&#xff0c;称为真正样本&#…

AI会带来新的就业岗位吗?

最近&#xff0c;百度的首席执行官Roy在世界人工智能大会&#xff08;WAIC&#xff09;上提出了一个观点。他表示&#xff0c;大家无需过于担心人工智能会导致大量失业&#xff0c;相反&#xff0c;人工智能会创造一批新的就业岗位。他特别提到了几个核心的典型代表&#xff0c…

visual Studio怎么设置背景图片

想在visual Studio设置一个自己喜欢的背景图片&#xff0c;效果如下&#xff1a; 废话不多说&#xff0c;以Vs2022为例&#xff0c;操作步骤如下&#xff1a; 1.打开“扩展”>“管理扩展”>“搜索ClaudiaIDe”安装 或者直接下载官方安装版https://kbuchi.gallerycdn.vs…

网安科班精选!爱荷华大学教授的网络安全零基础入门教程!

网络就像一把双刃剑&#xff0c;给我们的生活、交流、工作和发展带来了便利&#xff0c;但同时也给信息安全以及个人隐私带来了威胁。网络和信息安全问题不仅影响了网络的普及和应用&#xff0c;还关系到企国家、军队、企业的信息安全和社会的经济安全&#xff0c;让人又爱又恨…

用栈实现队列(双栈思路 + 代码实现)

题目 ①双栈大体思路 1.切入点 栈先进后出&#xff0c;队列先进先出。 两个栈&#xff0c;其中一个栈可以用于颠倒顺序。顺序就跟队列一样 2.明确双栈作用 1.第一个栈接收输入&#xff08;输入栈&#xff09; 2.第二个栈转换顺序&#xff08;输出栈&#xff09; 3.四个功…