Извлеките максимальное значение набора пикселей из списка векторов.

Я работаю над Python, и мне нужно извлечь максимальные или минимальные значения из набора определенных пикселей на изображении. скажем, мое изображение имеет размер 40 на 40. У меня есть список с некоторым заданным примером векторных координат: vectorlist=[[10,15],[13,14],[15,23]]. Мне нужно извлечь значения пикселей этих векторов в списке и вычислить минимальное и максимальное значения. Я ищу какой-нибудь быстрый способ сделать это, потому что цикл FOR медленный.

a=[]
for i in range(0,len(vectorlist)):
       a.append(image[vectorlist[i][0],vectorlist[i][1]])
max1=max(a)
min1=min(a)

если есть более быстрый способ сделать это, это было бы здорово!

Спасибо!


person Daniel R    schedule 24.05.2018    source источник
comment
Если цикл for в вашем примере является обязательным для построения вашего массива, вы можете использовать его для получения максимальных и минимальных значений с чем-то вроде if (max1 is None or max1 > image[vectorlist[i][0],vectorlist[i][1]]):... и if (min1 is None or min1 < image[vectorlist[i][0],vectorlist[i][1]]):...   -  person Cid    schedule 24.05.2018
comment
Я все еще новичок в Python, но думаю, вам нужна модная индексация.... jakevdp.github.io/PythonDataScienceHandbook/ Или, может быть, маскированный массив... docs.scipy.org/doc/numpy-1.13.0/reference/   -  person Mark Setchell    schedule 24.05.2018


Ответы (2)


Я согласен с Марком в том, что создание массива масок, вероятно, хорошая идея, потому что вы можете повторно использовать эту маску для других операций с этим массивом.

import numpy as np
#create test data with random but reproducible data
np.random.seed(54321)
arr = np.random.randint(0, 255, (40, 40), dtype = "uint8")

vectorlist = [[10, 15], [13, 14], [15, 23]]
#extracting rows and columns of the vectorlist
rows, cols = zip(*vectorlist)
#create mask at points defined by vectorlist 
mask = np.zeros(arr.shape, dtype = bool)
mask[rows, cols] = True
print(arr[mask])
#output
#[ 49 245 197]
print(np.max(arr[mask]))
#245
print(np.min(arr[mask]))
#49

Обратите внимание, что индексация начинается с 0, а не с 1 - ваш вопрос не ясен, если это учитывать ваш vectorlist. И убедитесь, что в вашем списке первое значение представляет строку. Если нет, просто поменяйте местами rows и cols в скрипте при извлечении этих значений из объекта zip.

person Mr. T    schedule 24.05.2018
comment
это полностью исключает использование цикла for - person Jeru Luke; 24.05.2018

Я абсолютный новичок в Python, но, похоже, мой комментарий был неправильным, но я соберусь с духом, признаю это и скажу, как я это сделал, и, возможно, кто-то знает, почему. Прежде чем кто-либо скажет, что это не ответ, это так, потому что он улучшает исходный код (в функции loop()) за счет введения улучшенной функции loop2():

#!/usr/local/bin/python3
import numpy as np

# Generate an array 40x40 of random integers <100
image=np.random.randint(100,size=(40,40))

# List of pixels we like
vectorlist=[[0,0],[1,1],[1,0],[39,39]]

# Boolean mask of elements we like
mask=np.reshape(np.zeros(1600,dtype=bool),(40,40))
mask[0,0]=mask[1,1]=mask[1,0]=mask[39,39]=True

# OP's suggested method
def loop():
   a=[]
   for i in range(0,len(vectorlist)):
      a.append(image[vectorlist[i][0],vectorlist[i][1]])
   mi=min(a)
   ma=max(a)
   return(mi,ma)

# Slight improvement on OP's method
def loop2():
   # Don't add a bunch of items to a list we don't need
   mi=ma=image[vectorlist[0][0],vectorlist[0][1]]
   for i in range(1,len(vectorlist)):
      this=image[vectorlist[i][0],vectorlist[i][1]]
      if this>ma:
          ma=this
      elif this<mi:
          mi=this
   return (mi,ma)

# My very own slow method using a masked array
def masked():
   selpix=image[mask]
   mi=np.amin(selpix)
   ma=np.amax(selpix)
   return (mi,ma)

print(loop())
print(loop2())
print(masked())

Пример вывода

(22, 91)
(22, 91)
(22, 91)

Я вставил все вышеперечисленное в IPython, а затем провел следующие временные тесты:

In [178]: %timeit loop()
1.96 µs ± 6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [179]: %timeit loop2()
1.4 µs ± 2.21 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [180]: %timeit masked()
4.64 µs ± 32.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Разочарован в Челтнеме :-)

person Mark Setchell    schedule 24.05.2018