I am running into a strange issue involving the use of cv2.inRange and could use some help.
For context, I am trying to identify the colors of each individual circle for this board game (board).
Since some of the colors look very similar, I had the idea to “tune” the colors to find the min and max HSV values for each color.
To do this, I first crop the area I am interested in.
def crop_circle(img, i, j):
h, w = img.shape[:2]
mask = np.zeros((h, w), np.uint8) # Empty black mask
cv2.circle(mask, calculate_center(i, j), CIRCLE_RADIUS, CIRCLE_COLOR, -1) # Fill in white circle
result = cv2.bitwise_and(img, img, mask=mask)
x, y, w, h = cv2.boundingRect(mask)
return result[y : y + h, x : x + w]
Then I split the image and calculate those min / max HSV values.
def split_image(img):
v, v2, v3 = cv2.split(img)
v_avg = int(cv2.mean(v)[0])
v2_avg = int(cv2.mean(v2)[0])
v3_avg = int(cv2.mean(v3)[0])
return v_avg, v2_avg, v3_avg
def calculate_optimal_colors(hsv_img, colors):
def _update_colors(hsv_img, letter, colors):
def _helper(img, color_detection, letter, colors):
v, v2, v3 = split_image(img)
if len(colors[letter][color_detection.name]) == 0:
colors[letter][color_detection.name] = [[v, v2, v3], [v, v2, v3]]
else:
values = colors[letter][color_detection.name]
values[0][0] = min(values[0][0], v)
values[0][1] = min(values[0][1], v2)
values[0][2] = min(values[0][2], v3)
values[1][0] = max(values[1][0], v)
values[1][1] = max(values[1][1], v2)
values[1][2] = max(values[1][2], v3)
if letter not in colors:
colors[letter] = {
COLOR_DETECTION.HSV.name: []
}
_helper(hsv_img, COLOR_DETECTION.HSV, letter, colors)
Then I use those min / max HSV values in attempt to determine what the most likely color is by passing those values to cv2.inRange. I try to calculate the percentage of matching pixels that are in that range.
def _calculate_letter_percentage(img, lower_range, upper_range, threshold=0.5):
mask = cv2.inRange(img, np.array(lower_range), np.array(upper_range))
# Calculate the percentage of matching pixels
total_pixels = mask.shape[0] * mask.shape[1]
matching_pixels = np.sum(mask > 0)
percentage = matching_pixels / total_pixels
return percentage if percentage > threshold else 0
However, the mask ALWAYS results in being all black (see below image). The number of matching pixels is always 0 (mask).
And I have confirmed that the incoming image to determine that percentage is in fact HSV (image).
Any ideas what is going on here? Thanks so much!