在几秒钟内旋转数百个JPEG图像,而不是数小时。

3
我们有数百张图片,计算机一次获取多张,需要尽快进行旋转和调整大小。旋转可以为90度、180度或270度。
目前我们使用命令行工具GraphicsMagick来旋转图像。旋转这些图像(5760*3840 ~ 22MP)需要大约4到7秒的时间。
以下Python代码可悲地给我们带来相同的结果。
import cv
img = cv.LoadImage("image.jpg")
timg = cv.CreateImage((img.height,img.width), img.depth, img.channels) # transposed image

# rotate counter-clockwise
cv.Transpose(img,timg)
cv.Flip(timg,timg,flipMode=0)
cv.SaveImage("rotated_counter_clockwise.jpg", timg)

有没有更快的方式使用图形卡旋转图像?OpenCL和OpenGL是可行的选择,但我们想知道性能提升是否明显。我们使用的硬件相对有限,因为设备应尽可能小。 我们使用Debian 6操作系统,并配备官方(闭源)Radeon驱动程序。

5
阅读这个问题时,我想知道:执行这个操作的每个部分所花费的时间占总时间的百分比是多少?等待中有多少时间用于JPEG编码和实际旋转操作?又有多少时间用于磁盘IO?这些问题的答案可能会对您的优化产生影响。 - csd
1
只需使用jpeg tran,它有一个很好的副作用,不会影响质量。 - datenwolf
你能提供一下你贴出的代码每个部分的时间吗?(在加载后,在转置后,在翻转后,在保存后)? - Daniel Mošmondor
3个回答

12
你可以执行无损旋转,这将只修改EXIF部分。这样旋转图片会更快。
同时查看jpegtran实用程序,它执行无损的JPEG修改。https://linux.die.net/man/1/jpegtran

更改Exif方向标签可能是最快的方法。但并非所有图像查看器都支持它。jpegtran似乎是一个不错的解决方案。它只会部分重新压缩您的图像,这应该仍然非常快。 - Piotr Praszmo
3
若图片的宽和高都是8的倍数,你可以通过重新排列组件而无需重新压缩即可将其旋转90/180/270度。 - Martin Beckett
2
@MartinBeckett:请注意,大多数JPEG图像都以8的倍数维度存储,并在之后应用裁剪,因此jpegtran应该能够为大多数图像重新排序组件。 - datenwolf

4

有一个jpeg无压缩插件适用于 irfanview,可以旋转和调整图像大小(简单方式)而不需要重新压缩,也可以运行一个图像目录 - 这应该会快很多。

显卡可能没有帮助,你在opencv中几乎肯定是I/O限制,它并没有真正针对高速文件访问进行优化。


2
在这里,您将找到更多的实用程序,可以无损地进行旋转,而无需解压缩和再次压缩图像:http://jpegclub.org/losslessapps.html - Mārtiņš Možeiko
对于大量图像,缓冲和/或异步内存传输可以缓解I/O瓶颈 - 因此我不会说基于GPU的实现没有帮助。 - Ani
@ananthonline - 如果JPEG只是简单地旋转90度的倍数,那么您只需要重新排列每个8x8块中的压缩值。GPU在这方面并没有真正帮助,并且在随机内存读/写方面通常很慢,即使您已经将数据放在卡上。如果您正在重新压缩,则可能会更快,尽管使用SSE2的DCT非常快速。 - Martin Beckett
你需要重新压缩某些块,因为图像大小发生了变化,是吧?对于大型图像,即使这些块也会受益于GPU的大规模并行性。使用GPU时,解码+有损旋转选项变得可行。 - Ani

1

我不是jpeg和压缩主题的专家,但是由于您的问题几乎是I/O限制(假设您可以在没有重度编码/解码计算的情况下旋转),因此您可能无法在您拥有的GPU上加速它。 (不)幸运的是,您的参考是一个相当慢的Atom CPU。

我假设Radeon具有单独的主存储器。这意味着数据需要通过PCI-E进行通信,这是与CPU执行相比的额外延迟,并且如果未隐藏,则可以确定它是瓶颈。这是为什么使用OpenCV在GPU上的代码很慢的最有可能的原因(除了您执行两个内存绑定操作,transpose& flip,而不是一个操作)。

关键是通过使用多重缓冲尽可能地隐藏PCI-E传输时间。利用PCI-E的全双工能力,将GPU的传输与计算重叠,只有当所涉及的卡具有双DMA引擎,如高端RadeonsNVIDIA Quadro/Tesla cards时才能正常工作--我非常怀疑这一点。

如果您的GPU计算时间(旋转所需的时间)低于传输时间,您将无法完全重叠。 HD 4530具有相当慢的内存接口,仅具有12.8 Gb/s峰值,并且旋转核心应该相当受内存限制。但是,我只能估计,但我会说,如果您达到了约1.5 Gb/s(4x PCI-E AFAIK)的峰值PCI-E传输速率,计算核心将比传输快几倍,您将能够重叠非常少。

您可以简单地分别计时各个部分,而不需要复杂的异步代码,并且您可以估计在最佳重叠下可以获得多快的速度。

您可能要考虑的一件事是获取不会表现为PCI-E瓶颈的硬件,例如:

  • 基于AMD APU的系统。在这些平台上,您将能够锁定页面内存并直接从GPU中使用它;
  • 与主机共享主内存的集成GPU;
  • 像移动Intel Ivy Bridge(例如i5-3427U)这样的快速低功耗CPU,其功耗几乎与Atom D525相当,但具有AVX支持,并且应该快几倍。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接