Snesticle Snesticle - 1 month ago 7
Python Question

using numpy.any to match color in opencv gives strange results

I'm trying to turn on and off a relay based on the detection of a color in a frame from a webcam. Since it needs to do this in real time I chose to use numpy slicing. The problem is numpy ALWAYS detects the color I input unless I completely cover the camera and I'm just not seeing why.

Here is the relevant code snippet:

import numpy as np
import cv2
import video

while True:
ret,frame = cam.read()
img = frame.copy()
sens = 20
b = 0
#roughly neon green
img1B = 20
img1G = 230
img1R = 50
if np.any(np.logical_and(img[:,:,0]>=img1B-sens, img[:,:,0]<=img1B+sens)):
b = True
else:
b = False
if np.any(np.logical_and(img[:,:,1]>=img1G-sens, img[:,:,1]<=img1G+sens)):
g = True
else:
g = False
if np.any(np.logical_and(img[:,:,2]>=img1R-sens, img[:,:,2]<=img1R+sens)):
r = True
else:
r = False
print b,g,r


B,G,R shouldn't always be true unless the cam is seeing a neon green pixel so I'm not sure what's happening.

Answer

You Don't need to over-complicate the problem by using numpy operations thrice. You may simply use cv2.inRange() and cv2.countNonZero() to get your job done. The above steps can be modulated to a method which you may call from your while loop to process each webcam frame.

import cv2

def detect_color_blob(img_BGR, blob_color_BGR, tolerance, threshold):
    blob_color_lower = [blob_color_BGR[0] - tolerance, blob_color_BGR[1] - tolerance, blob_color_BGR[2] - tolerance]
    blob_color_upper = [blob_color_BGR[0] + tolerance, blob_color_BGR[1] + tolerance, blob_color_BGR[2] + tolerance]

    # Get a Binary Mask, where 255 => blob color found and 0=> blob color NOT found
    mask = cv2.inRange(img_BGR, blob_color_lower, blob_color_upper)

    # Check if the detected number of pixels is greater than threshold.
    return cv2.countNonZero(mask) > threshold
Comments