line-follow-pid / color_detector.py
samuellimabraz's picture
Implement real-time line detection application with Streamlit and OpenCV. Features include webcam input, interactive HSV color adjustment, multiple line detection algorithms (Hough, Adaptive Hough, Rotated Rectangle, Fit Ellipse, RANSAC), customizable region of interest, and confidence estimation. Includes necessary modules for color detection, line detection, and PID control.
1b7bc37 unverified
import cv2
import numpy as np
import os
class ColorDetector:
def __init__(self, color: str = None):
self.mask = None
self.result = None
self._hsv_color = None # Initialize internal hsv storage
# Set a default HSV range (full range)
self._hsv_color = np.array([[0, 0, 0], [179, 255, 255]], dtype=np.uint8)
@property
def hsv_color(self):
if self._hsv_color is None:
# Return a default wide range to avoid errors initially
return np.array([[0, 0, 0], [179, 255, 255]], dtype=np.uint8)
return self._hsv_color
@hsv_color.setter
def hsv_color(self, values):
try:
# Ensure input is a numpy array for consistency and clipping
values_np = np.array(values, dtype=np.uint8)
if values_np.shape != (2, 3):
raise ValueError("HSV values must be a 2x3 array [[h,s,v], [h,s,v]]")
# Verify and adjust HSV value limits using numpy clipping
values_np[0] = np.clip(values_np[0], [0, 0, 0], [179, 255, 255])
values_np[1] = np.clip(values_np[1], [0, 0, 0], [179, 255, 255])
# Ensure min <= max for each channel
for i in range(3):
if values_np[0, i] > values_np[1, i]:
values_np[0, i], values_np[1, i] = (
values_np[1, i],
values_np[0, i],
) # Swap if min > max
self._hsv_color = values_np
except (ValueError, TypeError) as e:
print(f"Error setting HSV values: {e}. Expected format [[h,s,v],[h,s,v]].")
def filterColor(self, img):
"""
Apply the HSV filter to an image.
Args:
img (numpy.ndarray): Input image in BGR format.
Returns:
tuple: (mask, filtered_result) - The binary mask and color-filtered result
"""
imgHsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_bound = self.hsv_color[0]
upper_bound = self.hsv_color[1]
# Filter the desired color
mask = cv2.inRange(imgHsv, lower_bound, upper_bound)
# Remove noise
mask = cv2.dilate(mask, np.ones((11, 11), np.uint8), iterations=1)
mask = cv2.erode(mask, np.ones((7, 7), np.uint8), iterations=1)
# Morphological operations for further noise removal and closing gaps
mask = cv2.morphologyEx(mask, cv2.MORPH_DILATE, np.ones((8, 8), np.uint8))
# Apply the mask to the original image to get the filtered result
result = cv2.bitwise_and(img, img, mask=mask)
# Store the results
self.mask = mask
self.result = result
return mask, result