Изменить значения многомерного массива в соответствии с условием - PullRequest
0 голосов
/ 25 октября 2018

У меня есть изображение RGB, хранящееся в виде массива.У меня есть цветовой массив, и эти цвета я буду искать в изображении и заменять эти значения RGB тем же скалярным значением.Остальные значения RGB, которые не совпадают, должны быть просто заменены на 0.

Цвета, которые я ищу, могут быть такими, как показано ниже:

colors = []
colors.append((69, 0, 9, 17))
colors.append((196, 127, 128,1))
colors.append((199, 5, 126, 19))
colors.append((55, 127, 126, 4))
colors.append((0, 127, 29, 2))
colors.append((68, 6, 124, 18))

4-е значения для каждого цветаэто значение, которое заменит соответствующие значения RGB.

Я пытался использовать np.asin, но он не ищет массивы.Он ищет только скаляры.Прямо сейчас я использую цикл for, но он очень медленный.

for i in range(image.shape[0]):
   for j in range(image.shape[1]):
      match = -1
      for k in range(len(colors)):  
         match = k       
         for l in range(3):
            if image[i,j,l] != colors[k][l]:
               match=-1
               break
         if match >=0 :
            break

      val = [0,0,0]
      if match >= 0:
         val = [colors[match][3],colors[match][3],colors[match][3]]
      for l in range(3):
         image[i,j,l] = val[l]

Любой эффективный подход будет очень признателен.

Ответы [ 3 ]

0 голосов
/ 25 октября 2018

Для ints, вот один способ, основанный на dimensionality-reduction, который обсуждается более подробно here -

# Based on https://stackoverflow.com/a/38674038/ @Divakar
def matching_index(X, searched_values, invalid_val=-1):
    dims = np.maximum(X.max(0),searched_values.max(0))+1
    X1D = np.ravel_multi_index(X.T,dims)
    searched_valuesID = np.ravel_multi_index(searched_values.T,dims)
    sidx = X1D.argsort()
    sorted_index = np.searchsorted(X1D,searched_valuesID,sorter=sidx)
    sorted_index[sorted_index==len(X1D)] = len(X1D)-1
    idx = sidx[sorted_index]
    valid = X1D[idx] == searched_valuesID
    idx[~valid] = invalid_val
    return valid, idx

# Convert to array
colors = np.asarray(colors)

# Get matching indices and corresponding valid mask
v, idx = matching_index(colors[:,:3],image.reshape(-1,3))
image2D = np.where(v,colors[:,-1][idx],0).reshape(image.shape[:-1])

# If you need a 3D image output
image3D = np.broadcast_to(image2D[...,None], image2D.shape + (3,))

Мы также можем использовать views для реализации эквивалентной версииmatching_index для общих данных dtype -

# https://stackoverflow.com/a/45313353/ @Divakar
def view1D(a, b): # a, b are arrays
    a = np.ascontiguousarray(a)
    b = np.ascontiguousarray(b)
    void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
    return a.view(void_dt).ravel(),  b.view(void_dt).ravel()

# Based on https://stackoverflow.com/a/38674038/ @Divakar
def matching_index_view(X, searched_values, invalid_val=-1):
    X1D,searched_valuesID = view1D(X,searched_values)
    sidx = X1D.argsort()
    sorted_index = np.searchsorted(X1D,searched_valuesID,sorter=sidx)
    sorted_index[sorted_index==len(X1D)] = len(X1D)-1
    idx = sidx[sorted_index]
    valid = X1D[idx] == searched_valuesID
    idx[~valid] = invalid_val
    return valid, idx
0 голосов
/ 25 октября 2018

@ Габриэль М

Отличный подход.Но я думаю, что это должно быть

for r,g,b, replace in colors:

    colors_match = np.where( np.all([image[:,:,0] == r, image[:,:,1] == g, image[:,:,2] == b], axis=0))
    image[colors_match] = replace
    print(colors_match)

или более просто

for r,g,b, replace in colors:

    colors_match = np.all([image[:,:,0] == r, image[:,:,1] == g, image[:,:,2] == b], axis=0)
    image[colors_match] = replace
    print(colors_match)

отредактировано

Чтобы заменить значения, которые не были преобразованы, сохраняя историю конверсийв другом массиве может быть выбор.

converted = np.zeros((image.shape[0], image.shape[1]), dtype=bool)
for r,g,b, replace in colors:

    colors_match = np.all([image[:,:,0] == r, image[:,:,1] == g, image[:,:,2] == b], axis=0)
    image[colors_match] = replace
    converted[colors_match] = True
image[~converted] = 0
0 голосов
/ 25 октября 2018

почему бы не упростить ваш цикл следующим образом?

1002 *
...