mmcv和openCV两个库imcrop()和imresize()方法的对应【基础分析】

news2024/11/23 2:56:32

🥇 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连
🎉 声明: 作为全网 AI 领域 干货最多的博主之一,❤️ 不负光阴不负卿 ❤️

0-9

文章目录

    • MMCV 全家桶
    • mmcv.imresize(img, (1000, 600), return_scale=True) 方法实现
    • 对应的 openCV 的 cv2.resize 方法
    • mmcv 中 imcrop(img, bboxes, scale=1.0, pad_fill=None) 方法
    • mmcv/image/geometric.py 文件分析
    • 📙 精选专栏

MMCV 全家桶

  • https://github.com/open-mmlab/mmcv/blob/master/README_zh-CN.md

是一个用于训练深度学习模型的基础库

1-90

有很多star数量较高的集成仓库方便开发者进行模型训练和部署的全流程搭建

1-9

mmcv.imresize(img, (1000, 600), return_scale=True) 方法实现

mmcv.imresize(img, (1000, 600), return_scale=True)

源码链接如下

  • https://github.com/open-mmlab/mmcv/blob/b9bdfeb6f6aa67372d18b2ed5a10de28fc179d11/mmcv/image/geometric.py

cv2_interp_codes = {
    'nearest': cv2.INTER_NEAREST,
    'bilinear': cv2.INTER_LINEAR,
    'bicubic': cv2.INTER_CUBIC,
    'area': cv2.INTER_AREA,
    'lanczos': cv2.INTER_LANCZOS4
}

def imresize(img,
             size,
             return_scale=False,
             interpolation='bilinear',
             out=None,
             backend=None):
    """Resize image to a given size.
    Args:
        img (ndarray): The input image.
        size (tuple[int]): Target size (w, h).
        return_scale (bool): Whether to return `w_scale` and `h_scale`.
        interpolation (str): Interpolation method, accepted values are
            "nearest", "bilinear", "bicubic", "area", "lanczos" for 'cv2'
            backend, "nearest", "bilinear" for 'pillow' backend.
        out (ndarray): The output destination.
        backend (str | None): The image resize backend type. Options are `cv2`,
            `pillow`, `None`. If backend is None, the global imread_backend
            specified by ``mmcv.use_backend()`` will be used. Default: None.
    Returns:
        tuple | ndarray: (`resized_img`, `w_scale`, `h_scale`) or
        `resized_img`.
    """
    h, w = img.shape[:2]
    if backend is None:
        backend = imread_backend
    if backend not in ['cv2', 'pillow']:
        raise ValueError(f'backend: {backend} is not supported for resize.'
                         f"Supported backends are 'cv2', 'pillow'")

    if backend == 'pillow':
        assert img.dtype == np.uint8, 'Pillow backend only support uint8 type'
        pil_image = Image.fromarray(img)
        pil_image = pil_image.resize(size, pillow_interp_codes[interpolation])
        resized_img = np.array(pil_image)
    else:
        resized_img = cv2.resize(
            img, size, dst=out, interpolation=cv2_interp_codes[interpolation])
    if not return_scale:
        return resized_img
    else:
        w_scale = size[0] / w
        h_scale = size[1] / h
        return resized_img, w_scale, 

对应的 openCV 的 cv2.resize 方法

resized_img = cv2.resize(
            img, size, dst=out, interpolation=cv2_interp_codes[interpolation])

mmcv 中 imcrop(img, bboxes, scale=1.0, pad_fill=None) 方法

调用方式

bboxes = np.array([10, 10, 100, 120])
patch = mmcv.imcrop(img, bboxes)
  • mmcv/image/geometric.py 源码实现
