图像使用什么数据类型?
What data-type is used for images?
我推导了 NDVI(归一化植被指数),它是 (NIR-R)/(NIR+R) 的比率,其中 NIR 是近红外波段,R 是红色波段。这个索引的范围从 -1 到 1。所以我写了一个 pyopencl 代码,这是我所做的和观察到的。
Python代码:
import pyopencl as cl
import cv2
from PIL import Image
import numpy as np
from time import time
import matplotlib.pyplot as plt
#get kernel file
def getKernel():
kernel = open('kernel.c').read()
return kernel
#return images as numpy int32 arrays
def convToArray(im_r,im_nir):
a = np.asarray(im_r).astype(np.int32)
b = np.asarray(im_nir).astype(np.int32)
return a,b
#processing part
def getDerivation(platform,device,im_r,im_nir):
#setting device
pltfrm = cl.get_platforms()[platform]
dev = pltfrm.get_devices()[device]
cntx = cl.Context([dev])
queue = cl.CommandQueue(cntx)
#get 2Darrays
r,nir = convToArray(im_r,im_nir)
#shape of array
x = r.shape[1]
mf = cl.mem_flags
bs = time()
#input images buffer
inR = cl.Buffer(cntx,mf.READ_ONLY | mf.COPY_HOST_PTR,hostbuf=r)
inIR = cl.Buffer(cntx,mf.READ_ONLY | mf.COPY_HOST_PTR,hostbuf=nir)
#output image buffers
ndvi = cl.Buffer(cntx,mf.WRITE_ONLY,r.nbytes)
be = time()
print("Buffering time: " + str(be-bs) + " sec")
ts = time()
#load kernel
task = cl.Program(cntx,getKernel()%(x)).build()
#execute the process
task.derive(queue,r.shape,None,inR,inIR,ndvi)
#create empty buffer to store result
Vout = np.empty_like(r)
#dump output buffers to empty arrays
cl.enqueue_copy(queue,Vout,ndvi)
te = time()
#convert arrays to gray - image compatible formate
NDVI = Vout.astype(np.uint8)
print("Processing time: " + str(te - ts) + " On: " + pltfrm.name + " --> " + dev.name)
return NDVI
def process(platform,device,im_r,im_nir):
NDVI,NDBI,NDWI = getDerivation(platform,device,im_g,im_r,im_nir,im_swir)
print(NDVI)
cv2.imshow("NDVI",NDVI)
cv2.waitKey(0)
if __name__ == '__main__':
R = cv2.imread("BAND3.jpg",0)
NIR = cv2.imread("BAND4.jpg",0)
print(R.dtype) #returns uint8
process(0,0,R,NIR) #(0,0) is my intel gpu
内核代码(C):
__kernel void derive(__global int* inR,__global int* inIR,__global int* ndvi){
int x = get_global_id(0);
int y = get_global_id(1);
int width = %d;
int index = x + y*width;
//ndvi ratio (-1 to 1)
int a = ((inIR[index] - inR[index])/(inIR[index] + inR[index])) * (256);
a = (a < (0) ? (-1*a) : (a));
a = (a > (255) ? (255) : (a));
ndvi[index] = (a);
}
输入图像R:
输入图像 NIR:
两个图像的位深度都是 8
但我得到的只是一张空白图像。最初出于调试原因,我在命令行上写了结果,
命令行输出:
(1151, 1151)
Buffering time: 0.015959739685058594 sec
Processing time: 0.22115755081176758 On: Intel(R) OpenCL --> Intel(R) HD Graphics 520
[[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]]
现在我想我可能没有为图像使用正确的数据类型?此外,在内核中,行 ((inIR[index] - inR[index])/(inIR[index] + inR[index]))
将给出一个浮点值,我将其乘以 256 以获得相应浮点值的像素值。那有问题吗?有人知道我哪里错了吗?
非常感谢您的帮助!
好的...我知道了。我只是将函数 convToArray()
中行 a = np.asarray(im_r).astype(np.int32)
中的数据类型更改为 float32
并且在内核文件中,我将参数类型更改为 float
并添加了 int a = (int)((((float)(inIR[index] - inR[index])/(float)(inIR[index] + inR[index]))+1)*127.5);
进行计算。然而,我需要一个解释,为什么这行得通,而不是其他方式......我可能会这样想,我们得到的结果此计算,int
类型在从 float
转换时丢失数据...是吗?
我推导了 NDVI(归一化植被指数),它是 (NIR-R)/(NIR+R) 的比率,其中 NIR 是近红外波段,R 是红色波段。这个索引的范围从 -1 到 1。所以我写了一个 pyopencl 代码,这是我所做的和观察到的。
Python代码:
import pyopencl as cl
import cv2
from PIL import Image
import numpy as np
from time import time
import matplotlib.pyplot as plt
#get kernel file
def getKernel():
kernel = open('kernel.c').read()
return kernel
#return images as numpy int32 arrays
def convToArray(im_r,im_nir):
a = np.asarray(im_r).astype(np.int32)
b = np.asarray(im_nir).astype(np.int32)
return a,b
#processing part
def getDerivation(platform,device,im_r,im_nir):
#setting device
pltfrm = cl.get_platforms()[platform]
dev = pltfrm.get_devices()[device]
cntx = cl.Context([dev])
queue = cl.CommandQueue(cntx)
#get 2Darrays
r,nir = convToArray(im_r,im_nir)
#shape of array
x = r.shape[1]
mf = cl.mem_flags
bs = time()
#input images buffer
inR = cl.Buffer(cntx,mf.READ_ONLY | mf.COPY_HOST_PTR,hostbuf=r)
inIR = cl.Buffer(cntx,mf.READ_ONLY | mf.COPY_HOST_PTR,hostbuf=nir)
#output image buffers
ndvi = cl.Buffer(cntx,mf.WRITE_ONLY,r.nbytes)
be = time()
print("Buffering time: " + str(be-bs) + " sec")
ts = time()
#load kernel
task = cl.Program(cntx,getKernel()%(x)).build()
#execute the process
task.derive(queue,r.shape,None,inR,inIR,ndvi)
#create empty buffer to store result
Vout = np.empty_like(r)
#dump output buffers to empty arrays
cl.enqueue_copy(queue,Vout,ndvi)
te = time()
#convert arrays to gray - image compatible formate
NDVI = Vout.astype(np.uint8)
print("Processing time: " + str(te - ts) + " On: " + pltfrm.name + " --> " + dev.name)
return NDVI
def process(platform,device,im_r,im_nir):
NDVI,NDBI,NDWI = getDerivation(platform,device,im_g,im_r,im_nir,im_swir)
print(NDVI)
cv2.imshow("NDVI",NDVI)
cv2.waitKey(0)
if __name__ == '__main__':
R = cv2.imread("BAND3.jpg",0)
NIR = cv2.imread("BAND4.jpg",0)
print(R.dtype) #returns uint8
process(0,0,R,NIR) #(0,0) is my intel gpu
内核代码(C):
__kernel void derive(__global int* inR,__global int* inIR,__global int* ndvi){
int x = get_global_id(0);
int y = get_global_id(1);
int width = %d;
int index = x + y*width;
//ndvi ratio (-1 to 1)
int a = ((inIR[index] - inR[index])/(inIR[index] + inR[index])) * (256);
a = (a < (0) ? (-1*a) : (a));
a = (a > (255) ? (255) : (a));
ndvi[index] = (a);
}
输入图像R:
输入图像 NIR:
两个图像的位深度都是 8
但我得到的只是一张空白图像。最初出于调试原因,我在命令行上写了结果, 命令行输出:
(1151, 1151)
Buffering time: 0.015959739685058594 sec
Processing time: 0.22115755081176758 On: Intel(R) OpenCL --> Intel(R) HD Graphics 520
[[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]]
现在我想我可能没有为图像使用正确的数据类型?此外,在内核中,行 ((inIR[index] - inR[index])/(inIR[index] + inR[index]))
将给出一个浮点值,我将其乘以 256 以获得相应浮点值的像素值。那有问题吗?有人知道我哪里错了吗?
非常感谢您的帮助!
好的...我知道了。我只是将函数 convToArray()
中行 a = np.asarray(im_r).astype(np.int32)
中的数据类型更改为 float32
并且在内核文件中,我将参数类型更改为 float
并添加了 int a = (int)((((float)(inIR[index] - inR[index])/(float)(inIR[index] + inR[index]))+1)*127.5);
进行计算。然而,我需要一个解释,为什么这行得通,而不是其他方式......我可能会这样想,我们得到的结果此计算,int
类型在从 float
转换时丢失数据...是吗?