将2张图像转换为numpy数组并逐像素比较

时间:2018-10-16 01:44:35

标签: python arrays numpy python-imaging-library

我正在使用枕头加载2张图像(显然是黑白图像,但是是RGB格式)并转换为灰度图像。我不能使用opencv。

aImage = Image.open(imageA.visualFilename).convert("L")
bImage = Image.open(imageB.visualFilename).convert("L")

我将它们转换为numpy数组。

aArray = np.array(aImage)
bArray = np.array(bImage)

我最终要做的是(1)计算每个阵列中的所有黑色像素,并且(2)逐像素比较aArray和bArray并计算匹配的黑色像素的数量。

当前让我感到困惑的是,当我打印print aArray.shape数组之一时,我不明白我在看什么。我正在使用np.set_printoptions(threshold='nan')打印整个数组,但是它似乎是一系列元素,其值比我预期的要多。我认为每个元素将包含单个255或0?

我是否要正确处理黑白像素?当我尝试转换为二进制“ 1”时,得到了“ True” /“ False”结果,这使我更加困惑。

此外,假设aArray和bArray看起来相同,但实际上相差几个像素,那么将“模糊逻辑”结合到逐像素比较这像素的最佳方法是什么?

仅提供其他信息,aImage.sizeaImage.mode返回

(184, 184)
L

2 个答案:

答案 0 :(得分:1)

听起来像您想要Numpy阵列给我。 当我这样做时,我使用

使用cv2将图像加载到数组中

img = cv2.imread(filepath, cv2.IMREAD_UNCHANGED)

使用我得到的我的演示img

>>> img.shape (2576, 4592, 3)

>>> img.max() 255

>>> img.min() 0

将其与第二张img进行比较会为每个像素生成一个布尔值,该布尔值表示这些像素是否相同。见

>>> (img == img2).shape (2576, 4592, 3)

您可以通过检查所有像素是否与True相比来确定图像是否相同:

>>> (img == img2).all() False

通过以下方式计算黑色像素:

>>> sum(sum(sum((img == 0).astype(int)))) 6136

在这里,每个轴求和三次。您还可以使用以下方法快速完成此任务:

>>> ((img == 0).astype(int)).sum() 6136

编辑:

问题的第二部分要难一些。

1)在x y方向上偏移。 然后,您可能会尝试通过将两个图像都嵌入更大的数组中来找到它。 现在,您可以使用聚类方法来查找要尝试连接的关键区域。 这应该导致移动甚至旋转,这应该是两个图像之间的平移。

2)另一方面,颜色偏移将需要对两个图像进行减法处理。 现在,您可以使用总和来计算黑白图像等极端情况的比率。

3)模糊逻辑。 您可以放弃比较索引的想法,而是在每个图像上滑动一个窗口并比较窗口中显示的集合。

编辑2: 不使用cv2的原因: 您可以跳过cv2加载,而只需像在问题中一样使用np.array(aArray)。我只是使用了cv2,因为我没有安装PIL,并想向您展示演示。

答案 1 :(得分:1)

对于初学者,L中的Image.open(visualFilename).convert("L")模式不会将图像转换为黑白,而是使用以下公式将图像转换为灰度:

  

L = R * 299/1000 + G * 587/1000 + B * 114/1000

分别是R,G和B,分别是红色,绿色和蓝色

此公式遍历整个图像,并将3(RGB)通道像素更改为最接近3通道配色方案的1(灰度)通道像素。这就是为什么最后不只获得0和255值的原因,而是得到的像素值介于0到255之间的原因。

首先要比较两个灰度图像之间的所有黑色像素,您必须定义黑色的真正含义。像10的黑色就足够了还是25的值已经为您黑了?您必须记住,颜色不是绝对的,其含义可以根据您的工作而改变。

因此,解决此问题的方法是设置一个阈值,在该阈值中您将定义“对您来说什么是黑色”。使用简单的阈值功能即可。因此,我认为这段简单的代码可能会解决您的问题:

import numpy as np

def threshold(array, th=50, above_to_max = False):
  #check type numpy
  if type(array) is np.ndarray:
    #Creates a copy to not mess with original
    array = array.copy()
     #set all values below threshold to 0
    array[array<=th] = 0
    if above_to_max:
      #set all values above threshold to 0
      array[array>th] = 255
    return array
  else:
    raise Exception("Array must be a numpy array")

#Example images
image1 = [[ 0,  5, 10, 15, 20],
          [ 25, 30, 35, 40, 45],
          [ 50, 55, 60, 65, 70],
          [175,180,185,190,195],
          [200,210,215,240,255]]

image2 = [[ 5,  5, 110,  5,  0],
          [ 25, 30, 35,  0, 15],
          [150, 55, 60, 65, 70],
          [275,280,285,290,295],
          [ 20, 10, 15,240,255]]

#Transform to array
array1 = np.asarray(image1, dtype=np.uint8)
array2 = np.asarray(image2, dtype=np.uint8)

#Apply threshold
tsh_array1 = threshold(array1)
tsh_array2 = threshold(array2)

print(' Array1\n', array1, '\n', 'Thresholded1\n',tsh_array1,'\n' )
print(' Array2\n', array2, '\n', 'Thresholded2\n',tsh_array2,'\n' )
equals = (tsh_array1==0)[tsh_array2==0]

print("Number of pixels in the same position equal to zero: {}".format(sum(equals)))

此代码呈现以下内容:

Array1
[[  0   5  10  15  20]
 [ 25  30  35  40  45]
 [ 50  55  60  65  70]
 [175 180 185 190 195]
 [200 210 215 240 255]] 
Thresholded1
[[  0   0   0   0   0]
 [  0   0   0   0   0]
 [  0  55  60  65  70]
 [175 180 185 190 195]
 [200 210 215 240 255]] 

Array2
[[  5   5 110   5   0]
 [ 25  30  35   0  15]
 [150  55  60  65  70]
 [ 19  24  29  34  39]
 [ 20  10  15 240 255]] 
Thresholded2
[[  0   0 110   0   0]
 [  0   0   0   0   0]
 [150  55  60  65  70]
 [  0   0   0   0   0]
 [  0   0   0 240 255]] 

Number of pixels in the same position equal to zero: 9

编辑:

让我们更好地看一下以下行:(tsh_array1==0)[tsh_array2==0]

  • (tsh_array1==0)返回与tsh_array1形状相同的数组,其值True的位置为0,否则为False

    < / li>
  • [tsh_array2==0]与where子句相同。它将过滤上一个项目tsh_array2==0

结果是一个看起来像这样的数组:

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

由于True与1相同,因此此数组的总和将返回两个数组中相同位置的零个数

希望对您有帮助!