Python中的zip()以及where()

在使用OpenCV进行TemplateMatching的时候碰到这两个方法,查询官方文档和网上的使用方法,说的不是很清楚,遂在此记录自己的理解。

  • where ( )

    官方文档:

    numpy.where(condition[,x,y])
    Return elements, either from x or y, depending on condition.
    If only condition is given, return condition.nonzero().

    Parameters:condition : array_like, bool
    When True, yield x, otherwise yield y.
    x, y : array_like, optional

    Returns:out : ndarray or tuple of ndarrays
    If both x and y are specified, the output array contains elements of x where condition is True, and elements from y elsewhere.
    If only condition is given, return the tuple condition.nonzero(), the indices where condition is True.

什么意思呢?就是说where方法会根据条件来选择合适的输出,如果只给了条件,那么输出就是符合条件值的索引。具体看下面的例子。

>>>np.where([[True,False],[True,True]],
            [[1,2],[3,4]],
            [[9,8],[7,6]])

array([[1,8],[3,4]])

我们来分析一下为什么是这个结果,第一个array中的是条件,后面两个array是条件的作用范围,先看第一个True,根据文档中的描述,条件为真(1),选择X,此时选择第二个array即X中对应位置的值,即1,再看紧接着的False,此时因为条件为假(0),选择Y中对应的值,即8,后面与此一致,便得到了输出的结果。

再看下面的情况:

>>> a = np.array([1,2,3,4,5,6])
>>> np.where(a > 4)

(array([4, 5]),)

注意此时得到的结果是元祖类型,4,5代表了大于4的值的索引位置,这在OpenCV的模板匹配中很有作用。

再看一个二维数组的情况:

>>>a = np.arange(16).reshape(4,-1)
>>> a
array([[ 0,  1,  2,  3],
   [ 4,  5,  6,  7],
   [ 8,  9, 10, 11],
   [12, 13, 14, 15]])
>>> np.where(a > 9)
(array([2, 2, 3, 3, 3, 3]), array([2, 3, 0, 1, 2, 3]))

我们看到输出的结果同样是元祖类型,元祖里的第一个数组元素存储了所有大于9的值得第一维索引位置,它们与第二个数组中对应位置所存储的第二维索引位置结合,代表了大于9的六个值得具体位置,分别为(2,2)、(2,3)、(3,0)、(3,1)、(3,2)、(3,3)。

关于where()的用法就总结这么多,接下来介绍zip(),它能和where()产生很好的联动。

  • zip ( )

    zip()函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用*号操作符,可以将元组解压为列表。

    zip([iterable, …])

示例:

>>>b = [1,2,3]
>>>c = [4,5,6]
>>>d = [7,8,9,0]

>>>zz = zip(b,c)
>>>zzz = zip(b,d)
>>>unzzz = zip(*zzz)
>>>print(zz)

<zip object at 0x110ec2548>

我们得到了上示的结果,这是为什么呢,因为在python3中,zip返回的是一个可迭代的对象,我们通过循环遍历的方式可以打印出他的元素。进行如下操作:

>>>for i in zz:
>>>print(i)
(1, 4)
(2, 5)
(3, 6)

>>>for i in zzz:
>>>print(i)             # 元素个数与最短的列表一致
(1, 7)
(2, 8)
(3, 9)

>>>for i in unzzz:
>>>print(i)
(1, 2, 3)
(7, 8, 9)

接着看where()中我们使用的最后一个例子,我们对其结果使用zip()方法:

a = np.arange(16).reshape(4,-1)
c = np.where(a > 9)
z = zip(*c)

for i in c:
print(i)
[2 2 3 3 3 3]
[2 3 0 1 2 3]

for i in z:
print(i)
(2, 2)
(2, 3)
(3, 0)
(3, 1)
(3, 2)
(3, 3)

我们通过zip()方法得到了符合条件的值得位置。

Donate here!