从光栅图像创建numPy数组

2024-10-01 07:51:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在ArcMap中将一个4band(RGB&nr红外线)光栅图像转换成numPy数组。一旦成功转换成numpy数组,我想计算图像上没有数据的像素数。当这些数据在通道1中被标记为“绿色”或“无”时,它们被标记为“蓝色”或“无”。我要找到他们。在

以下是我目前所掌握的情况:

import numpy
import os

myDir = "C:\\Temp\\temp"
# myFile = "4_pixel_test.tif"
myFile = "4band.tif"

# import 4band (R,G,B & nr Infrared) image
fName = os.path.join(myDir, myFile)
head, tail = os.path.split(fName)


# Convert Raster to Array, Default using LowerLeft as Origin
rasArray = arcpy.RasterToNumPyArray(fName)

# find out the number of bands in the image
nbands = rasArray.shape[0] # int
# print nbands (int)

blackCount = 0 # count the black pixels per image
th = 0 # Threhold value

# print rasArray

r, g, b, a = rasArray # not working

rCheck = numpy.any(r <= th)
gCheck = numpy.any(g <= th)
bCheck = numpy.any(b <= th)
aCheck = numpy.any(a == 0)

print rCheck
print gCheck
print bCheck
print aCheck


# show the results
if rCheck:
  print ("Black pixel (red): %s" % (tail))

elif gCheck:
  print ("Black pixel (green): %s" % (tail))

elif bCheck:
  print ("Black pixel (blue): %s" % (tail))

else:
  print ("%s okay" % (tail))

if aCheck:
  print ("Transparent pixel: %s" % (tail))

Runtime error Traceback (most recent call last): File "", line 14, in File "c:\program files (x86)\arcgis\desktop10.2\arcpy\arcpy__init__.py", line 1814, in RasterToNumPyArray return _RasterToNumPyArray(*args, **kwargs) RuntimeError: ERROR 999998: Unexpected Error.

^{pr2}$

我能够将光栅图像从代码here更改为numPY数组。在

不确定numPY数组是如何存储的,但当遍历它时,数据会从y轴开始打印出来,并向下(逐列)处理图像,而不是x(逐行)。在

我需要切换这个,这样我就可以从左上角到右下角逐像素地读取数据(RGBA)。不过,我对纽比的了解还不够。在

我认为这个错误可能是由于tiff的大小引起的:它在2.5MB时工作正常,但在4GB时却会出现问题。:(


Tags: the数据图像imageimportnumpyosany
2条回答

你好像在问np.nditer。在

除非需要低级控制,否则不希望使用nditer。然而,你几乎永远不需要这种程度的控制。最好不要使用nditer,除非您确切知道为什么需要它。在

你得到的是一个三维纽比阵列。您当前正在迭代数组中的每个元素。相反,您只需要迭代数组的前两个维度(宽度和高度)。在


迭代三维数组

作为一个快速的示例,您可以在没有ArcMap的情况下重现所看到的内容:

import numpy as np

data = np.random.random((3, 10, 10))

for value in np.nditer(data):
    print value

简要说明:我在这里使用arcpy的形状约定nbands x nrows x ncolumns。看到nrows x ncolumns x nbands也是很常见的。在这种情况下,后面部分中的索引表达式将不同于

同样,nditer不是您想要的,因此如果您确实想这样做(数组中的每个值而不是每个r、g、b像素),那么这样做的可读性会更高:

^{pr2}$

在这种情况下,两者是相同的。在


迭代像素

不过,如果继续下去,您需要遍历每个像素。在这种情况下,你可以做一些类似的事情:

import numpy as np

data = np.random.random((3, 10, 10))

for pixel in data.reshape(3, -1).T:
    r, g, b = pixel
    print r, g, b

在本例中,我们暂时将10x10x3阵列视为100x3阵列。因为默认情况下numpy数组迭代第一个轴,所以它将迭代每个r,g,b元素。在

如果您愿意,也可以直接使用索引,但速度会慢一些:

import numpy as np

data = np.random.random((3, 10, 10))

for i, j in np.ndindex(data.shape[:-2]):
    r, g, b = data[:, i, j]
    print r, g, b

矢量化,不要遍历numpy数组

不过,一般来说,像这样逐个元素遍历数组元素并不是使用numpy的有效方法。在

你提到你正在尝试检测何时波段被消除和/或设置为一个常量值。在

有三件事你可能是指:1)只有一个波段,2)某些波段的数据被设置为0(或其他值),3)图像是灰度级的,但存储为RGB。在

您可以通过查看numpy数组来检查频带数:

nbands = data.shape[0]

或者直接使用arcpy

nbands = raster.bandCount

这处理了第一种情况,但是,看起来你在试图检测什么时候乐队没有信息,而不是他们是否在那里。在

如果您总是希望至少有红色、绿色和蓝色(有时是alpha,有时不是),那么最简单的方法是将这些波段展开,这有点类似于:

r, g, b = data[:3, :, :]

这样的话,如果有α带,我们就忽略它,如果它不存在,那就不重要了。同样,假设数据的形状是nbands x nrows x ncolumns(而不是nrows x ncolumns x nbands)。在

下一步,如果我们想检查一个波段中的所有像素值是否为零,请不要迭代。相反,使用numpy布尔比较。它们的速度将大大提高(100倍):

r, g, b = data[:3, :, :]
print np.all(r == 0) # Are all red values zero?

但是,我猜你最想检测的是一个存储为RGB的灰度图像。在这种情况下,每个像素的红、绿、蓝值将相等,但像素不会全部相同。您可以通过以下操作进行检查:

gray = (r == b) & (b == g)
print np.all(gray)

一般来说,您并不想迭代numpy数组中的每个像素。请改用矢量化表达式。在

假设您已经知道图像大小(nxm),并且您的1d numpy数组是A,那么这就可以了。在

img2D = np.reshape(A, (m,n)).T

示例:假设您的图像数组是

^{pr2}$

但你被赋予 A=数组([1,3,5,2,4,6]) 你想要的输出是

 img2D = np.reshape(A, (2, 3)).T

相关问题 更多 >