YOLOv5:LoadImages类、letterbox函数

【玩转yolov5】来自茱丽叶的letterbox 数据集中的图片一般为长方形,当模型输入为正方形时直接将长方形图片resize为正方形会使得图片失真,采用letterbox(啥意思?邮箱盒子!)通过填充边界(通常是灰色填充)的方式来保持原始图片的长宽比例,同时又满足模型正方形输入的需要。这里以我做训练时使用的一张bdd100k中的图片为例直观感受一下即可。 import cv2 import matplotlib as plt import numpy as np img_size = 640 #yolov5默认输入图片尺寸640x640 ... 阅读详情

前言

  • 由于水平有限,难免出现错漏,敬请批评改正。
  • 更多精彩内容,可点击进入YOLO系列专栏或我的个人主页查看

前提条件

相关介绍

  • Python是一种跨平台的计算机程序设计语言。是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越多被用于独立的、大型项目的开发。
  • Python OS模块是负责程序与操作系统的交互,提供了访问操作系统底层的接口和非常丰富的方法用来处理文件和目录。

letterbox()函数:自适应图片缩放

  • letterbox的主要思想是尽可能地利用网络感受野的信息特征。在YOLOv5中,最后一层的特征图中每个点,可以对应原图中32X32的区域信息,在保证图片变换比例一致的情况下,长宽均可以被32整除,那么就可以有效的利用感受野的信息。
  • 假设原图尺寸为(720, 640),目标缩放尺寸为(640, 640)。要想满足收缩的要求,应该选取收缩比例720 ÷ \div ÷ 640 = 0.88.则图片被缩放为(640,569),然后,要填充边界至可以被stride=32整除,则569填充至576,最终得到图片尺寸为(640, 576)。
import cv2
def letterbox(im, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleFill=False, scaleup=True, stride=32):
    # Resize and pad image while meeting stride-multiple constraints
    # 自适应调整图片大小和填充图像,同时满足stride-multiple约束
    shape = im.shape[:2]  # current shape [height, width]
    if isinstance(new_shape, int):
        new_shape = (new_shape, new_shape)

    # Scale ratio (new / old) 尺度比例 # 计算收缩比
    r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
    if not scaleup:  # only scale down, do not scale up (for better val mAP)
        r = min(r, 1.0)

    # Compute padding # 计算填充信息
    ratio = r, r  # width, height ratios
    # 计算收缩后图片的长宽
    new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
    # print("(w,h):",new_unpad) # (w,h)
    # 计算需要填充的像素,即计算那个需要收缩比大的那一边需要填充的像素
    dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]  # wh padding
    # print('dw, dh:',dw, dh)
    if auto:  # minimum rectangle # 最小矩形区域
        dw, dh = np.mod(dw, stride), np.mod(dh, stride)  # wh padding # mod余数
        # print('dw, dh:',dw, dh)
    elif scaleFill:  # stretch # 直接缩放
        dw, dh = 0.0, 0.0
        new_unpad = (new_shape[1], new_shape[0])
        ratio = new_shape[1] / shape[1], new_shape[0] / shape[0]  # width, height ratios
        # print('dw, dh:',dw, dh)

    dw /= 2  # divide padding into 2 sides
    dh /= 2
    # print('dw, dh:',dw, dh)
    
    if shape[::-1] != new_unpad:  # resize
        im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
    # 缩放图片并填充像素 # round(number)表示四舍五入到最接近的整数
    top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
    left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
    # 填充边界
    im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)  # add border
    return im, ratio, (dw, dh)

if __name__ =="__main__":
    source = '1.jpg'
    im = cv2.imread(source)
    im = cv2.resize(im,(640,720))
    print('原图大小:',im.shape) # (720, 640, 3)
    im, ratio, (dw, dh) = letterbox(im)
    print('缩放后大小:',im.shape) # (640, 576, 3)
原图大小: (720, 640, 3)
缩放后大小: (640, 576, 3)

LoadImages类:读取测试图片数据集

  • LoadImages类实现涉及到两个魔法函数__iter__和__next__,这使其拥有迭代器的特性。
import os
import glob
import cv2
import numpy as np
from pathlib import Path
from utils.augmentations import letterbox

# Parameters
HELP_URL = 'See https://github.com/ultralytics/yolov5/wiki/Train-Custom-Data'
IMG_FORMATS = 'bmp', 'dng', 'jpeg', 'jpg', 'mpo', 'png', 'tif', 'tiff', 'webp', 'pfm'  # include image suffixes
VID_FORMATS = 'asf', 'avi', 'gif', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'ts', 'wmv'  # include video suffixes

