从numpy数组中删除连续的RGB值

时间:2018-06-25 11:37:23

标签: python arrays numpy image-processing python-imaging-library

我最初从初始数组创建了一个子数组,用于从中生成灰度图像:Deleting consecutive numbers from a numpy arrayRemove following duplicates in a numpy array

但是现在我想对彩色图像做同样的事情,我真的很困惑。我已经研究了好几天了,根本无法理解如何处理它。

问题在于正方形的大小不同,我希望每个正方形用相同的颜色表示一个像素。

彩色图片:

Coloured image

我的灰度图像代码:

from PIL import Image
import numpy as np

name1 = raw_input("What is the name of the .png file you want to open? ")

filename1 = "%s.png" % name1

img = Image.open(filename1).convert('L')  # convert image to 8-bit grayscale
WIDTH, HEIGHT = img.size

a = list(img.getdata()) # convert image data to a list of integers
# convert that to 2D list (list of lists of integers)
a = np.array ([a[offset:offset+WIDTH] for offset in range(0, WIDTH*HEIGHT, WIDTH)])

print " "
print "Intial array from image:"  #print as array
print " "
print a

rows_mask = np.insert(np.diff(a[:, 0]).astype(np.bool), 0, True)
columns_mask = np.insert(np.diff(a[0]).astype(np.bool), 0, True)
b = a[np.ix_(rows_mask, columns_mask)]

print " "
print "Subarray from Image:"  #print as array
print " "
print b

#img = Image.fromarray(b, mode='L')

print " "
print "Subarray from Image (clearer format):"  #print as array
print " "
for row in b: #print as a table like format
    print(' '.join('{:3}'.format(value) for value in row))

#img.save("chocolate.png")


#print np.mean(b) #finding mean

例如此图片:

enter image description here

输入数组示例:

a = list(img.getdata()),这是我从图片中获得的输入。

[(115, 45, 135), (115, 45, 135), (115, 45, 135), (115, 45, 135), (115, 45, 135), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (115, 45, 135), (115, 45, 135), (115, 45, 135), (115, 45, 135), (115, 45, 135), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (115, 45, 135), (115, 45, 135), (115, 45, 135), (115, 45, 135), (115, 45, 135), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (115, 45, 135), (115, 45, 135), (115, 45, 135), (115, 45, 135), (115, 45, 135), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (115, 45, 135), (115, 45, 135), (115, 45, 135), (115, 45, 135), (115, 45, 135), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (245, 245, 35), (55, 235, 195), (55, 235, 195), (55, 235, 195), (55, 235, 195), (55, 235, 195), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (55, 235, 195), (55, 235, 195), (55, 235, 195), (55, 235, 195), (55, 235, 195), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (55, 235, 195), (55, 235, 195), (55, 235, 195), (55, 235, 195), (55, 235, 195), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (55, 235, 195), (55, 235, 195), (55, 235, 195), (55, 235, 195), (55, 235, 195), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (55, 235, 195), (55, 235, 195), (55, 235, 195), (55, 235, 195), (55, 235, 195), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (55, 235, 195), (55, 235, 195), (55, 235, 195), (55, 235, 195), (55, 235, 195), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95), (245, 245, 95)]

使用a = np.array ([a[offset:offset+WIDTH] for offset in range(0, WIDTH*HEIGHT, WIDTH)])的numpy输入:

[[[115  45 135]
  [115  45 135]
  [115  45 135]
  [115  45 135]
  [115  45 135]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]]

 [[115  45 135]
  [115  45 135]
  [115  45 135]
  [115  45 135]
  [115  45 135]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]]

 [[115  45 135]
  [115  45 135]
  [115  45 135]
  [115  45 135]
  [115  45 135]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]]

 [[115  45 135]
  [115  45 135]
  [115  45 135]
  [115  45 135]
  [115  45 135]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]]

 [[115  45 135]
  [115  45 135]
  [115  45 135]
  [115  45 135]
  [115  45 135]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]
  [245 245  35]]

 [[ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]]

 [[ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]]

 [[ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]]

 [[ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]]

 [[ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]]

 [[ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [ 55 235 195]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]
  [245 245  95]]]

