我正在对图像进行一些数据分析。对于某些分析,我想将图像的像素从最初存储它们的RGB转换为HSV。
目前我正在使用此代码:
def generate_hsv(im):
coords = product(range(im.shape[0]), range(im.shape[1]))
num_cores = multiprocessing.cpu_count()
m = Parallel(n_jobs=num_cores)(delayed(process_pixels)(im[i]) for i in coords)
return np.array(m).reshape(im.shape)
process_pixels
只是我转换函数的包装器:
def process_pixels(pixel):
return rgb_to_hsv(pixel[0], pixel[1], pixel[2])
事情是它运行缓慢。
有更有效的方法吗?还是更好的并行化方法?
答案 0 :(得分:1)
正如Warren Weckesser所说,转换功能存在问题。我最终使用了matplotlib:
matplotlib.colors.rgb_to_hsv(arr)
现在运行速度提高了一百万倍。
答案 1 :(得分:1)
Colorsys
模块具有每个像素的实现,输入预期为(R,G,B)
。现在,colorsys
's implementation列在下面 -
def rgb_to_hsv(r, g, b):
maxc = max(r, g, b)
minc = min(r, g, b)
v = maxc
if minc == maxc:
return 0.0, 0.0, v
s = (maxc-minc) / maxc
rc = (maxc-r) / (maxc-minc)
gc = (maxc-g) / (maxc-minc)
bc = (maxc-b) / (maxc-minc)
if r == maxc:
h = bc-gc
elif g == maxc:
h = 2.0+rc-bc
else:
h = 4.0+gc-rc
h = (h/6.0) % 1.0
return h, s, v
我假设正在读取的图像是(B,G,R)
格式,就像使用OpenCV的cv2.imread
一样。因此,让我们对上面提到的函数进行矢量化,以便我们可以以矢量化方式处理所有像素。对于矢量化,通常优选的方法是broadcasting
。因此,使用它,rgb_to_hsv
的矢量化实现看起来像这样(请注意如何在此处传输循环代码中的相应部分) -
def rgb_to_hsv_vectorized(img): # img with BGR format
maxc = img.max(-1)
minc = img.min(-1)
out = np.zeros(img.shape)
out[:,:,2] = maxc
out[:,:,1] = (maxc-minc) / maxc
divs = (maxc[...,None] - img)/ ((maxc-minc)[...,None])
cond1 = divs[...,0] - divs[...,1]
cond2 = 2.0 + divs[...,2] - divs[...,0]
h = 4.0 + divs[...,1] - divs[...,2]
h[img[...,2]==maxc] = cond1[img[...,2]==maxc]
h[img[...,1]==maxc] = cond2[img[...,1]==maxc]
out[:,:,0] = (h/6.0) % 1.0
out[minc == maxc,:2] = 0
return out
运行时测试
让我们为大小为(256,256)
的标准RGB图像计时,并创建让我们使用[0,255]
中的随机数。
以下是在像素图像上使用colorsys的rgb_to_hsv
的典型方法:
def rgb_to_hsv_loopy(img):
out_loopy = np.zeros(img.shape)
for i in range(img.shape[0]):
for j in range(img.shape[1]):
out_loopy[i,j] = colorsys.rgb_to_hsv(img[i,j,2],img[i,j,1],img[i,j,0])
return out_loopy
作为替代方案,还有matplotlib's
和OpenCV's
色彩转换版本,但它们似乎会产生不同的结果。为了时间安排,我们还是要包括它们。
In [69]: img = np.random.randint(0,255,(256,256,3)).astype('uint8')
In [70]: %timeit rgb_to_hsv_loopy(img)
1 loops, best of 3: 987 ms per loop
In [71]: %timeit matplotlib.colors.rgb_to_hsv(img)
10 loops, best of 3: 22.7 ms per loop
In [72]: %timeit cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
1000 loops, best of 3: 1.23 ms per loop
In [73]: %timeit rgb_to_hsv_vectorized(img)
100 loops, best of 3: 13.4 ms per loop
In [74]: np.allclose(rgb_to_hsv_vectorized(img),rgb_to_hsv_loopy(img))
Out[74]: True # Making sure vectorized version replicates intended behavior