我目前正在尝试制作一个非常原始的对象检测系统,方法是将图像作为输入,使用 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])
我建议将图像转换为 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]
正如 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)]