class LoadImages:
    # YOLOv5 image/video dataloader, i.e. `python detect.py --source image.jpg/vid.mp4`
    def __init__(self, path, img_size=640, stride=32, auto=True, transforms=None, vid_stride=1):
        print("__init__")
        
        if isinstance(path, str) and Path(path).suffix == ".txt":  # *.txt file with img/vid/dir on each line
            path = Path(path).read_text().rsplit()
            
        files = []
        # 读取所有文件路径进入files列表
        for p in sorted(path) if isinstance(path, (list, tuple)) else [path]:
            p = str(Path(p).resolve())
            if '*' in p:
                files.extend(sorted(glob.glob(p, recursive=True)))  # glob
            elif os.path.isdir(p):
                files.extend(sorted(glob.glob(os.path.join(p, '*.*'))))  # dir
            elif os.path.isfile(p):
                files.append(p)  # files
            else:
                raise FileNotFoundError(f'{p} does not exist')

        images = [x for x in files if x.split('.')[-1].lower() in IMG_FORMATS]
        videos = [x for x in files if x.split('.')[-1].lower() in VID_FORMATS]
        # print(images,videos,sep='\n')
        
        ni, nv = len(images), len(videos) # 图片数量,视频数量

        self.img_size = img_size # 图像大小
        self.stride = stride # 步长
        self.files = images + videos # 所以文件列表
        self.nf = ni + nv  # number of files 
        self.video_flag = [False] * ni + [True] * nv 
        self.mode = 'image'
        self.auto = auto # 默认auto = True
        self.transforms = transforms  # optional ,# 默认transforms = None
        self.vid_stride = vid_stride  # video frame-rate stride # 默认vid_stride=1
        if any(videos): # any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False,则返回 False,如果有一个为 True,则返回 True。
            self._new_video(videos[0])  # new video
        else:
            self.cap = None
        assert self.nf > 0, f'No images or videos found in {p}. ' \
                            f'Supported formats are:\nimages: {IMG_FORMATS}\nvideos: {VID_FORMATS}'

    def __iter__(self):
        print("__iter__")
        self.count = 0
        return self

    def __next__(self):
        print("__next__")
        if self.count == self.nf:
            raise StopIteration
        path = self.files[self.count]

        if self.video_flag[self.count]:
            # Read video
            self.mode = 'video'
            for _ in range(self.vid_stride):
                self.cap.grab()
            ret_val, im0 = self.cap.retrieve()
            while not ret_val:
                self.count += 1
                self.cap.release()
                if self.count == self.nf:  # last video
                    raise StopIteration
                path = self.files[self.count]
                self._new_video(path)
                ret_val, im0 = self.cap.read()

            self.frame += 1
            # im0 = self._cv2_rotate(im0)  # for use if cv2 autorotation is False
            s = f'video {self.count + 1}/{self.nf} ({self.frame}/{self.frames}) {path}: '

        else:
            # Read image
            self.count += 1
            im0 = cv2.imread(path)  # BGR
            assert im0 is not None, f'Image Not Found {path}'
            s = f'image {self.count}/{self.nf} {path}: '

        if self.transforms:
            im = self.transforms(im0)  # transforms
        else:
            im = letterbox(im0, self.img_size, stride=self.stride, auto=self.auto)[0]  # padded resize
            im = im.transpose((2, 0, 1))[::-1]  # HWC to CHW, BGR to RGB
            im = np.ascontiguousarray(im)  # contiguous

        return path, im, im0, self.cap, s
    
if __name__ =="__main__":
    source = '1.jpg'
    imgsz = 640
    stride = 32
    pt = True
    vid_stride = 1
    dataset = LoadImages(source, img_size=imgsz, stride=stride, auto=pt, vid_stride=vid_stride)
    for path, im, im0s, vid_cap, s in dataset:
        print('img_path:',path)
        print('im0s.shape',im0s.shape)
        print('im.shape:',im.shape)
        print('vid_cap:',vid_cap)
        print('相关信息string:',s)        
__init__
__iter__
__next__
img_path: 1.jpg
im0s.shape (416, 416, 3)
im.shape: (3, 640, 640)
vid_cap: None
相关信息string: image 1/1 1.jpg: 
__next__
YOLOv5实战:手把手教你实现letterbox自适应缩放,告别图片变形信息丢失 本文详细介绍了YOLOv5中letterbox自适应缩放技术的实现方法,帮助解决目标检测中图片变形和信息丢失的问题。通过对比直接resize与letterbox的效果,展示了后者在检测精度上的显著优势,并提供了完整的代码实现和优化策略,适用于安全帽检测、车牌识别等多种场景。 阅读详情

