I currently am trying to make a very primitive object detection system by taking an image as input, converting it to a list using PIL image, and sorting out pixels that are close enough to a predetermined color. I then take the average of those to get the location.
I'm planning to use this with a distance sensor and some basic trig to make a root that can grab objects without having to hard code it.
I've coded it using for loops, but it currently takes several seconds to run, and I wanted to put it into list comprehension, but I have no idea how to use list comprehension with nested loops and if statements. I've tried looking at tutorials online, but everything I've seen has been for simple list comprehension with only 1 variable or loop, and am completely lost
Here is the code I'm using
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])
and here is the link to my replit project
Instead of looping over the pixel values, I suggest converting the image to a numpy array and working with that. If you are not familiar with NumPy, it is the de facto standard way of working with numerical data in Python, and it lets us avoid the trouble of looping over individual rows / columns.
I include an example below of how you can get the pixel values that fit your criteria.
The values are all arbitrary, so you will have to put in your image and values for rgb thresholds.
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]