如何在 python 中提取二维数组的第一个元素?

How to extract the first element of a 2d array in python?

假设我在 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]] ].我想提取每个条目的第一个元素并将它们全部放入像这样的一维数组 [3, 5, 6, 2, 7, 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 是否有可以执行此操作的库?

假设: 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])

我没有处理过像素和图像,无法解决您的其他问题,抱歉!

您可以zip列表的列表,使用next获取第一项作为元组,并使用list构造函数将元组转换为列表(如果您不需要列表形式的结果,列表转换是可选的):

list(next(zip(*img_hsv)))

编辑: 您修改后的问题现在有一个列表列表列表(如您所说的 3d 数组),因此您可以先使用生成器表达式展平列表并应用同上逻辑:

list(next(zip(*(t for s in img_hsv for t in s))))

切片数组是迄今为止最快的可用方法。您导入的数组本质上是 3 维的,举个例子,让我们从域 0-10 中的随机数创建一个 3 维数组:

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]]])

现在,您想 select 第一个值(在您的例子中是色调)通过:

hue = img[:, :, 0]

hue
Out[43]: 
array([[8, 9, 9],
       [5, 3, 3],
       [1, 9, 2],
       [8, 4, 3],
       [8, 0, 5]])

这将产生一个二维数组,但您想要一个一维数组:只需展平它

hue = hue.flatten()

hue
Out[44]: array([8, 9, 9, 5, 3, 3, 1, 9, 2, 8, 4, 3, 8, 0, 5])

瞧,一维数组。阅读 flatten 的工作原理以了解它如何对输出进行排序。

虽然切片是这里最快的选项,但您询问如何改进 for 循环。你的循环的问题是你只遍历行。由于您在 3d 数组的前两个维度上操作,因此您需要有两个 for 循环(警告,这非常慢......阅读 "Big O notation" 可能会有帮助)。对循环进行以下更改就足够了

b = []
for row in img_hsv.shape[0]:
    for col in img_hsv.shape[1]:
        b.append(hsv[row, col, 0])

还有一件事,您说您希望输出 (b) 是一个数组。您目前已将其定义为列表,您可以通过

将其转换为数组
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 微秒与每个文件 80 毫秒(快 4200 倍)。

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)