相关推荐

YOLOv5实时检测避坑指南:海康工业相机分辨率设置与OpenCV接口调优

本文针对YOLOv5结合海康工业相机进行高分辨率实时检测时遇到的性能瓶颈,提供了全面的优化指南。核心在于通过优化OpenCV的cv2.VideoCapture接口参数、重构YOLOv5数据加载器的预处理流程,并引入多线程流水线设计,有效解决了图像缩放等CPU端处理延迟问题,从而显著提升系统整体帧率,实现流畅的实时检测。

weixin_29065791的博客 104

【玩转yolov5】深入解析letterbox:保持图像比例不失真的秘密武器

本文深入解析了YOLOv5中的letterbox技术,该技术通过智能填充保持图像原始比例,避免目标检测中的失真问题。详细介绍了letterbox的核心实现原理、代码详解及实际应用技巧,帮助开发者提升模型检测精度和推理效率。

weixin_29041195的博客 241

YOLOv5前处理函数 letterbox 详解

输出图像宽 640 高 640,非纯色填充区域宽 640 高 480,顶部灰色填充区域的高度为80,底端灰色填充区域的高度为80。

qq_21603315的博客 288

YOLOv5(PyTorch)目标检测:原理与源码解析

【为什么要学习这门课】 Linux创始人Linus Torvalds有一句名言:Talk is cheap. Show me the code. 冗谈不够,放码过来!代码阅读是从基础到提高的必由之路。 YOLOv5是最近推出的轻量且高性能的实时目标检测方法。YOLOv5使用PyTorch实现,含有很多业界前沿和常用的技巧,可以作为很好的代码阅读案例,让我们深入探究其实现原理,其中不少知识点的代码可以作为相关项目的借鉴。 【课程内容与收获】 本课程将详细解析YOLOv5的实现原理和源码,对关键代码使用PyCharm的debug模式逐行分析解读。 本课程将提供注释后的YOLOv5的源码程序文件。   【相关课程】 本人推出了有关YOLOv5目标检测的系列课程。请持续关注该系列的其它视频课程,包括:《YOLOv5(PyTorch)目标检测实战:训练自己的数据集》Ubuntu系统 https://edu.youkuaiyun.com/course/detail/30793 Windows系统 https://edu.youkuaiyun.com/course/detail/30923 《YOLOv5(PyTorch)目标检测:原理与源码解析》https://edu.youkuaiyun.com/course/detail/31428 《YOLOv5(PyTorch)目标检测实战:Flask Web部署》https://edu.youkuaiyun.com/course/detail/31087 《YOLOv5(PyTorch)目标检测实战:TensorRT加速部署》https://edu.youkuaiyun.com/course/detail/32303

【目标检测-YOLO】YOLOv5-5.0v-数据处理(第三篇)

前文链接: YOLOv5-v5.0-yolov5s网络架构详解(第一篇)_星魂非梦的博客-优快云博客 YOLOv5-5.0v-yaml 解析(第二篇)_星魂非梦的博客-优快云博客 YOLO Input Backbone Neck Head 置信度Loss 坐标回归Loss 分类Loss v1 448*448 GoogleNet FC*2 MSE v2 32x DarkNet-19 Passth.

博观约取,厚积薄发 1万+

数字IC设计(8)之AHB-Lite总线(持续更新)

AHB总线全称Advanced High-performance Bus,意为先进高性能总线。推出该总线的目的是补充APB总线在性能上的不足,APB总线适合挂载低速外设,所以AHB总线用来挂载高性能的外设,这样子可以分工合作,节约资源。AHB总线可以实现多主多从的连接,此时需要设计仲裁机和matrix(矩阵),AHB-Lite一般用于一主多从,此时则不需要仲裁机和matrix,但是也可以用AHB-Lite来实现多主多从,就是设计多个layer,每个layer是一主多从,再把各个layer连起来;

qq_69440734的博客 2255

Yolov5笔记--自适应图片缩放letterbox

简单阐述:letterbox()函数的作用是将图像缩放到指定尺寸,因为直接resize到指定尺寸会导致信息的丢失,而采用等比例缩放的形式,能较好地保留图像的信息;Yolov5采用自适应缩放确保图片宽高值最大为640,同时通过padding填充像素值的方式确保宽高能被32整除,最大程度地利用感受野。

