2016-06-27 30 views
1

我正在對圖像進行一些數據分析。對於某些分析,我想將圖像的像素從原來存儲的RGB像素轉換爲HSV。將存儲爲numpy數組的圖像轉換爲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

「rgb_to_hsv」如何實現?另外,它一次只能處理一個像素嗎?如果是這樣,它不能一次處理所有像素嗎?你嘗試過cv2的'rgb2hsv' func嗎? – Divakar

+0

@Divakar它來自Python的colorsys。我在安裝cv2時遇到了問題,所以我沒有試着去嘗試。 – cwj

+0

分享'rgb_to_hsv'的實現? – Divakar

回答

1

正如沃倫Weckesser說,轉換功能是有問題的。我結束了使用matplotlib:

matplotlib.colors.rgb_to_hsv(arr)

現在跑得快一萬倍。

+0

它與colorsys的RGB2HSV轉換是否會產生類似的結果? – Divakar

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 

運行測試

讓我們一次了標準RGB圖像的大小爲(256,256),並創建讓我們使用[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'sOpenCV's彩色converion版本,但他們似乎產生不同的結果。爲了時機,無論如何我們都要包括它們。

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