2014-04-06 107 views
2

我一直在使用PyOpenCL製作圖像的副本時遇到了一些麻煩。我想嘗試複製,因爲我真的想做其他處理,但我無法理解訪問每個像素的基本任務。請幫我找出錯誤,確保它能正常工作。使用PyOpenCL複製圖像

這裏是程序

import pyopencl as cl 
import numpy 
import Image 
import sys 

img = Image.open(sys.argv[1]) 
img_arr = numpy.asarray(img).astype(numpy.uint8) 
dim = img_arr.shape 

host_arr = img_arr.reshape(-1) 

ctx = cl.create_some_context() 
queue = cl.CommandQueue(ctx) 
mf = cl.mem_flags 
a_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=host_arr) 
dest_buf = cl.Buffer(ctx, mf.WRITE_ONLY, host_arr.nbytes) 

kernel_code = """ 
    __kernel void copyImage(__global const uint8 *a, __global uint8 *c) 
    { 
     int rowid = get_global_id(0); 
     int colid = get_global_id(1); 

     int ncols = %d; 
     int npix = %d; //number of pixels, 3 for RGB 4 for RGBA 

     int index = rowid * ncols * npix + colid * npix; 
     c[index + 0] = a[index + 0]; 
     c[index + 1] = a[index + 1]; 
     c[index + 2] = a[index + 2]; 
    } 
    """ % (dim[1], dim[2]) 

prg = cl.Program(ctx, kernel_code).build() 

prg.copyImage(queue, (dim[0], dim[1]) , None, a_buf, dest_buf) 

result = numpy.empty_like(host_arr) 
cl.enqueue_copy(queue, result, dest_buf) 

result_reshaped = result.reshape(dim) 
img2 = Image.fromarray(result_reshaped, "RGB") 
img2.save("new_image_gpu.bmp") 

我給的輸入是 enter image description here

不過的圖像,從程序的輸出是 enter image description here

我不能有道理爲什麼會出現這些黑線。 請幫我解決這個bug。

謝謝你

行!所以我找到了一個解決方案。我將所有的uint8都改爲int,並且在numpy數組中我刪除了「astype(numpy.uint8)」。我不知道爲什麼,我只是試過這個,它工作。解釋爲什麼會有幫助。此外,這是否意味着現在需要更多的記憶? 它的工作原理,但現在我認爲它需要更多的內存。任何使用uint8的解決方法都會有所幫助。

回答

4

您在Python和OpenCL中使用的數據類型之間存在不匹配。在numpy中,uint8是一個8位無符號整數(我認爲這是你以後的樣子)。在OpenCL中,uint8是32位無符號整數的8元素向量。 OpenCL中8位無符號整數的正確數據類型僅爲uchar。所以,您的astype(numpy.uint8)沒問題,但它應該在您的OpenCL內核中伴隨着__global const uchar*陣列。

如果您正在處理圖像,我還建議查看OpenCL的專用圖像類型,它可以利用本地支持來處理某些硬件中可用的圖像。

+0

謝謝你,讓uchar現在改變。我嘗試使用專用圖片類型,並試用[鏈接](http://code.google.com/p/opencl-book-sa​​mples/source/browse/trunk/src/Chapter_20/?r=17#Chapter_20% 2FPyImageFilter2D),但它給了我一些問題。所以決定改用數組。 – algrebe

+0

由於我現在有更多空間,因此我決定發送更多圖像以減少GPU和CPU之間的內存拷貝。但是,我覺得這是面臨類似的問題。我所做的只是添加一個'int imgid = get_global_id(0);並索引開始imgid * nrows * ncols * npix'不應該是足夠的? – algrebe

+0

這聽起來大致正確,假設您在使用Python加載圖像時創建相同的內存佈局。除非圖像非常小,否則我不會指望通過這種方式打包圖像會有巨大的性能提升(事實上,最好的方法可能是在處理圖像時將流程傳輸並傳輸圖像「n + 1」 'N')。 – jprice