比方说,我在python中有一个3d数组,看起来像这样[[[3,4,9],[5,3,1],[6,4,2]],[[2,3,6 ],[7、9、10],[5、12、4]],[[7、5、1],[3、1、2],[6、5、2]]]。我想提取每个条目的第一个元素,并将它们全部放入这样的1d数组中[3,5,6,2,7,5,5,7,3,6]。我正在使用hsv图像,其中每个像素都有一个3元组,其中每个条目对应于色相,饱和度和值。我只想提取每个像素的色相值并将其放入一维数组中。这是我的代码的样子。
import numpy as np
import colorsys
from skimage import color
from skimage.color import rgb2hsv
img = cv2.imread("input.jpg", 1)
img_hsv = color.rgb2hsv(img)
b = []
for i in img_hsv:
b.append(i[0][0])
问题是我正在阅读的图像为640x480,b的形状仅为640,这让我觉得我没有图像中的所有像素。所以我的两个问题是,我的for循环是否正确,我是否甚至需要for循环来执行此操作,或者python是否具有可以执行此操作的库?
答案 0 :(得分:1)
切片是迄今为止最快的方法。您要导入的数组本质上是3维的,例如,让我们从域0-10的随机数创建3d数组:
import numpy as np
img = np.random.randint(0, 10, (5, 3, 3))
img.shape
Out[36]:
(5, 3, 3)
Out[37]:
array([[[8, 0, 8],
[9, 0, 5],
[9, 0, 4]],
[[5, 2, 5],
[3, 3, 1],
[3, 4, 0]],
[[1, 2, 2],
[9, 0, 6],
[2, 5, 9]],
[[8, 6, 2],
[4, 5, 1],
[3, 3, 6]],
[[8, 0, 7],
[0, 6, 0],
[5, 2, 3]]])
现在,您要通过以下方式选择第一个值(在您的情况下为色相):
hue = img[:, :, 0]
hue
Out[43]:
array([[8, 9, 9],
[5, 3, 3],
[1, 9, 2],
[8, 4, 3],
[8, 0, 5]])
这将产生一个2d数组,但您需要一个1d:将其展平
hue = hue.flatten()
hue
Out[44]: array([8, 9, 9, 5, 3, 3, 1, 9, 2, 8, 4, 3, 8, 0, 5])
Voila,一维数组。阅读flatten如何工作以了解其如何对输出进行排序。
虽然切片是此处最快的选项,但您询问如何改进for循环。循环的问题是您仅遍历行。由于您是在3D数组的前两个维度上进行操作,因此需要有两个for循环(警告,这非常慢,有些读者可能对“ Big O表示法”有所了解)。对循环进行以下更改就足够了
b = []
for row in img_hsv.shape[0]:
for col in img_hsv.shape[1]:
b.append(hsv[row, col, 0])
还有一件事,您说您希望输出(b)是一个数组。您目前已将其定义为列表,可以通过以下方式将其转换为arry
b = np.array(b)
只是为了好玩,为了让我明白循环的慢点,我为每个选项定了时间。
import datetime as dt
import numpy as np
img = np.random.randint(0, 100, (640, 480, 3))
iterations = 100
d1 = dt.datetime.now()
for i in range(iterations):
hue = img[:, :, 0]
print('Slicing total time: ', dt.datetime.now() - d1)
d1 = dt.datetime.now()
for i in range(iterations):
hue = []
for row in range(img.shape[0]):
for col in range(img.shape[1]):
hue.append(img[row, col, 0])
print('Multiple total looping time: ', dt.datetime.now() - d1)
Slicing total time: 0:00:00.002107
Multiple total looping time: 0:00:08.860522
每个文件20微秒vs每个文件80毫秒(速度提高了4200倍)。
答案 1 :(得分:0)
让我们说: two_D = [[3,5,6],[2,7,5],[7,3,6]] 我通常也将这些数组称为列表列表。 如果您打印two_D [0],您会看到它将打印出您的第一个列表。 如果要到达第一个列表的第一个元素: two_D [0] [0]。
用于填充问题中的一维数组:
one_d = []
for i in range(len(two_D)):
one_d.append(two_D[i][0])
我还没有处理像素和图像,也无法解决您的其他问题,对不起!
答案 2 :(得分:0)
您可以zip
列表列表,使用next
作为元组获取第一项,并使用list
构造函数将元组转换为列表(列表转换如果不需要结果作为列表,则为可选):
list(next(zip(*img_hsv)))
编辑:现在,您修改后的问题具有列表列表列表(如您所说的3d数组),因此您可以首先使用生成器表达式展平列表并应用上面的相同逻辑:
list(next(zip(*(t for s in img_hsv for t in s))))
答案 3 :(得分:0)
from array import *
a = [[[3, 4, 9], [5, 3, 1], [6, 4, 2]], [[2, 3, 6], [7, 9, 10], [5, 12, 4]], [[7, 5, 1], [3, 1, 2], [6, 5, 2]]]
b=[]
j=0
m=0
print(a[0][0])
while j<len(a):
print("J:",j)
l=0
for k in a[j]:
print(j,l)
b.insert(m, a[j][l][0])
l+=1
m+=2
j+=1
print(b)
j和m变量用于跟踪数组(a)中的嵌套迭代,j在第一个嵌套内递增,而m在第二个嵌套内递增2,因此可以获得每个嵌套数组的所有第0个元素并插入到数组(b)