def imcrop(img, bboxes, scale=1.0, pad_fill=None):
    """Crop image patches.
    3 steps: scale the bboxes -> clip bboxes -> crop and pad.
    Args:
        img (ndarray): Image to be cropped.
        bboxes (ndarray): Shape (k, 4) or (4, ), location of cropped bboxes.
        scale (float, optional): Scale ratio of bboxes, the default value
            1.0 means no padding.
        pad_fill (Number | list[Number]): Value to be filled for padding.
            Default: None, which means no padding.
    Returns:
        list[ndarray] | ndarray: The cropped image patches.
    """
    chn = 1 if img.ndim == 2 else img.shape[2]
    if pad_fill is not None:
        if isinstance(pad_fill, (int, float)):
            pad_fill = [pad_fill for _ in range(chn)]
        assert len(pad_fill) == chn

    _bboxes = bboxes[None, ...] if bboxes.ndim == 1 else bboxes
    scaled_bboxes = bbox_scaling(_bboxes, scale).astype(np.int32)
    clipped_bbox = bbox_clip(scaled_bboxes, img.shape)

    patches = []
    for i in range(clipped_bbox.shape[0]):
        x1, y1, x2, y2 = tuple(clipped_bbox[i, :])
        if pad_fill is None:
            patch = img[y1:y2 + 1, x1:x2 + 1, ...]
        else:
            _x1, _y1, _x2, _y2 = tuple(scaled_bboxes[i, :])
            if chn == 1:
                patch_shape = (_y2 - _y1 + 1, _x2 - _x1 + 1)
            else:
                patch_shape = (_y2 - _y1 + 1, _x2 - _x1 + 1, chn)
            patch = np.array(
                pad_fill, dtype=img.dtype) * np.ones(
                    patch_shape, dtype=img.dtype)
            x_start = 0 if _x1 >= 0 else -_x1
            y_start = 0 if _y1 >= 0 else -_y1
            w = x2 - x1 + 1
            h = y2 - y1 + 1
            patch[y_start:y_start + h, x_start:x_start + w,
                  ...] = img[y1:y1 + h, x1:x1 + w, ...]
        patches.append(patch)

    if bboxes.ndim == 1:
        return patches[0]
    else:
        return patches

依赖方法

def bbox_clip(bboxes, img_shape):
    """Clip bboxes to fit the image shape.
    Args:
        bboxes (ndarray): Shape (..., 4*k)
        img_shape (tuple[int]): (height, width) of the image.
    Returns:
        ndarray: Clipped bboxes.
    """
    assert bboxes.shape[-1] % 4 == 0
    cmin = np.empty(bboxes.shape[-1], dtype=bboxes.dtype)
    cmin[0::2] = img_shape[1] - 1
    cmin[1::2] = img_shape[0] - 1
    clipped_bboxes = np.maximum(np.minimum(bboxes, cmin), 0)
    return clipped_bboxes

def bbox_scaling(bboxes, scale, clip_shape=None):
    """Scaling bboxes w.r.t the box center.
    Args:
        bboxes (ndarray): Shape(..., 4).
        scale (float): Scaling factor.
        clip_shape (tuple[int], optional): If specified, bboxes that exceed the
            boundary will be clipped according to the given shape (h, w).
    Returns:
        ndarray: Scaled bboxes.
    """
    if float(scale) == 1.0:
        scaled_bboxes = bboxes.copy()
    else:
        w = bboxes[..., 2] - bboxes[..., 0] + 1
        h = bboxes[..., 3] - bboxes[..., 1] + 1
        dw = (w * (scale - 1)) * 0.5
        dh = (h * (scale - 1)) * 0.5
        scaled_bboxes = bboxes + np.stack((-dw, -dh, dw, dh), axis=-1)
    if clip_shape is not None:
        return bbox_clip(scaled_bboxes, clip_shape)
    else:
        return scaled_bboxes

mmcv/image/geometric.py 文件分析

从头文件的import和基础代码分析,可以看到 mmcv 中是把 openCV 和 PIL 两个库的 image 处理集成到 geometric.py 各个方法中

import numbers
import warnings
from typing import Optional, Tuple

import cv2
import numpy as np

from ..utils import to_2tuple
from .io import imread_backend

try:
    from PIL import Image
except ImportError:
    Image = None


