【问题标题】:Python: most efficient way to mirror an image along its vertical axisPython:沿垂直轴镜像图像的最有效方法
【发布时间】:2018-04-10 22:12:13
【问题描述】:

我有很多图像需要(即时)翻转,因此我正在寻找使用 Python 的最快方法。

最有效的方法是什么?

我在磁盘上有图像文件并尝试了一些方法,如下面我自己的答案所示,但这些以 Numpy 数组开头,因此可能不是最佳的。有更好的方法吗?

【问题讨论】:

  • 图片是如何存储的?作为数组列表还是一个大数组?
  • 存储为单个 .jpg 文件。对于下面我自己的尝试,我在开始时将它们读入一个 numpy 数组,使用 matplotlib.image.imread()
  • 让我换一种说法。您的回答帖子中有images。那么,images 是数组还是列表?
  • 嗯,好的——三个图像在一个 numpy 数组中。我已将shape 添加到我的答案中。

标签: python image numpy opencv


【解决方案1】:

您可以简单地使用slicing 来翻转倒数第二个轴,从而将等效的翻转视图放入图像的输入数组中,这样不会在内存中创建任何新数据,因此是一种高效的数据,就像这样 -

images[...,::-1,:]

如果您仍需要制作副本,请在此处使用.copy,它仍然比np.fliplr 更有效,并且对于小型/体面大小的数组很明显。

运行时测试-

似乎 NumPy 是赢家,所以我将用它来测试它。

In [64]: images = np.random.randint(0,255,(3,200,400,3))

In [65]: out1 = np.array([np.fliplr(images[i]) for i in range(3)])

In [66]: out2 = images[...,::-1,:]

In [67]: np.allclose(out1, out2)
Out[67]: True

In [68]: %timeit np.array([np.fliplr(images[i]) for i in range(3)])
1000 loops, best of 3: 1.38 ms per loop

In [69]: %timeit images[...,::-1,:]
1000000 loops, best of 3: 259 ns per loop # virtually free

如果你需要复制 -

In [76]: images = np.random.randint(0,255,(3,10,10,3))

In [77]: %timeit np.array([np.fliplr(images[i]) for i in range(3)])
100000 loops, best of 3: 5.76 µs per loop

In [78]: %timeit images[...,::-1,:].copy()
100000 loops, best of 3: 2.23 µs per loop

In [79]: images = np.random.randint(0,255,(3,100,100,3))

In [80]: %timeit np.array([np.fliplr(images[i]) for i in range(3)])
10000 loops, best of 3: 159 µs per loop

In [81]: %timeit images[...,::-1,:].copy()
10000 loops, best of 3: 152 µs per loop

【讨论】:

  • 太好了!我也测试过...%timeit -r 10 -n 100000 images[...,::-1,:]。每个循环 369 ns ± 125 ns(10 次运行的平均值 ± 标准偏差,每次 100000 次循环)。对于像我这样不熟悉三个点(Ellipsis 对象)的人,这里有一些提示:link1, link2
  • 感谢您提供额外的copy 信息。另外,接受,因为我不相信我们可以免费击败! :)
  • 还值得看看implementation of fliplr,看看它只是切片的简写,需要额外检查
【解决方案2】:

这里有两种方法,使用:

  1. OpenCV cv2.flip()
  2. 麻木np.fliplr()

导入包

import cv2
import numpy as np

我在一个 numpy 数组中有三个图像,每个图像的分辨率如下所示:

images.shape
(3, 200, 400, 3)

使用 Jupyter 的 %%timeit 模块:

%%timeit -r 10 -n 100000
[cv2.flip(images[i], 1) for i in range(3)]

--> 70.4 µs ± 1.16 µs per loop (mean ± std. dev. of 10 runs, 100000 loops each)

%%timeit -r 10 -n 100000
[np.fliplr(images[i]) for i in range(3)]

--> 3.19 µs ± 288 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)

运行以下代码可确保结果相同:

x = [cv2.flip(images[i], 1) for i in range(3)]
y = [np.fliplr(images[i]) for i in range(3)]

for i in range(3):
    print(np.array_equal(x[i], y[i]))

# True
# True
# True

所以 numpy 大约是。比opencv快20倍

【讨论】:

  • @scharette 是的,您可以立即回答。 SO 旨在帮助未来的用户。如果您为某个问题苦苦挣扎了一段时间,但在这里找不到答案,然后自己想通了,那么您可以提出问题并打算自己回答
  • 帮助中心有一条说明,可以在stackoverflow.com/help/self-answer回答您自己的问题
  • @scharette 问题和答案显然必须是高质量的,并且以前没有被问过。 This blog 可能会感兴趣。
猜你喜欢
  • 1970-01-01
  • 2019-06-30
  • 2015-03-10
  • 2016-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-23
  • 1970-01-01
相关资源
最近更新 更多