0

I am new to OpenCV and python. I am trying to detect colors in real-time using a camera. I want to put an "if condition" when the detected color is Red, Green or Blue. If it detects red then it should print "The color is RED" The same is the case I want to apply with the Green and Blue color. Here is the code that is showing RGB colors separately. Is there anyone who can help me out with this? Thanks in advance :)

import cv2
import numpy as np
import matplotlib.pyplot as plt

cap = cv2.VideoCapture(0)

while True:
    _, frame = cap.read()
    hsv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # Red color
    low_red = np.array([161, 155, 84])
    high_red = np.array([179, 255, 255])
    red_mask = cv2.inRange(hsv_frame, low_red, high_red)
    red = cv2.bitwise_and(frame, frame, mask=red_mask)


    # Blue color
    low_blue = np.array([94, 80, 2])
    high_blue = np.array([126, 255, 255])
    blue_mask = cv2.inRange(hsv_frame, low_blue, high_blue)
    blue = cv2.bitwise_and(frame, frame, mask=blue_mask)

    # Green color
    low_green = np.array([25, 52, 72])
    high_green = np.array([102, 255, 255])
    green_mask = cv2.inRange(hsv_frame, low_green, high_green)
    green = cv2.bitwise_and(frame, frame, mask=green_mask)

    # Every color except white
    low = np.array([0, 42, 0])
    high = np.array([179, 255, 255])
    mask = cv2.inRange(hsv_frame, low, high)
    result = cv2.bitwise_and(frame, frame, mask=mask)

#   plt.imshow(mask,cmap='gray')

######## Chech if the shown object has red color or not ##########

    img_height, img_width, _=hsv_frame.shape
    for i in range(img_height):
        for j in range(img_width):
            if hsv_frame[i][j][1]>= low_red and hsv_frame[i][j][1]<=upper_red:
                print("Red found")

#     cv2.imshow("Red", red)
#     cv2.imshow("Blue", blue)
#     cv2.imshow("Green", green)

    if cv2.waitKey(1)==13:
        break

cap.release()
cv2.waitKey(1)
cv2.destroyAllWindows()

The error im getting is

---> 40 if hsv_frame[i][j][1]>= low_red and hsv_frame[i][j][1]<=upper_red: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

6
  • The error im getting is ####### ---> 40 if hsv_frame[i][j][1]>= low_red and hsv_frame[i][j][1]<=upper_red: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() ########## Commented Nov 6, 2019 at 7:24
  • low_red and upper_red (high_red) are the arrays and you are comparing them with hsv_frame[i][j][1]. what is the content of hsv_frame[i][j][1] ? Commented Nov 6, 2019 at 7:29
  • beer44 hsv_frame is converting footage into hsv. And for hsv_frame[i][j][1] i actually have no idea as im newbie. Can you please help me fix it? Commented Nov 6, 2019 at 7:33
  • low_red is a numpy array. hsv_array[i][j][1] returns a scalar value. You cannot compare a scalar value with an array. An hsv_array[i,j] should give you a numpy array which you can possibly compare with low_red if you want. But you cannot use the <= or related operators because they work on scalars only. (Atleast to my knowledge; I am not that familiar with python opencv) Commented Nov 6, 2019 at 7:38
  • 1
    If it's real-time, you should set up your constants outside the main loop (low_red, high_red, low_blue, high_blue...) More critically though, you shouldn't have the nested for loops inside the loop - use Numpy there. Commented Nov 6, 2019 at 8:28

2 Answers 2

1

The line

if hsv_frame[i][j][1]>= low_red and hsv_frame[i][j][1]<=upper_red:

compares two arrays, i.e. pixels (r,g,b) <= (r,g,b) which will return 3 values. i.e. (True/False, True/False, True/False).

So you need to use either,

any() (atleast 1 is true)

or

all() (all must be true)

considering its pixel comparision i would recommend you to use all,

replace it with the below code.

if (hsv_frame[i][j][1]>= low_red).all() and (hsv_frame[i][j][1]<=upper_red).all():
Sign up to request clarification or add additional context in comments.

Comments

1

Looks like you want to count if the image has red color or not, where red is defined by your low_red and high_red bounds.

You already have the mask with the red region, why not use that?

countRed = cv2.countNonZero(red_mask)
if countRed > 0: #choose whatever condition you want
    print("Red found")

1 Comment

Thank you very much. I put this on my code and it works too :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.