📙 精选专栏


  • 🍊 深度学习模型训练推理——基础环境搭建推荐博文查阅顺序【基础安装—认真帮大家整理了】——【1024专刊】

计算机视觉领域 八大专栏、不少干货、有兴趣可了解一下

  • ❤️ 图像风格转换 —— 代码环境搭建 实战教程【关注即可阅】!
  • 💜 图像修复-代码环境搭建-知识总结 实战教程 【据说还行】
  • 💙 超分重建-代码环境搭建-知识总结 解秘如何让白月光更清晰【脱单神器】
  • 💛 YOLO专栏,只有实战,不讲道理 图像分类【建议收藏】!
  • 🍊 深度学习:环境搭建,一文读懂

  • 🍊 深度学习:趣学深度学习

  • 🍊 落地部署应用:模型部署之转换-加速-封装

  • 🍊 CV 和 语音数据集:数据集整理

  • 🍊 点赞 👍 收藏 ⭐留言 📝 都是博主坚持写作、更新高质量博文的最大动力!

9-9

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

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

相关文章

Unity 之 Post Processing后处理不同项目配置(URP项目配置)

Unity 之 Post Processing后处理不同项目配置(URP项目配置)一,Post Processing介绍二,正常项目配置2.1 场景配置2.2 摄像机配置2.3 集成步骤小结三,URP项目配置3.1 具体配置步骤3.2 最终实现效果四,代码控制…

【每天一个cmake技巧】简单的cmake demo

简单的cmake demo 一个简单的cmake 工程,包括生成动态库和链接动态库的demo工程和test工程。 demo下载链接: https://download.csdn.net/download/sinat_35178307/87243966 目录结构 该工程可以生成一个dll,一个调用dll的demo,…

【数据分享】维基百科Wiki负面有害评论(网络暴力)文本数据多标签分类挖掘可视化...

原文链接:http://tecdat.cn/?p8640讨论你关心的事情可能很困难。网络暴力骚扰的威胁意味着许多人停止表达自己并放弃寻求不同的意见(查看文末了解数据免费获取方式)。平台努力有效地促进对话,导致许多社区限制或完全关闭用户评论…

C++中的菱形继承问题及解决方案

存在问题 C中支持多重继承,但是由于这个特性,导致会有如下继承关系。 这样,类D就会同时拥有从类B中继承下来的A中的函数,也会拥有从类C中继承下来的A中的函数,会产生模糊调用的现象。 解决方案 为了解决这个问题&a…

spring源码 - AOP原理理解

