0

In Python 3, I want to use opencv to study some live webcam footage. I have defined several colors, as follows (I do not believe that it is necessary for the answering of this question to run the below code, which requires some packages and a webcam, but I left it unchanged because of the perhaps peculiar variable/object "types" that I want to define):

import cv2
from imutils.video import VideoStream
import imutils
import numpy as np
from collections import OrderedDict 

colors = ["red", "blue", "green", "yellow", "orange"]
dict = {}
cap = cv2.VideoCapture(0)

# Red color
low_red = np.array([170,100,100]) #50-90: green
high_red = np.array([179,255,255])
# Blue color
low_blue = np.array([80,100,100])
high_blue = np.array([120,255,255])
# Green color
low_green = np.array([50,100,100]) #50-90: green
high_green = np.array([75,255,255])
# Orange color
low_orange = np.array([5,100,100]) #50-90: green
high_orange = np.array([15,255,255])
# Yellow color
low_yellow = np.array([22,100,100]) #50-90: green
high_yellow = np.array([35,255,255])

while True:
    _, frame = cap.read()

    hsv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    rgb_frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

until now, I have defined color masks for each color as follows:

    red_mask = cv2.inRange(hsv_frame,low_red,high_red)
    red = cv2.bitwise_and(frame, frame, mask=red_mask)

    blue_mask = cv2.inRange(hsv_frame,low_blue,high_blue)
    blue = cv2.bitwise_and(frame, frame, mask=blue_mask)

    green_mask = cv2.inRange(hsv_frame,low_green,high_green)
    green = cv2.bitwise_and(frame, frame, mask=green_mask)

    orange_mask = cv2.inRange(hsv_frame,low_orange,high_orange)
    orange = cv2.bitwise_and(frame, frame, mask=orange_mask)

    yellow_mask = cv2.inRange(hsv_frame,low_yellow,high_yellow)
    yellow = cv2.bitwise_and(frame, frame, mask=yellow_mask)

But since

  • I want to have the ability to later add more colors,
  • and there is much more I need to do for every single color
  • and this would greatly clutter the code,

I need a method that, for each color in the above list, creates new variables/array/objects that have the name low_red, high_red, red_mask etc. Below, the first three lines are what I currently have for each single color; the latter part is what I want to achieve.

    red_mask = cv2.inRange(hsv_frame, low_red, high_red)
    red_mask = cv2.erode(red_mask, None, iterations=1)
    red_mask = cv2.dilate(red_mask, None, iterations=1)

    for color in colors:
        str(color)+"_mask" = cv2.inRange(hsv_frame, eval("low_"+color), eval("high_"+color))
        str(color)+"_mask" = cv2.erode(color_mask, None, iterations=1)
        str(color)+"_mask" = cv2.dilate(color_mask, None, iterations=1)

As seen exemplary above, I have attempted different uses of the functions eval().

I also found many references to the use of dictionaries on the internet, including this website; but they were never used in the name of a newly created variable, only in the content, and I could not manage to solve my problem based on these examples.

Marie. P.
  • 255
  • 1
  • 4
  • 17
  • If I define a dictionary with 5 colors, and then loop over the dictionary's entries, then, if I understand correctly, 1. I would have to refer to colors by index (i.e. currently looping through 0-4 or 1-5) instead of color names; and thus 2. I would need to adjust the length of the dictionary in a hard-coded way every time I add a new color (looping through 0-5 or 1-6), no? Would that be an elegant and safe solution? – Marie. P. Feb 10 '20 at 11:37
  • Should it be something like: `colordict = {'red', 'blue', 'green', 'yellow', 'orange'}` `for i in range (4):` `print(colordict[i])` `colordict[i] + "_mask" = cv2.erode(colordict[i] + "_mask", None, iterations =1 )` , because this gives ´SyntaxError: cannot assign to operator`. – Marie. P. Feb 10 '20 at 11:43
  • 1
    If you have a `dict`, then you can loop over the entire dict in several different ways (just pick a suitable way), but there need not be code changes when the contents change. – quamrana Feb 10 '20 at 11:43
  • @Marie.P. What is your specific problem? You loop over a list of colors, so you can create a dictionary as `{'red': color_mask}` etc. – a_guest Feb 10 '20 at 11:49

1 Answers1

1

First you can create a dictionary to contain all the low and high values and then you can create a dictionary to contain the various color masks:

colors = {
    'red': (np.array([170,100,100]), np.array([179,255,255])),
    # add other colors here
}

color_masks = {}
for color, (low, high) in colors.items():
    mask = cv2.inRange(hsv_frame, low, high)
    mask = cv2.erode(mask, None, iterations=1)
    mask = cv2.dilate(mask, None, iterations=1)
    color_masks[color] = mask
a_guest
  • 34,165
  • 12
  • 64
  • 118