跳转到主要内容

delayed_image模块

项目描述

GitlabCIPipeline GitlabCICoverage Pypi PypiDownloads ReadTheDocs

阅读文档

https://delayed-image.readthedocs.io

Gitlab(主)

https://gitlab.kitware.com/computer-vision/delayed_image

Github(镜像)

https://github.com/Kitware/delayed_image

Pypi

https://pypi.ac.cn/project/delayed-image

延迟图像模块允许您描述(树状结构的)图像操作,但在用户调用finalize之前不会执行它们。这允许在执行之前优化一系列操作,这意味着执行更快,量化伪影更少。

优化逻辑还可以利用包含内置分块或预览的图像格式的GDAL库。包含分块的格式允许延迟图像仅读取图像的子集,如果仅对图像的小部分进行裁剪。预览允许延迟图像在检测到缩放操作时加载预缩放图像。这比原始执行这些操作的方法快得多,并且比记住自己以正确的顺序做所有事情要容易得多。

注意:GDAL是可选的,但推荐使用。可以在Kitware的大图像轮存储库找到预编译的GDAL wheel。使用以下命令从这个服务器安装GDAL:pip install gdal -f https://girder.github.io/large_image_wheels/。跟踪官方GDAL wheel的状态在此处

历史记录

此模块仍处于开发初期,是将以下代码从kwcoco移植过来。

  • ChannelSpec

  • SensorChannelSpec

  • 延迟加载与其他延迟操作

快速入门

# Given a path to some image
import kwimage
fpath = kwimage.grab_test_image_fpath('amazon')

# Demo how to load, scale, and crop a part of an image.
import delayed_image
delayed = delayed_image.DelayedLoad(fpath)
delayed = delayed.prepare()
delayed = delayed.scale(0.1)
delayed = delayed[128:256, 128:256]

import kwplot
kwplot.autompl()
kwplot.imshow(delayed.finalize())
kwimage.imwrite('foo.png', delayed.finalize())
https://i.imgur.com/lsWLkPx.png

有关详细信息,请参阅快速入门Jupyter笔记本

延迟加载

延迟加载的示例

>>> from delayed_image import DelayedLoad
>>> import kwimage
>>> fpath = kwimage.grab_test_image_fpath(overviews=3)
>>> dimg = DelayedLoad(fpath, channels='r|g|b').prepare()
>>> quantization = {'quant_max': 255, 'nodata': 0}
>>> #
>>> # Make a complex chain of operations
>>> dimg = dimg.dequantize(quantization)
>>> dimg = dimg.warp({'scale': 1.1})
>>> dimg = dimg.warp({'scale': 1.1})
>>> dimg = dimg[0:400, 1:400]
>>> dimg = dimg.warp({'scale': 0.5})
>>> dimg = dimg[0:800, 1:800]
>>> dimg = dimg.warp({'scale': 0.5})
>>> dimg = dimg[0:800, 1:800]
>>> dimg = dimg.warp({'scale': 0.5})
>>> dimg = dimg.warp({'scale': 1.1})
>>> dimg = dimg.warp({'scale': 1.1})
>>> dimg = dimg.warp({'scale': 2.1})
>>> dimg = dimg[0:200, 1:200]
>>> dimg = dimg[1:200, 2:200]
>>> dimg.write_network_text()
╙── Crop dsize=(128,130),space_slice=(slice(1,131,None),slice(2,130,None))
    
    Crop dsize=(130,131),space_slice=(slice(0,131,None),slice(1,131,None))
    
    Warp dsize=(131,131),transform={scale=2.1000}
    
    Warp dsize=(62,62),transform={scale=1.1000}
    
    Warp dsize=(56,56),transform={scale=1.1000}
    
    Warp dsize=(50,50),transform={scale=0.5000}
    
    Crop dsize=(99,100),space_slice=(slice(0,100,None),slice(1,100,None))
    
    Warp dsize=(100,100),transform={scale=0.5000}
    
    Crop dsize=(199,200),space_slice=(slice(0,200,None),slice(1,200,None))
    
    Warp dsize=(200,200),transform={scale=0.5000}
    
    Crop dsize=(399,400),space_slice=(slice(0,400,None),slice(1,400,None))
    
    Warp dsize=(621,621),transform={scale=1.1000}
    
    Warp dsize=(564,564),transform={scale=1.1000}
    
    Dequantize dsize=(512,512),quantization={quant_max=255,nodata=0}
    
    Load channels=r|g|b,dsize=(512,512),num_overviews=3,fname=astro_overviews=3.tif

>>> # Optimize the chain
>>> dopt = dimg.optimize()
>>> dopt.write_network_text()
╙── Warp dsize=(128,130),transform={offset=(-0.6115,-1.0000),scale=1.5373}
    
    Dequantize dsize=(80,83),quantization={quant_max=255,nodata=0}
    
    Crop dsize=(80,83),space_slice=(slice(0,83,None),slice(3,83,None))
    
    Overview dsize=(128,128),overview=2
    
    Load channels=r|g|b,dsize=(512,512),num_overviews=3,fname=astro_overviews=3.tif

#
>>> final0 = dimg.finalize(optimize=False)
>>> final1 = dopt.finalize()
>>> assert final0.shape == final1.shape
>>> # xdoctest: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> kwplot.imshow(final0, pnum=(1, 2, 1), fnum=1, title='raw')
>>> kwplot.imshow(final1, pnum=(1, 2, 2), fnum=1, title='optimized')
https://i.imgur.com/3SGvxtC.png

原生分辨率采样