牵一只蜗牛去散步 5745

Windows 10/11下彻底卸载Chrome的终极指南(附一键清理注册表脚本)

本文提供了一份在Windows 10/11系统中彻底卸载Google Chrome浏览器的终极指南。针对标准卸载后用户数据与注册表项残留的问题,文章详细介绍了从应用程序层、用户数据层到系统集成层的三层深度清理方法,并重点提供了安全高效的注册表清理脚本,确保浏览器所有痕迹被完全移除,解决重装冲突并释放磁盘空间。

elastic6hunter的博客 782

【yolo】图像预处理方法letterbox

letterbox被用于LoadImages类的__next__方法中, 用于输入图像尺寸的预处理。letterbox实现了图像调整技术,主要用于深度学习领域中的物体检测任务,确保不同尺寸的输入图像能被模型接受。Letterbox的原理很简单。当输入图像的纵横比与模型所需不一致时,Letterbox会在图像的顶部和底部添加填充(通常是黑色或与背景色相同),以保持纵横比的一致性。填充的宽度会根据纵横比差异进行调整。这种方法可以确保模型能够处理各种纵横比的图像,并减少因纵横比差异导致的问题。

qq_51677409的博客 3557

MATLAB控制信号发生器(USB-GPIB-HS)GPIB仪器控制教程(含matlab代码)

自动化测试时需要自动产生信号,通过matlab控制信号发生器的频率与功率,以实现自动化信号生成输出

qq_43686057的博客 1606

给STM32供电,别只接VDD和GND!VBAT、VDDA这些引脚不接会怎样?

本文深入解析STM32电源设计中VBAT与VDDA引脚的关键作用,揭示仅连接VDD和GND可能导致的ADC精度下降、RTC功能异常等问题。通过实测数据对比不同连接方案,提供包括滤波电路设计、PCB布局布线和双电源自动切换在内的实用解决方案,帮助开发者优化系统稳定性与性能。

weixin_30521161的博客 626

有关YOLOV5在测试时,图片大小被调整的问题

上述操作具体就是通过计算“设置的宽高”与“原图宽高”的比例,计算出最终dw,dh的值,就能确定上下左右需要padding的像素个数,最后通过。代码解析,代码中的备注给出了所有变量的变化过程。

梦在黎明破晓时的博客 2416

FPGA图像处理入门 ZYNQ7020 图像中值膨胀腐蚀滤波

图像处理的三种滤波 中值滤波应用较为广泛 综合膨胀和腐蚀可以实现边缘检测。

Coast_的博客 715

yolov5-master代码详解笔记——detect模块

本文将开始带你进行yolov5-master模块代码详解,该专栏谨适用于python、opencv有一定基础且尝试使用过yolov5-master人士进行参考,不适合小白学习阅读。文章有待更新,敬请期待。

qq_68271367的博客 8206

Kali Linux实战:Aircrack-ng破解Wi-Fi密码的完整流程与常见问题解决

本文详细介绍了在Kali Linux中使用Aircrack-ng套件进行Wi-Fi密码破解的完整流程,包括环境准备、无线网卡配置、网络扫描、握手包捕获与字典破解等关键步骤。同时针对无线网卡不支持监听模式、无法捕获握手包等常见问题提供了实用解决方案,帮助安全研究人员有效评估无线网络安全性。

weixin_29323049的博客 296

Arduino与震动马达模块握手

震动马达模块采用采用高品质手机震动马达,适用于震动感互动产品的制作,可穿戴智能设备震动提醒,适合作为非可听指示器的小型振动马达。当输入为高电平时电动机会震动,就像你的静音模式的手机一样。

vor234的博客 5847

YOLOv5数据集处理模块深度解析

在LoadImagesAndLabels类的初始化过程中,首先会扫描指定路径下的图像文件,并自动匹配对应的标签文件。通过灵活的数据增强策略和高效的数据加载机制,为YOLOv5模型的优异性能提供了坚实的基础。YOLOv5的数据集处理模块是整个训练流程中的重要组成部分,负责数据的加载、预处理和增强。对于矩形训练模式,系统会根据图像的宽高比对batch内的图像进行分组,将相似宽高比的图像放在同一个batch中。可以在训练过程中保存增强后的图像,检查数据增强是否按预期工作,边界框是否正确变换。

2301_77531158的博客 274

[系统安全] 一.什么是逆向分析、逆向分析基础及经典扫雷游戏逆向

