OpenCL 中的快速 2D 直方图与 PyOpenCL



我正在尝试在 Python 中对 HSV 图像进行 2D 直方图,但即使使用 numpy 和 opencv,它也不够快(我实际上是用视频做的,但认为每一帧只是一个图像)。

我正在寻找最饱和的色相值。目前我有以下代码,它工作正常,但太慢了。

hist, xbins, ybins = np.histogram2d(hsv_channels[0].ravel(), saturation_channel.ravel(), [180,256],[[0,180],[0,256]])

我希望用 PyOpenCL 来做这件事,并将计算推送到 GPU,但除了 OpenCL 中的 hello world 程序。我找到了一些关于做这些事情的论文,但我不确定从哪里开始。

我将如何开始?

编辑:

我再想了一下。我认为我想在GPU上执行的步骤大致如下:

  1. 将图像转换为 1D 数组(如果为 10x10,则转换为 100 长数组)
  2. 将图像上传到图形处理器
  3. 将图像拆分为 N 个切片进行处理,其中 n 是并行计算单元的数量。或者,每个数组都可以引用此数组上的特定范围。
  4. (地图)对于每个计算单元,分配 180 个"箱",每个箱可以包含 256 个其他箱。每个内容的最里面只是一个用于计数的整数。
  5. 对于每个色调(180 个箱之一),计算每个饱和度级别(其他 256 个箱)有多少个色相。对可以计数的数组的子部分执行此操作。
  6. 创建新的空箱集。
  7. 减少)对于所有这些箱计数,然后将它们合并在一起(添加值)。我不确定我是否需要等到它们全部完成,或者只是按顺序与上面的空垃圾箱合并
  8. (确定最终答案)对于最后一组箱,循环遍历它们并找到该色调的最大饱和度值,并将其存储。现在找到具有最大饱和度的色调。作为最终答案,返回此色调 # 和此最大饱和度 #。

尽管如此,我对 PyOpenCL(或整个 OpenCL)的 GPU 知识还不够了解,无法正确做到这一点。

如果你采用不同的方法,你可以将计算时间减少到直方图2d所花费时间的2%左右。在 3143x2095 的图像上,此方法大约需要 5 毫秒,而 直方图2d 浪费了大约 280 毫秒。

import cv2
import numpy as np
from numpy import unravel_index
import time
img = cv2.imread('ducks.jpg')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
print hsv.shape
hue = hsv[:, :, 0]
sat = hsv[:, :, 1]
start = time.time()
max_index = unravel_index(sat.argmax(), sat.shape)
end = time.time()
print 'argmax time:', end - start
print sat[max_index]
print hue[max_index]
start = time.time()
hist, xbins, ybins = np.histogram2d(hue.ravel(), sat.ravel(), [180, 256], [[0, 180], [0, 256]])
end = time.time()
print 'histogram2d time:', end - start

输出:

(2095, 3143, 3)
argmax time: 0.00526285171509
255
39
histogram2d time: 0.288522958755
处理具有

最大饱和度值的多个像素的情况很容易。

最新更新