跳转到主要内容

qoi的简单包装器(https://github.com/phoboslab/qoi)

项目描述

PyPI version fury.io

QOI

QOI是一个简单的Python包装器,围绕“相当好的图像”格式qoi(https://github.com/phoboslab/qoi)。它是

  • 无损的,压缩效果与PNG相当,但速度快!它比PNG在OpenCV或PIL中编码快10倍,解码快约5倍。
  • 您可以通过一个简单的技巧使其有损,然后您可以获得与JPEG类似的压缩效果,但速度要快得多。(这些数字取决于您如何使JPEG或QOI“有损”)。这很酷。
  • 多线程 - 没有GIL挂起。

安装

pip install qoi

示例

import numpy as np
import qoi

# Get your image as a numpy array (OpenCV, Pillow, etc. but here we just create a bunch of noise). Note: HWC ordering
rgb = np.random.randint(low=0, high=255, size=(224, 244, 3)).astype(np.uint8)

# Write it:
_ = qoi.write("/tmp/img.qoi", rgb)

# Read it and check it matches (it should, as we're lossless)
rgb_read = qoi.read("/tmp/img.qoi")
assert np.array_equal(rgb, rgb_read)

# Likewise for encode/decode to/from bytes:
bites = qoi.encode(rgb)
rgb_decoded = qoi.decode(bites)
assert np.array_equal(rgb, rgb_decoded)

# Benchmarking
from qoi.benchmark import benchmark
benchmark()  # Check out the arguments if you're interested

如果您想真正发挥CPU的最大性能

from concurrent.futures import ThreadPoolExecutor, wait
import numpy as np
import qoi

RGB = np.random.randint(low=0, high=255, size=(224, 244, 3)).astype(np.uint8)

def worker():
    bites = bytearray(qoi.encode(RGB))
    img_decoded = qoi.decode(bites)

print("Go watch your CPU utilization ...")
with ThreadPoolExecutor(8) as pool:
    futures = [pool.submit(worker) for _ in range(10000)]
    wait(futures)

(单线程) 基准测试

如果我们考虑无损,那么我们通常与PNG进行比较。是的,还有其他一些,但它们不太常见。基准测试

测试图像 方法 格式 输入 (kb) 编码 (ms) 编码 (kb) 解码 (ms) SSIM
全黑 ('最佳'情况) PIL png 6075.0 37.75 6.0 16.04 1.00
全黑 ('最佳'情况) opencv png 6075.0 23.82 7.7 17.93 1.00
全黑 ('最佳'情况) qoi qoi 6075.0 4.13 32.7 2.67 1.00
koi photo PIL png 6075.0 849.07 2821.5 85.46 1.00
koi photo opencv png 6075.0 95.24 3121.5 44.34 1.00
koi photo qoi qoi 6075.0 28.37 3489.0 17.19 1.00
随机噪声 (最差情况) PIL png 6075.0 300.37 6084.5 46.30 1.00
随机噪声 (最差情况) opencv png 6075.0 63.72 6086.9 14.01 1.00
随机噪声 (最差情况) qoi qoi 6075.0 16.16 8096.1 7.67 1.00

因此,在压缩方面,qoi与PNG不相上下,但编码速度快4-20倍,解码速度快1.5-6倍。

注意

  1. 这里有一些额外的开销,因为PIL图像被转换回数组作为返回类型,以保持一致。从某种意义上说,这并不公平,因为如果您处理的是PIL图像,PIL将更快。另一方面,如果您的常见用例涉及数组(例如,用于计算机视觉),则这是合理的。
  2. 使用 python src/qoi/benchmark.py --implementations=qoi,opencv,pil --formats=png,qoi 在 i7-9750H 上生成。由于结果对于这种“普通”场景已经足够清晰,所以没有进行 OpenCV/PIL 优化(例如 SIMD 或 pillow-simd)。如果你想要深入了解,请随意!你可以轻松地自己运行这些测试。

如果我们考虑有损压缩,那么通常我们会将 JPEG 作为比较对象。通常情况下,将 QOI 与 JPEG 比较是不公平的,因为 QOI 是无损的。然而,我们可以进行一个小技巧,使 QOI 变得有损——将图像缩小,然后编码,然后在解码后按相同的比例放大。你可以看到我们在下面实现了这个技巧,将图像缩小到 40%,并使用 80 的 JPEG 质量度(这使得它们的视觉压缩效果相同,即 SSIM)。所以,结果(仅针对 koi photo,因为其余的对于有损压缩来说不那么有意义/公平)

测试图像 方法 格式 输入 (kb) 编码 (ms) 编码 (kb) 解码 (ms) SSIM
koi photo PIL jpg @ 80 6075.0 47.67 275.2 24.01 0.94
koi photo opencv jpg @ 80 6075.0 24.03 275.3 19.58 0.94
koi photo qoi qoi 6075.0 23.17 3489.0 12.94 1.00
koi photo qoi-lossy-0.40x0.40 qoi 6075.0 4.38 667.5 2.96 0.94

在这里,我们看到无损的 qoi 在压缩方面损失很大,正如预期的那样,因为这是有损与无损的对比。此外,qoi 的编码速度仅比编码速度快 1x-2x,解码速度快 1.5x-2x。然而,需要注意的是,这取决于指定的 JPEG 质量值——这里为 80,但 OpenCV 的默认值实际上是 95,这会导致压缩效果差 3 倍,并且速度略慢。

然而,这仍然是有损与无损的对比!如果你看 qoi-lossy-0.40x0.40,其中我们将图像按上述方式缩小,你可以看到它的性能非常好。压缩比现在是 JPEG 的 3 倍(比无损 QOI 好出 5 倍,也与质量为 95 的默认 OpenCV JPEG 编码相同),但它的速度非常快——编码速度快 5x-10x,解码速度快 7x-8x。

当然,有些情况下使用 qoi 可能仍然比 JPEG 更有意义。即使是无损 QOI,如果大小不是问题,它也值得使用,因为它稍微快一点。但是,如果你使用“有损”QOI,你将获得“相当”(取决于 JPEG 质量值)的压缩效果,但速度要快得多。

注意

  1. 关于 PIL 的额外开销,请参见上文。
  2. 使用 python src/qoi/benchmark.py --images=koi --implementations=qoi,qoi-lossy,opencv,pil --formats=jpg,qoi --qoi-lossy-scale=0.4 --jpeg-quality=0.8 在 i7-9750H 上生成。由于结果对于这种“普通”场景已经足够清晰,所以没有进行 OpenCV/PIL 优化(例如 SIMD 或 pillow-simdlibjpeg-turbo、不同的 JPEG 质量值等)。如果你想要深入了解,请随意!你可以轻松地自己运行这些测试。

开发中

git clone --recursive https://github.com/kodonnell/qoi/
USE_CYTHON=1 pip install -e .[dev]
pytest .

我们使用 cibuildwheel 来构建所有轮子,它在 Github 动作中运行。如果你想检查本地是否成功,你可以尝试(未测试)

cibuildwheel --platform linux .

最后,当你满意时,提交一个 PR。

发布

当你在本地的 main 上时,使用 git tag vX.X.X 然后使用 git push origin vX.X.X。这将推送标签,触发完整的 GitHub Action 和

  • 构建源分布和轮子(针对各种平台)
  • 推送到 PyPI
  • 创建一个带有适当附件的新版本。

待办事项

  • benchmark.py 作为 CLI 在 setup.py 中实现
  • 创建一个 qoi CLI
  • 基准测试 - 添加真实图像,并与 QOI 进行性能比较,以查看 Python 包装器的开销。
  • setuptools_scm_git_archive?
  • 代码补全?

讨论

包装还是重写?

目前,这只是一个简单的包装器。我们将让原始项目去做所有关于性能等困难的工作,以及维护(或不)兼容性或添加新功能等。我们不做任何进一步的声明——我们基本上只是将 C 功能性移植到(C)Python 中。

关于命名

让我们现在就使用 qoi 吧,因为

  • 我们已经在 Python 中,而 pypyqoi 中似乎多余。就其价值而言,3 < 5
  • pyqoi 似乎是一个好的名字,用于 QOI 的纯 Python 版本(对于 pypy 等非常有用),但这不是本项目的目标。
  • qoi 通常很新,所以我们现在不必过分思考它。如果需要,我们总是可以在以后重命名。

关于 ./src 的什么问题?

请参阅此处此处。我没有全部阅读,但确实如此,当存在名为qoi的文件夹时,import qoi很烦人。

USE_CYTHON=1?

请参阅此处。很有道理。

项目详情


下载文件

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

源分布

qoi-0.7.0.tar.gz (3.3 MB 查看哈希值)

上传时间

由以下机构支持