使用GPU和OpenCV测量图像的清晰度。

3

我创建了一个小脚本,使用像Laplacian这样的方法从一组图像中提取最清晰的图像:

sharpness = cv2.Laplacian(cv2.imread(path), cv2.CV_64F).var()

然而,这段代码执行速度有点慢,并且似乎只使用了CPU,所以我想知道是否有一种方法可以使用GPU计算该值,但是我只找到了关于图像处理的示例。


当你说慢 - 有多慢,对于什么图像属性和图像数量?它如何扩展? - jtlz2
一切都是相对的,不是吗?我正在处理一些千兆级别的4K图像,每张图像需要半秒钟,这还好,我只是想看看是否可能更快。 - Entretoize
1个回答

3

在了解耗时点之前,请勿进行优化。

大多数时间都花在加载图像上。计时一下,你就会发现这牵涉到访问大规模存储和解码图像格式。PNG并不是最复杂的,所以情况可能更糟。

拉普拉斯计算使用特定的内核。将图片与任意3x3内核卷积需要9次乘法和9次加法。而这个内核只需要一次移位和五次加减法。CPU的SIMD轻松应对。

GPU毫无帮助。将数据传输到GPU需要时间。然后启动GPU上的任何计算还有其他固定成本(延迟,“预热”)。而CPU已经完成了计算。如果有很多图片,至少可以将传输进行流水线处理,并且只需要上传内核代码一次。

在整个操作中,GPU和CPU都可能受到内存限制,这意味着计算能力远未受到挑战。

如果您真的想让GPU参与其中,最简单的方法是将numpy数组封装到cv.UMat中,然后传递UMat对象。然后OpenCV将使用OpenCL。结果将再次是UMat,因此您需要查看OpenCV函数可以为您计算方差。

h_im = cv.imread(...) # hostside data
d_im = cv.UMat(im) # usable on "device"
d_lap = cv.Laplacian(d_im, cv.CV_32F) # single floats are usually faster than doubles
h_lap = d_lap.get() # retrieve data
# numpy functions unavailable on UMat, hence hostside calculation
var = h_lap.var()
# try cv.meanStdDev, calculates for each channel

是的,没错,读取时间接近0.25秒,计算时间约为0.3秒,但仍有一定的余地。我会尝试找出如何使用GPU,不确定您所说的“将numpy数组包装在cv.UMat中”是什么意思... - Entretoize
授予的权限取决于处理器和特定图片。我碰巧挑选了一些随意文件夹中需要加载更多时间而不是处理时间的图片。我在另外几张图片中尝试过,加载时间比计算时间更短。-- 这只是 cv.Laplacian(cv.UMat(cv.imread(...)), cv.CV_32F).get().var()。单精度浮点数是个好主意,因为即使CPU仅对双精度有1:2的惩罚,许多GPU的惩罚更严重。 - Christoph Rackwitz
cv.Laplacian(cv.UMat(cv.imread(...)), cv.CV_32F).get().var() 可以正常工作,计算时间现在为0.08秒!我接受了你的答案,也许你可以在答案中添加你的评论。谢谢。 - Entretoize

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