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

时间:2019-01-23 19:50:40

标签: python image numpy hsv

比方说,我在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是否具有可以执行此操作的库?

4 个答案:

答案 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)