【问题标题】:Rotate an image by 90 degrees using Eigen from OpenCV Matrix in C++ [closed]使用 C++ 中 OpenCV 矩阵的特征将图像旋转 90 度 [关闭]
【发布时间】:2020-04-24 00:44:56
【问题描述】:

如何使用 OpenCV Matrix 中的 Eigen 将图像旋转 90 度,然后将旋转后的图像转换回 C++ 中的 OpenCV Matrix。 OpenCV 的rotate 功能需要时间,我想尽快完成。我尝试在 Python 中使用 Numpy rot90 函数,与 C++ 中的 OpenCV rotate 函数相比,它非常快。不幸的是,Numpy 不适用于 C++。我读过 C++ 中还有其他库,如 Eigen 和 Armadillo,它们可以快速执行这些矩阵运算。这就是我想使用 Eigen 旋转图像并检查时间的原因。

我在 Windows 10 的 i5 机器上测试了 Visual Studio 2019 中的函数。Python 中的 numpy rot90 函数比 C++ 中的 OpenCV rotate 函数快大约 10 倍。

【问题讨论】:

  • 您打算在哪个平台上执行此操作?对于性能问题,了解这一点很有趣。哪个cpu?你能用gpu吗?
  • 这应该只是一个转置和一个翻转,OpenCV 应该已经做到了这一点。检查这个:stackoverflow.com/questions/2259678/…
  • @87VN0 我在 i5 机器上的 Windows 10 上运行它。我不打算使用 GPU。
  • 您如何对此进行基准测试? (你测量了什么差异?对于什么图像大小/类型?)你从哪里读到 Eigen 或 Armadillo 可以比 OpenCV 更快地做到这一点?您的 OpenCV 是否包含所有可用的 SIMD 优化?

标签: python c++ numpy opencv eigen


【解决方案1】:

我猜函数warpAffine 更快。至少你应该比较检查。
这里有一个例子:
https://docs.opencv.org/master/dd/d52/tutorial_js_geometric_transformations.html

cuda 也有同样的功能:
https://docs.opencv.org/master/db/d29/group__cudawarping.html

编辑:
OpenCV 中的warpAffine 实际上可以使用英特尔性能基元库中的ippiWarpAffine* 函数。这可能是可以获得的最快性能。如果您可以在具有 nvidia gpu 的平台上运行您的软件,cuda 版本预计会更快。性能取决于您使用的数据类型。如果你可以使用 8 位无符号图像,你会更快。

编辑 2: 在评论说 warpAffine 速度较慢后,我进行了一些测试,有时它可能会更快。但是,与 numpy 的旋转相比,没有什么可比的,即使是 cv2.flip 或 cv2.transpose 也慢得多。因此,我建议查看this recommendation on Intel's developer zone,它使用 ippiRotate 和 ippiMirror 函数来执行 90 次旋转。如果您真的有兴趣从 Intel cpu 中获得最佳性能,那将是我的猜测。还要注意多线程,一些功能可以在 IPP 中多线程。最后,这取决于您是否寻找一种解决方案来旋转单个大图像或多个大图像,数据类型,通道数。通过 IPP,您至少可以使用最适合您的数据类型的函数。
此后在 python 中进行了一些试验,以与 numpy 的 rot90 函数进行比较。当然结果会随着参数的变化而变化,但与 numpy 仍然存在很大差异。从我的试验中也看不出 cv2.rotate 这么快。

100x np.rot90 time       : 0.001626729965209961
100x cv2.rotate time     : 0.21501994132995605
100x cv2.transpose time  : 0.18512678146362305
100x cv2.remap time      : 0.6473801136016846
100x cv2.warpAffine time : 0.11946868896484375
import cv2
import numpy as np
import time

img = np.random.randint(0, 255, (1000, 1000, 3)).astype(np.uint8)

##################################
start = time.time()
for i in range(100):
    rotated = np.rot90(img)
end = time.time()
print("100x np.rot90 time       :", end - start)

##################################
start = time.time()
for i in range(100):
    rotated = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)
end = time.time()
print("100x cv2.rotate time     :", end - start)

##################################
start = time.time()
for i in range(100):
    rotated = cv2.transpose(img, 1)
end = time.time()
print("100x cv2.transpose time  :", end - start)

##################################
mapx, mapy = np.meshgrid(np.arange(0, img.shape[1]), np.arange(0, img.shape[0]))
mapx = mapx.transpose()
mapy = mapy.transpose()

start = time.time()
for i in range(100):
    rotated = cv2.remap(img, mapx.astype(np.float32), mapy.astype(np.float32), cv2.INTER_NEAREST)
end = time.time()
print("100x cv2.remap time      :", end - start)

##################################
rows = img.shape[0]
cols = img.shape[1]
M = cv2.getRotationMatrix2D((rows / 2, cols / 2), 90, 1)
M[0, 2] = 0
M[1, 2] = cols

start = time.time()
for i in range(100):
    rotated = cv2.warpAffine(img, M, (rows, cols), flags=cv2.INTER_NEAREST)
end = time.time()
print("100x cv2.warpAffine time :", end - start)

我希望这会有所帮助!

【讨论】:

  • warpAffine 不可能接近以 90 度为步长进行简单旋转的性能,这仅涉及像素的复制/重新排列。
  • 我尝试过使用warpAffine 函数。与rotate 函数相比,它需要很多时间。我想要比rotate 函数更快的东西。
  • rot90 不对数组本身做任何事情,它只是在原始数组上创建一个视图。 (您可以通过查看标志来检查这一点)。这当然非常快,但是使用这种非对齐视图可能会更慢。例如。 %timeit rotated*rotated -> 13.1 毫秒 %timeit img*img -> 3.59 毫秒。
  • @max9111 将rot90 的结果反馈给 OpenCV 函数也会引入新问题,因为 Mat 不如 numpy 数组灵活(没有负步幅,没有列主要订单支持)。充其量这将涉及一个副本(基本上是在做rotate 所做的事情),最坏的情况是一些奇怪的故障(我已经看过几次了)。
  • @87VN0。非常感谢。我尝试使用英特尔 IPP 库中的 ippiMirrorippiTranspose 函数进行 90 度图像旋转,速度非常快。对于 1280x500 的图像大小,OpenCV rotate 函数花费了 0.83 毫秒,而 ippiMirrorippiTranspose 函数在我的英特尔 i5 机器上总共只花费了 0.22 毫秒。
猜你喜欢
  • 2016-07-11
  • 2020-09-04
  • 2013-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多