AOP使用 1.我们都知道我们在使用spring aop时需要在configuration类上增加EnableAspectJAutoProxy 2.然后在准备AOP类就可以对相应类的方法进行aop Component Aspect public class MyAspect { Pointcut("execution(* com.my.service.*.*(..))") public void as…

利用WSL2搭建Qemu仿真Vexpress-a9开发环境

利用WSL2搭建Qemu仿真Vexpress-a9开发环境开发环境搭建更新软件源uboot-tools安装交叉编译环境安装qemu安装编译linux镜像和DBT文件启动qemu仿真kernelbusybox制作根文件系统制作rootfs使用u-boot启动kernel下载编译u-bootu-boot利用tftp网络引导方式启动Linux内核WSL2主机网络…

火爆朋友圈的ChatGPT是什么?

火爆朋友圈的ChatGPT是什么? 官方博客:https://openai.com/blog/chatgpt/ 背景 OpenAI,在美国成立的人工智能研究公司。2015年,OpenAI由马斯克、美国创业孵化器Y Combinator总裁阿尔特曼、全球在线支付平台PayPal联合创始人彼得…

Java入门教程(14) ——Scanner 获取键盘输入

在后台开发中,我们可能需要在运行的时候传递一些参数进去,该怎么处理呢? Java 提供了一个 Scanner 类,利用这个类,我们可以很方便的获取键盘输入的参数,接下来给大家详细介绍一下 1.首先导包 import jav…

到底什么是类脑计算?

当前感存算一体化的类脑神经拟态芯片流行,对其类脑计算的定义各家有各家的说法。但总之,类脑计算就是模拟人类思考方式的一种计算。 本文摘编自《类脑计算》(危辉著. 北京:科学出版社, 2022. 7)一书“第1 章什么是类脑…

“在别人恐惧时贪婪”,这支基金将在“自动驾驶寒冬”加大投资力度

交流群 | 进“传感器群/滑板底盘群”请加微信号:xsh041388交流群 | 进“汽车基础软件群”请加微信号:Faye_chloe备注信息:群名称 真实姓名、公司、岗位前段时间,Argo“关闭”的消息将寒气传给了全球自动驾驶产业的每一个人。再加…

[附源码]计算机毕业设计图书馆出版物预订系统Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

C#语言实例源码系列-实现批量图片格式转换

专栏分享点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册 👉关于作者 众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中…

极客时间Kafka - 02 为什么要分区|生产者的分区策略|轮询策略|随机策略|消息键保序策略

文章目录1. 为什么分区?2. Kafka 生产者的分区策略1. 轮询策略 RoundRobinPartitioner2. 随机策略 UniformStickyPartitioner3. 按消息键保序策略 DefaultPartitioner我们在使用 Apache Kafka 生产和消费消息的时候,肯定是希望能够将数据均匀地分配到所有…

Jenkins-jenkins凭证管理与代码拉取

什么是凭证? Jenkins经常与第三方插件如git,docker等交互,需要提供第三方的凭证,比如access token,用户名和密码等 可以使用插件Credentials Binding Plugin来管理这些凭证 jenkins凭证类型 jenkins可以管理以下凭证…

UEFI的一点点概识

最近看了一篇Blog讲的是关于PC安全的,其中很多的地方还是有一定相似之处。其中这个UEFI引起了我兴趣,以前安装系统的时候听说过这个名词。这里于是便来认识一下什么是UEFI。 前言 大多数人接触UEFI都是在PC的应用场景上,有在PC上安装过多操…

关闭二维码

关闭二维码 结果演示 概述 通过事件的绑定来实现&#xff0c;关闭二维码的效果。 构建HTML框架 <body><div class"box">二维码<img src"images/tao.png" alt""><i class"close-btn"></i></div&g…

第四十一篇 指令中的VNode

VNode 前面讲到了自定义指令的引入使用&#xff0c;以及结合封装swiper组件一起进行结合使用&#xff0c;还记在inserted 指令生命周期当中使用的参数吗&#xff1f;第一个参数是可以拿到DOM节点&#xff08;el&#xff09;&#xff0c;第二个参数是可以拿到使用自定义指令绑定…

NLP-信息抽取-三元组-联合抽取-多任务学习-2019:spERT【采用分类的思想实现联合抽取,实体抽取和关系抽取模型均为分类模型】

论文题目&#xff1a;Span-based Joint Entity and Relation Extraction with Transformer Pre-trainin 论文链接&#xff1a;https://arxiv.org/abs/1909.07755 论文代码&#xff1a;https://github.com/markus-eberts/spert SpERT模型是联合式抽取模型&#xff0c;同时抽取…

消息队列RabbitMQ核心:简单(Hello World)模式、队列(Work Queues)模式、发布订阅模式

文章目录一、简单模式&#xff08;Hello World&#xff09;代码实现二、队列模式&#xff08;Work Queues&#xff09;轮训分发消息代码实现消息应答概述RabbitMQ持久化不公平分发三、发布订阅模式原理概述发布确认策略单个确认发布批量确认发布异步确认发布三种发布确认速度对…

MongoDB_实战部分(二)

目录一、MongoDB CRUD操作MongoDB 插入文档MongoDB 查询文档MongoDB 修改文档MongoDB 删除文档练习题二、Mongoose三、VSCode连接MongoDB模块化一、MongoDB CRUD操作 MongoDB 插入文档 /*向数据库插入文档db.<collection>.insert()db.<collection>.insertOne() 插…