所需的输出:

[[[115  45 135] [245 245  35]]
[ 55 235 195] [245 245  95]]]

1 个答案:

答案 0 :(得分:3)

这应该做到:

columns_mask = np.insert(np.any(np.any(np.diff(a, axis=0).astype(np.bool), axis=1), axis=1), 0, True)
rows_mask = np.insert(np.any(np.any(np.diff(a, axis=1).astype(np.bool), axis=0), axis=1), 0, True)
print(a[np.ix_(columns_mask, rows_mask)])

输出:

[[[115  45 135]
  [245 245  35]]

 [[ 55 235 195]
  [245 245  95]]]

说明:
让我们举一个更具代表性的示例:

a = np.array([[[1, 2, 3],
               [1, 2, 3],
               [2, 4, 7],
               [2, 4, 7],
               [2, 4, 7]], 
              [[1, 2, 3],
               [1, 2, 3],
               [2, 4, 7],
               [2, 4, 7],
               [2, 4, 7]], 
              [[1, 2, 3],
               [1, 2, 3],
               [3, 4, 7],
               [3, 4, 7],
               [3, 4, 7]],
              [[1, 2, 3],
               [1, 2, 3],
               [3, 4, 7],
               [3, 4, 7],
               [3, 4, 7]],
              [[6, 4, 3],
               [6, 4, 3],
               [0, 1, 7],
               [0, 1, 7],
               [0, 1, 7]],
              [[6, 4, 3],
               [6, 4, 3],
               [0, 1, 7],
               [0, 1, 7],
               [0, 1, 7]]])

我选择尺寸为6x5x3,以便于跟踪。

对于R,G和B,我们将具有以下子数组:

>>> print(a[:,:,0])  # R
[[1 1 2 2 2]
 [1 1 2 2 2]
 [1 1 3 3 3]
 [1 1 3 3 3]
 [6 6 0 0 0]
 [6 6 0 0 0]]
>>> print(a[:,:,1])  # G
[[2 2 4 4 4]
 [2 2 4 4 4]
 [2 2 4 4 4]
 [2 2 4 4 4]
 [4 4 1 1 1]
 [4 4 1 1 1]]
>>> print(a[:,:,2])  # B
[[3 3 7 7 7]
 [3 3 7 7 7]
 [3 3 7 7 7]
 [3 3 7 7 7]
 [3 3 7 7 7]
 [3 3 7 7 7]]

请注意,在此示例中,我们有6种不同颜色的块。但是为了示例起见,对于某些组件,我选择了相同的值。
预期结果将是:

# R
[[1 2]
 [1 3]
 [6 0]]
# G
[[2 4]
 [2 4]
 [4 1]]
# B
[[3 7]
 [3 7]
 [3 7]]

首先,我们计算diff以便找到颜色方块之间的边界。
对于列:

>>> print(np.diff(a, axis=0))
[[[ 0  0  0]
  [ 0  0  0]
  [ 0  0  0]
  [ 0  0  0]
  [ 0  0  0]]

 [[ 0  0  0]
  [ 0  0  0]
  [ 1  0  0]
  [ 1  0  0]
  [ 1  0  0]]

 [[ 0  0  0]
  [ 0  0  0]
  [ 0  0  0]
  [ 0  0  0]
  [ 0  0  0]]

 [[ 5  2  0]
  [ 5  2  0]
  [-3 -3  0]
  [-3 -3  0]
  [-3 -3  0]]

 [[ 0  0  0]
  [ 0  0  0]
  [ 0  0  0]
  [ 0  0  0]
  [ 0  0  0]]]

以及行:

>>> print(np.diff(a, axis=1))
[[[ 0  0  0]
  [ 1  2  4]
  [ 0  0  0]
  [ 0  0  0]]

 [[ 0  0  0]
  [ 1  2  4]
  [ 0  0  0]
  [ 0  0  0]]

 [[ 0  0  0]
  [ 2  2  4]
  [ 0  0  0]
  [ 0  0  0]]

 [[ 0  0  0]
  [ 2  2  4]
  [ 0  0  0]
  [ 0  0  0]]

 [[ 0  0  0]
  [-6 -3  4]
  [ 0  0  0]
  [ 0  0  0]]

 [[ 0  0  0]
  [-6 -3  4]
  [ 0  0  0]
  [ 0  0  0]]]

