将嵌套 for 循环转换为列表理解

问题描述 投票:0回答:2

我目前正在尝试制作一个非常原始的对象检测系统,方法是将图像作为输入,使用 PIL 图像将其转换为列表,并排序出足够接近预定颜色的像素。然后我取它们的平均值来获得位置。

我计划将其与距离传感器和一些基本的三角函数一起使用,以创建一个可以抓取物体而无需对其进行硬编码的根。

我已经使用 for 循环对其进行了编码,但当前需要几秒钟才能运行,我想将其放入列表理解中,但我不知道如何将列表理解与嵌套循环和 if 语句一起使用。 我尝试过在线查看教程,但我所看到的所有内容都是为了简单的列表理解,只有 1 个变量或循环,我完全迷失了

这是我正在使用的代码

for x in range(0, len(image)):
  for y in range(0, len(image[x])):
    pixel = image[x][y]
    #had to split because line was too long: line too long (180 > 88 characters)
    if (pixel[0] > red - error and pixel [0] < red + error):
      if (pixel[1] > green - error and pixel [1] < green + error):
        if (pixel[2] > blue - error and pixel [2] < blue + error):
          goodPixels.append([x,y])

这是我的 replit 项目的链接

python list-comprehension
2个回答
1
投票

我建议将图像转换为 numpy 数组并使用它,而不是循环像素值。如果您不熟悉 NumPy,它是 Python 中处理数值数据的事实上的标准方法,它可以让我们避免循环遍历各个行/列的麻烦。

我在下面提供了一个示例,说明如何获取符合您条件的像素值。

这些值都是任意的,因此您必须输入图像和 RGB 阈值。

import numpy as np
from PIL import Image

pil_im = Image.new("RGB", (128, 128))
image = np.array(pil_im)

red = 128
green = 50
blue = 200
error = 5

red_min = red - error
red_max = red + error
green_min = green - error
green_max = green + error
blue_min = blue - error
blue_max = blue + error

pixel_is_red = np.logical_and(image[:, :, 0] > red_min, image[:, :, 0] < red_max)
pixel_is_green = np.logical_and(image[:, :, 1] > green_min, image[:, :, 1] < green_max)
pixel_is_blue = np.logical_and(image[:, :, 2] > blue_min, image[:, :, 2] < blue_max)

# Get a boolean matrix of the pixels that are R, G, and B.
final_mask = pixel_is_red & pixel_is_green & pixel_is_blue

# Index the original image with our boolean mask, to recover the good pixels.
good_pixels = image[final_mask]

1
投票

正如 mkrieger1 在评论中指出的那样,列表理解并不一定会比构建具有嵌套循环的列表提高性能。它主要用于代码简洁和程序员更好的可读性。尽管可以使用多个

for
子句和表达式编写非常复杂的列表推导式,但它们通常不被鼓励,例如 Google 的 Python 风格指南 中的情况。

不过,为了理解列表理解,您提供的代码将如下所示:

goodPixels = [[x, y] for x in range(len(image)) for y in range(len(image[x])) if (image[x][y][0] > red - error and image[x][y][0] < red + error) and (image[x][y][1] > green - error and image[x][y][1] < green + error) and (image[x][y][2] > blue - error and image[x][y][2] < blue + error)]

由于复杂的列表推导式可能太长,您可能需要缩进它们:

goodPixels = [
  [x, y]
  for x in range(len(image)) 
  for y in range(len(image[x])) 
  if (image[x][y][0] > red - error and image[x][y][0] < red + error)
      and (image[x][y][1] > green - error and image[x][y][1] < green + error)
      and (image[x][y][2] > blue - error and image[x][y][2] < blue + error)
]
© www.soinside.com 2019 - 2024. All rights reserved.