【问题标题】:Change multi dimensional numpy array values according to condition根据条件更改多维numpy数组值
【发布时间】:2018-10-25 06:05:59
【问题描述】:

我有一个 RGB 图像存储为一个 numpy 数组。我有一个颜色数组,我将在图像中搜索这些颜色并将这些 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]

非常感谢任何有效的方法。

【问题讨论】:

  • 这应该不起作用:colors[k,l],对吧?
  • @b-fg 你是对的。它是一个伪代码来表达我正在尝试的内容。可能有一些错误。
  • 请始终发布最少的完整且经过验证的代码。

标签: python arrays numpy indexing python-3.6


【解决方案1】:

@Gabriel M

一个很棒的方法。但我认为应该是

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的位置怎么替换呢?
【解决方案2】:

为什么不这样简化你的循环呢?:

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

【讨论】:

    【解决方案3】:

    对于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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-04
      • 2023-03-26
      • 1970-01-01
      • 2020-08-05
      • 2019-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多