2015-10-18 102 views
1

我有以下使用Python和OpenCV的代碼。簡而言之,我有一堆在不同震源深度拍攝的圖像。這些代碼在所有焦深(z)中具有最大高斯拉普拉斯響應拉普拉斯位置的每個(x,y)位置挑選出像素,從而創建焦點疊加圖像。函數get_fmap創建一個2d陣列,其中每個像素將包含具有最大日誌響應的焦平面的編號。在以下代碼中,註釋掉的行是我當前的VIPS實現。它們在函數定義中看起來不兼容,因爲它只是部分解決方案。如何在Python中使用VIPS執行邏輯操作和邏輯索引?

# from gi.repository import Vips 

def get_log_kernel(siz, std): 
    x = y = np.linspace(-siz, siz, 2*siz+1) 
    x, y = np.meshgrid(x, y) 
    arg = -(x**2 + y**2)/(2*std**2) 
    h = np.exp(arg) 
    h[h < sys.float_info.epsilon * h.max()] = 0 
    h = h/h.sum() if h.sum() != 0 else h 
    h1 = h*(x**2 + y**2 - 2*std**2)/(std**4) 
    return h1 - h1.mean() 

def get_fmap(img): # img is a 3-d numpy array. 
    log_response = np.zeros_like(img[:, :, 0], dtype='single') 
    fmap = np.zeros_like(img[:, :, 0], dtype='uint8') 
    log_kernel = get_log_kernel(11, 2) 
    # kernel = get_log_kernel(11, 2) 
    # kernel = [list(row) for row in kernel] 
    # kernel = Vips.Image.new_from_array(kernel) 
    # img = Vips.new_from_file("testimg.tif") 
    for ii in range(img.shape[2]):   
     # img_filtered = img.conv(kernel) 
     img_filtered = cv2.filter2D(img[:, :, ii].astype('single'), -1, log_kernel) 
     index = img_filtered > log_response 
     log_response[index] = img_filtered[index] 
     fmap[index] = ii 
    return fmap 

然後fmap將被用來挑選出來自不同焦平面的像素來創建一個焦點堆棧圖像

這是一個非常大的圖像上完成的,而且我覺得VIPS可能做得更好比OpenCV就此。但是,官方文檔僅提供有關Python綁定的信息。根據我在互聯網上可以找到的信息,我只能夠進行圖像卷積工作(在我的情況下,它比OpenCV快一個數量級)。我想知道如何在VIPS中實現這一點,尤其是這些行?

log_response = np.zeros_like(img[:, :, 0], dtype = 'single') 

index = img_filtered > log_response 

log_response[index] = im_filtered[index] 

fmap[index] = ii 

回答

0

諮詢Python VIPS manual和一些試驗和錯誤之後,我拿出我自己的答案。我的問題numpy的和OpenCV的實現可以翻譯成VIPS這樣的:

from gi.repository import Vips 

img = [] 
for ii in range(num_z_levels): 
    img.append(Vips.Image.new_from_file("testimg_z" + str(ii) + ".tif") 

def get_fmap(img) 
    log_kernel = get_log_kernel(11,2) # get_log_kernel is my own function, which generates a 2-d numpy array. 
    log_kernel = [list(row) for row in log_kernel] # Vips.Image.new_from_array takes 1-d list array. 
    log_kernel = Vips.Image.new_from_array(log_kernel) # Turn the kernel into Vips array so it can be used by Vips. 
    log_response = img[0].conv(log_kernel, precision = Vips.Precision.FLOAT) 

    for ii in range(len(img)): 
     img_filtered = img[ii+1].conv(log_kernel, precision = Vips.Precision.FLOAT) 
     log_response = (img_filtered > log_response).ifthenelse(img_filtered, log_response) 
     fmap = (img_filtered > log_response).ifthenelse(ii+1, 0) 

邏輯索引是通過ifthenelse方法實現:

result_img = (test_condition).ifthenelse(value_if_true, value_if_false) 

語法相當靈活。測試條件可以是相同大小的兩個圖像之間或圖像與數值之間的比較,例如, img1 > img2img > 5。像明智一樣,value_if_true可以是單個值或Vips圖像。

+1

我是vips維護者。你的代碼看起來不錯。你看到vips'logmat'函數了嗎?它可能適合你。它創建一個日誌掩碼http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/libvips-create.html#vips-logmat從Python使用(例如)'Vips .Image.logmat(2,0.1)'。它會生成近似整數掩碼和可分離掩碼,這可以提供有用的加速。如果你願意,你可以使用字符串'「float」'而不是'Vips.Precision.FLOAT'。 – user894763

+1

(第2部分)你需要'索引'圖像嗎?我認爲你可以將其重寫爲'fmap =(img_filtered> log_response).ifthenelse(ii + 1,0)',我可能錯過了一些東西。如果你有任何可以共享的基準,我會很好奇速度和內存使用與opencv相比。 – user894763

+0

嘗試:'x = Vips.Image.logmat(2,0.1); x.matrixprint()'查看vips製作的日誌文件。添加'precision =「float」'獲得一個浮點版本。 – user894763

1

log_responsefmap被初始化爲在問題代碼3D陣列,而問題文本指出,輸出,fmap是2D陣列。因此,我假定log_responsefmap將被初始化爲2D陣列,其形狀與每個圖像相同。因此,該修改將 -

log_response = np.zeros_like(img[:,:,0], dtype='single') 
fmap = np.zeros_like(img[:,:,0], dtype='uint8') 

現在,回到問題的主題,你在每個圖像一個接一個上執行2D過濾,並在所有的堆疊圖像得到濾波輸出的最大指數。如果您不知道cv2.filter2D的文檔,它也可以用在多維數組上,從而爲我們提供多維數組作爲輸出。然後,獲取所有圖像的最大索引就像.argmax(2)一樣簡單。因此,執行必須是非常有效的,是簡單的 -

fmap = cv2.filter2D(img,-1,log_kernel).argmax(2) 
+0

謝謝。提供這個最簡單的例子時我犯了一個錯誤。我編輯了我的帖子。很高興知道'cv2.filter2d'具有這種用法。我一定會試一試。不過,默認情況下,VIPS使用多個內核,而使用OpenCV時,我必須自己實現這一點。並且向OpenCV添加多處理還會增加一些開銷。我不認爲'multiprocessing'模塊加上OpenCV會執行接近VIPS。我在具有11x11內核的3000x4000圖像上測試了高斯濾波。 VIPS在0.0025秒完成任務。 OpenCV花了0.1334秒。 – user3667217

+0

@ user3667217那麼,您是否已經在VIPS中實施了該解決方案? Si,在這裏分享一個答案?那麼,直到今天,我還沒有聽說過,所以謝謝!讓我知道任何其他的想法!那個VIPS,我當然看起來很有趣。 – Divakar

+0

我沒有在VIPS中獲得完整的解決方案,這就是爲什麼我會問如何在VIPS中執行邏輯操作和索引。顯然,VIPS正在積極開發(目前已經是第8版),但是很少有人知道。我設法做的是離現有的Python手冊沒有太遠。我只知道它執行高斯濾波並使用我自己的內核進行濾波。我仍在探索它。我會在OP中輸入代碼。 VIPS真的很棒。例如,它花費了0.0011秒的時間讀取圖像,而openCV花費了0.043秒。它的速度非常快。絕對值得一試! – user3667217