0

I am trying to detect the most repeated color range in an image, put a bounding box around it and label it with the color name, but while running, face this error ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() on the 60th line. what should I do about it?

import cv2
import numpy as np

img = cv2.imread("image path") 
img = cv2.resize(img, (0, 0), fx= 0.5, fy= 0.5)
img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)




red_lower = np.array([136, 87, 111], np.uint8)
red_upper = np.array([180, 255, 255], np.uint8)

blue_lower = np.array([78, 158, 124], np.uint8)
blue_upper = np.array([138, 255, 255], np.uint8)
    
yellow_lower = np.array([22, 60, 200], np.uint8)
yellow_upper = np.array([60, 255, 255], np.uint8)

green_lower = np.array([40, 100, 100], np.uint8)
green_upper = np.array([80, 255, 255], np.uint8)

white_lower = np.array([0, 0, 0], np.uint8)
white_upper = np.array([0, 0, 255], np.uint8)



red_mask = cv2.inRange(img, red_lower, red_upper)
blue_mask = cv2.inRange(img, blue_lower, blue_upper)
yellow_mask = cv2.inRange(img, yellow_lower, yellow_upper)
green_mask = cv2.inRange(img, green_lower, green_upper)
white_mask = cv2.inRange(img, white_lower, white_upper)



kernal = np.ones((5, 5), "uint8")

red = cv2.dilate(red_mask, kernal)
res = cv2.bitwise_and(img, img, mask = red_mask)

blue = cv2.dilate(blue_mask,kernal)
res1 = cv2.bitwise_and(img, img, mask = blue_mask)

yellow = cv2.dilate(yellow_mask,kernal)
res2 = cv2.bitwise_and(img, img, mask = yellow_mask)  

green = cv2.dilate(green_mask,kernal)
res3 = cv2.bitwise_and(img, img, mask = green_mask)    

white = cv2.dilate(white_mask, kernal)
res4 = cv2.bitwise_and(img, img, mask= white_mask)





colors  = [red, blue, yellow, green, white]
l1 = ["RED", "BLUE", "YELLOW", "GREEN", "WHITE"]

max_color = max(colors)  # line 60 # 

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

i = colors.index(max_color)
max_name  = l1[i]



#Tracking the red Color
l2 = []
l3 = []
contours, hierarchy = cv2.findContours(max_color, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)   
for pic, contour in enumerate(contours):
    area = cv2.contourArea(contour)
    l2.append(area)
    l2.append(contour)
    d = {}
    for i in range(len(l2)):
        d[l2[i]] = l3[i]
    max_area = max(l2)
    max_contour = d[max_area]
    x, y, w, h = cv2.boundingRect(max_contour)
    img = cv2.rectangle(img, (x, y) ,(x + w, y + h), (255 , 255, 255) ,2)
    cv2.putText(img, max_name, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255))



cv2.imshow("Color Tracking",img)
#cv2.imwrite("result", img)
cv2.waitKey(5000)
cv2.destroyAllWindows()
Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
  • 1
    Which is the 60th line? Please copy-paste the full error message, including the stack trace, in your post. That will give us a lot more information than a paraphrased message. You can [edit] at any time. – Cris Luengo Sep 11 '22 at 15:33
  • Did you intend to do something like `colors = [np.sum(red), np.sum(blue), …`? You want to find the color with the most pixels, no? – Cris Luengo Sep 11 '22 at 15:37
  • Post example image. You can upload to some free hosting service and put the link in a comment. – fmw42 Sep 11 '22 at 15:53
  • the error message says what to do: **`Use a.any() or a.all()`**. pick any of these to read more: https://stackoverflow.com/search?q=The+truth+value+of+an+array+with+more+than+one+element+is+ambiguous.+Use+a.any()+or+a.all() -- even first-time posters can add images to their questions. they'll just not be inlined, but they'll be there, as a link. – Christoph Rackwitz Sep 11 '22 at 16:13
  • Does this answer your question? [ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()](https://stackoverflow.com/questions/10062954/valueerror-the-truth-value-of-an-array-with-more-than-one-element-is-ambiguous) – Christoph Rackwitz Sep 11 '22 at 16:13
  • please review [ask] and [mre]. before posting a question, do some debugging and some research. – Christoph Rackwitz Sep 11 '22 at 16:16
  • i = colors.index(max_color). The max_color is not defined. You could comment in max_color = max(colors). – toyota Supra Sep 11 '22 at 16:43
  • 1
    "what should I do about it?": fix it if you want the program to run. –  Sep 11 '22 at 18:36
  • @CrisLuengo Yes, I want to detect the most repeated pixel so I can label the picture – senobar naderian Sep 12 '22 at 10:33

1 Answers1

0

The variables red, blue etc. contain image masks stored as 2-dim -arrays. So colors is a list of those masks. max will try to find the maximum value of the elements of this list by applying the comparison operator to pairs of the elements. If you compare two -arrays the result will be an array of the same shape that is consisting of True or False values. This can't be used for retrieving a maximum value, because more than one boolean values can't be used to decide which of those image is "greater".

If you want to sort the masks by the count of non-zero values, then you can use cv2.countNonZero() like this:

i, max_color = max(enumerate(colors), key=lambda x:cv2.countNonZero(x[1]))
max_name = l1[i]

Explanation:

  1. enumerate(colors) generates a list of pairs of index positions and masks
  2. max will get the maximum pair while using ...
  3. cv2.countNonZero(x[1]) on the second item of each pair as key value for comparison
Markus
  • 5,976
  • 5
  • 6
  • 21