Python:沿垂直轴镜像图像的最有效方法

n1k*_*1t4 4 python opencv numpy image

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

执行此操作的最有效方法是什么?

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

n1k*_*1t4 6

这里有两种方法,使用:

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

导入包

import cv2
import numpy as np
Run Code Online (Sandbox Code Playgroud)

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

images.shape
(3, 200, 400, 3)
Run Code Online (Sandbox Code Playgroud)

使用 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)
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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


Div*_*kar 6

您可以简单地使用slicing翻转倒数第二个轴以获得等效的翻转视图到输入图像数组中,因此不会在内存中创建任何新数据,因此是一个高效的数据,如下所示 -

images[...,::-1,:]
Run Code Online (Sandbox Code Playgroud)

如果您仍然需要制作副本,请.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
Run Code Online (Sandbox Code Playgroud)

如果您需要复印 -

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
Run Code Online (Sandbox Code Playgroud)