娜璋AI安全之家于2020年8月18日开通,将专注于Python和安全技术,主要分享Web渗透、系统安全、CVE复现、威胁情报分析、人工智能、大数据分析、恶意代码检测等文章。真心想把自己近十年的所学所做所感分享出来,与大家一起进步。 系统安全系列作者将深入研究恶意样本分析、逆向分析、攻防实战等,通过在线笔记和实践操作的形式分享与博友们学习,希望能与您一起进步。第一篇文章先带领大家学习什么是逆向分析,然后详细讲解逆向分析的典型应用,接着通过OllyDbg工具逆向分析经典的游戏扫雷,再通过Cheat Engin

杨秀璋的专栏 2万+

关于Yolov5在测试时,图像大小被调整的问题

关于Yolov5在测试时,图像大小被调整的问题

iamjingong的博客 1万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

YOLOv5 数据集加载与处理机制解析

YOLOv5 的datasets.py模块通过精心设计的类结构和处理流程,实现了高效、灵活的数据集加载与预处理。它不仅支持多种数据源的输入,还集成了丰富的数据增强策略,为模型训练提供了高质量的输入。理解这些机制不仅有助于我们更好地使用 YOLOv5 进行目标检测任务,也能为我们自己设计数据集处理模块提供宝贵的参考。

2301_82221961的博客 492

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

借用yolov5实现目标检测自动标注

借用yolov5实现目标检测自动标注 **背景**:目标检测中的数据标注工作量巨大,本文利用yolov5实现自动标注功能,格式为pascal voc。 **步骤**: 1.利用[yolov5](https://github.com/ultralytics/yolov5)先训练小批量样本比如100pcs(yolov5的数据标注以及训练网上有很多教材),得到100pcs的.pt文件 2.将我给的auto_labelimg.py放到yolov5文件夹下面 ![auto_labelimg.py所在位置](http

ly3848的博客 8140

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

YOLOv5 数据集处理源码解析

在目标检测模型的训练过程中,高效的数据处理管道是提升模型性能和训练效率的关键环节。YOLOv5 作为当前流行的目标检测框架,其数据集处理模块融合了多种优化策略和数据增强技术,能够充分挖掘训练数据的潜力。

wsygjbr的博客 710

如何进一步化简提取yolov5-7.0检测的算法

而通过对于监测代码的分析,我们可以发现在处理图片类型的数据时,主要使用了img这一个参数所传递的数据。最后的最后,这个检测代码虽然是基于YOLOv5-5.0的经典输入和YOLOv5-7.0的检测代码所写的,按道理来说是不需要任何新加的库函数的,报错的可能会相对小一些。这里,我们可以不用改变视频的输入部分的代码,而是将我们编写的新一代的API函数替换视频检测的代码。一开始的图片输入,我们使用的是图片的地址信息,但现在我们要改为图片本身的信息,这意味着我们需要将一部分输入内容前移到需要调用这个模块的外面去。

m0_52701839的博客 1589

u版yolov3详解 --->> 前向推理部分

推理是detect.py脚本。 一张图像首先经过class LoadImages: 类处理。 经过def letterbox(img, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleFill=False, scaleup=True, stride=32)函数 处理成最长边为640,并且最短边为32的倍数的图像。 原图是1...

无左无右的博客 2757

基于Yolov5的布匹缺陷检测(含源码和数据集)

先给大家看看效果:产线实时检测每秒能跑45帧,mAP能到0.89,比传统算法快了三倍不止。这里有个坑:布匹缺陷往往是小目标,建议把模型neck部分的C3模块换成BottleneckTransformer。源码里有个实用技巧:在utils/dataloaders.py的LoadImages类里加个热成像处理分支,能有效应对光照变化问题。训练完用--task study参数分析混淆矩阵,重点看哪些类别容易混淆,针对性加数据。布匹缺陷主要分四类:破洞、污渍、跳线、色差,我用的公开数据集已经整理成YOLO格式了。

NBhhbYyOljP的博客 386

yolov3-archive detect 和 test 输出的结果不一,以及test检测结果P有误差的原因

LoadImagesAndLabels调用的load_image函数会使图片本体ceil缩小1个像素,对于小目标影响明显。

KOLong的博客 1002
上一篇: Python日常小操作:chat-gpt-api
下一篇: Python筛选出含有指定label的Json文件
FriendshipT
FriendshipT 优质创作者: 人工智能技术领域 优质创作者: 人工智能技术领域
博客等级 码龄8年 4万+粉丝 491原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FriendshipT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值