仔细查看这些数字的来源。

接下来,我们使用.astype(np.bool)将所有非零元素转换为True。我们需要它来创建布尔掩码。有关使用布尔数组建立索引的更多信息,请参见NumPy docs
对于列,我们得到:

>>> print(np.diff(a, axis=0).astype(np.bool))
[[[False False False]
  [False False False]
  [False False False]
  [False False False]
  [False False False]]

 [[False False False]
  [False False False]
  [ True False False]
  [ True False False]
  [ True False False]]

 [[False False False]
  [False False False]
  [False False False]
  [False False False]
  [False False False]]

 [[ True  True False]
  [ True  True False]
  [ True  True False]
  [ True  True False]
  [ True  True False]]

 [[False False False]
  [False False False]
  [False False False]
  [False False False]
  [False False False]]]

对于行:

>>> print(np.diff(a, axis=1).astype(np.bool))
[[[False False False]
  [ True  True  True]
  [False False False]
  [False False False]]

 [[False False False]
  [ True  True  True]
  [False False False]
  [False False False]]

 [[False False False]
  [ True  True  True]
  [False False False]
  [False False False]]

 [[False False False]
  [ True  True  True]
  [False False False]
  [False False False]]

 [[False False False]
  [ True  True  True]
  [False False False]
  [False False False]]

 [[False False False]
  [ True  True  True]
  [False False False]
  [False False False]]]

现在,我们应该在第一个数组的行之间和第二个数组的列之间应用逻辑或运算。我们需要这样做,以免丢失与例如R色具有相同值的连续块。

>>> print(np.any(np.diff(a, axis=0).astype(np.bool), axis=1))
[[False False False]
 [ True False False]
 [False False False]
 [ True  True False]
 [False False False]]
>>> print(np.any(np.diff(a, axis=1).astype(np.bool), axis=0))
[[False False False]
 [ True  True  True]
 [False False False]
 [False False False]]

有关np.any的详细信息,请参见以下问题:How to operate logic operation of all columns of a 2D numpy array

现在,我们对颜色执行相同的操作:

>>> print(np.any(np.any(np.diff(a, axis=0).astype(np.bool), axis=1), axis=1))
[False  True False  True False]
>>> print(np.any(np.any(np.diff(a, axis=1).astype(np.bool), axis=0), axis=1))
[False  True False False]

最后,使用np.insert在数组的开头添加True来考虑第一个元素:

>>> print(np.insert(np.any(np.any(np.diff(a, axis=0).astype(np.bool), axis=1), axis=1), 0, True))
[ True False  True False  True False]
>>> print(np.insert(np.any(np.any(np.diff(a, axis=1).astype(np.bool), axis=0), axis=1), 0, True))
[ True False  True False False]

现在将这些索引与np.ix_结合使用以获得所需的结果:

columns_mask = np.insert(np.any(np.any(np.diff(a, axis=0).astype(np.bool), axis=1), axis=1), 0, True)
rows_mask = np.insert(np.any(np.any(np.diff(a, axis=1).astype(np.bool), axis=0), axis=1), 0, True)

>>> print(a[np.ix_(columns_mask, rows_mask)])
[[[1 2 3]
  [2 4 7]]

 [[1 2 3]
  [3 4 7]]

 [[6 4 3]
  [0 1 7]]]

就这样!

我们可以检查单独的颜色是否正确:

>>> print(a[np.ix_(columns_mask, rows_mask)][:, :, 0])  # R
[[1 2]
 [1 3]
 [6 0]]
>>> print(a[np.ix_(columns_mask, rows_mask)][:, :, 1])  # G
[[2 4]
 [2 4]
 [4 1]]
>>> print(a[np.ix_(columns_mask, rows_mask)][:, :, 2])  # B
[[3 7]
 [3 7]
 [3 7]]