考虑以下情况,我们有多个图像存储在磁盘上,具有不同的分辨率,但它们对应于相同的场景(例如,卫星图像可能具有10米分辨率的RGB波段和30米分辨率的红外波段),我们想要采样每个图像中的对应区域。通常,开发者可能会选择将所有内容简单地缩放到相同的分辨率,以便所有内容都对应,然后仅裁剪区域。这可行,但它有产生重采样伪影的负面影响。

延迟加载允许进行简单直观的“原生分辨率采样”。我们可以执行延迟缩放操作以获得一个“视图”,就像我们已将所有组件波段缩放到相同分辨率一样,然后执行延迟裁剪。最终完成此延迟操作与之前描述的情况完全相同(只不过它受益于延迟图像的优化操作重排序)。然而,我们可以更进一步。因为我们了解底层操作图,我们可以取消缩放组件,同时保留裁剪组件,这将在裁剪区域内加载图像的相应部分,但不会进行任何重采样。磁盘上的图像不仅分辨率可能不同,它们还可能偏移、倾斜或旋转,并且此去畸变过程仍然有效。

以下图像展示了一个极端示例,其中我们模拟了一个低分辨率的红色波段(R)、一个中等但旋转的绿色波段(G)和一个高但裁剪的蓝色(B)波段。

https://i.imgur.com/fW7Mdo1.png

磁盘上的原始波段显示在顶部一行。第二行展示了在执行裁剪时我们可以概念上思考的对齐空间。此行中定义的蓝色框被投影到所有其他图像上,使用的是延迟图像。第三行显示了蓝色框的原始重采样对齐和裁剪结果(以及优化和非优化最终化之间的像素差异)。最后,第四行显示了原生采样,其中每个裁剪对应于相同的区域,但我们已删除所有缩放因子(旋转和倾斜重采样仍然执行以对齐到图像角落,直至缩放因子)。

有关代码细节,请参阅delayed_image/__init__.py __doc__:2中的doctest。

SensorChanSpec

包括SensorChan规范,这使得处理来自不同传感源的信道的操作更加容易。

传感器/通道规范并非使用延迟图像所必需,但它有助于——特别是通道规范——在执行延迟加载操作时对通道进行语义标记。

在简单层面上,您需要了解的基本通道规范是通道名称由 | 分隔。例如,red|green|blue 指的是 3 个通道的图像。您可以使用这些名称来选择通道的子集。以下是一个示例,其中您加载一个图像,为每个通道提供语义标签,然后使用它们来选择单个通道。

import delayed_image
import kwimage
fpath = kwimage.grab_test_image_fpath(overviews=3)

# When you create a delayed image, you can enrich the image with
# information about what channels it contains by specifying the
# channels attribute.
delayed = DelayedLoad(fpath, channels='red|green|blue').prepare()

# You can use this to semantically interact with the channels
delayed_g = delayed.take_channels('green')
assert delayed_g.shape == (512, 512, 1)

# Specifying more than one channel works too
delayed_rb = delayed.take_channels('blue|red')
assert delayed_rb.shape == (512, 512, 2)

大部分传感器/通道规范的特性都是为了其他项目(如 kwcoco)的利益而存在的。诚然,这个库并不是完整的传感器/通道规范的完美家园,但这是它目前所在的地方。

完整的传感器通道规范在这个包中定义了一个正式的语法。

// SENSOR_CHAN_GRAMMAR
?start: stream

// An identifier can contain spaces
IDEN: ("_"|"*"|LETTER) ("_"|" "|"-"|"*"|LETTER|DIGIT)*

chan_single : IDEN
chan_getitem : IDEN "." INT
chan_getslice_0b : IDEN ":" INT
chan_getslice_ab : (IDEN "." INT ":" INT) | (IDEN ":" INT ":" INT)

// A channel code can just be an ID, or it can have a getitem
// style syntax with a scalar or slice as an argument
chan_code : chan_single | chan_getslice_0b | chan_getslice_ab | chan_getitem

// Fused channels are an ordered sequence of channel codes (without sensors)
fused : chan_code ("|" chan_code)*

// A channel only part can be a fused channel or a sequence
channel_rhs : fused | fused_seq

// Channels can be specified in a sequence but must contain parens
fused_seq : "(" fused ("," fused)* ")"

// Sensors can be specified in a sequence but must contain parens
sensor_seq : "(" IDEN ("," IDEN)* "):"

sensor_lhs : (IDEN ":") | (sensor_seq)

sensor_chan : sensor_lhs channel_rhs?

nosensor_chan : channel_rhs

stream_item : sensor_chan | nosensor_chan

// A stream is an unordered sequence of fused channels, that can
// optionally contain sensor specifications.

stream : stream_item ("," stream_item)*

%import common.DIGIT
%import common.LETTER
%import common.INT

您可以认为通道规范是通过“,”分割的,它给出了应该一起处理和“后期融合”的通道组。在每个组内,“|”运算符“早期融合”通道。

例如,假设我们有一个网络,我们想要在一个流中处理 3 通道 rgb 图像,在第二个流中处理 1 通道红外图像,然后将它们融合在一起。标记为“红色”、“绿色”、“蓝色”和“红外”的通道的通道规范将是

infrared,red|green|blue

传感器可以包含冒号前缀。括号可以用于分组。

S2:(infrared,red|green|blue)

项目详情


下载文件

下载您平台上的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源代码分发

delayed_image-0.4.1.tar.gz (106.5 kB 查看哈希值)

上传时间 源代码

构建分发

delayed_image-0.4.1-py3-none-any.whl (94.2 kB 查看哈希值)

上传时间 Python 3

由以下机构支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面