mirror of
https://github.com/kristoferssolo/Traffic-Light-Detector.git
synced 2026-03-22 00:36:22 +00:00
Minor release update
Removed `setup.py` and its adjasant files. Removed `tox`. Wrote meta data in `pyproject.toml`. Migrated from `playsound` to `magicsound` (not tested).
This commit is contained in:
@@ -2,7 +2,6 @@ from typing import NamedTuple
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
from loguru import logger
|
||||
|
||||
|
||||
class ColorRange(NamedTuple):
|
||||
@@ -10,24 +9,40 @@ class ColorRange(NamedTuple):
|
||||
color2: tuple[int, int, int]
|
||||
|
||||
|
||||
@logger.catch
|
||||
class ColorAttributes:
|
||||
def __init__(self, name: str, color: tuple[int, int, int], lowers: ColorRange,
|
||||
uppers: ColorRange, hsv: cv2.cvtColor, minDist: int, param2: int) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
color: tuple[int, int, int],
|
||||
lowers: ColorRange,
|
||||
uppers: ColorRange,
|
||||
hsv: np.ndarray,
|
||||
minDist: int,
|
||||
param2: int,
|
||||
) -> None:
|
||||
self.name = name
|
||||
self.color = color
|
||||
|
||||
# set mask
|
||||
masks: list[cv2.inRange] = []
|
||||
masks = []
|
||||
for lower, upper in zip(lowers, uppers):
|
||||
masks.append(cv2.inRange(hsv, lower, upper))
|
||||
|
||||
self.mask = masks[0]
|
||||
if len(masks) > 1:
|
||||
for mask in masks:
|
||||
self.mask = cv2.add(self.mask, mask)
|
||||
|
||||
# set circle
|
||||
self.circle = cv2.HoughCircles(self.mask, cv2.HOUGH_GRADIENT, 1, minDist=minDist, param1=50,
|
||||
param2=param2, minRadius=0, maxRadius=30)
|
||||
self.circle = cv2.HoughCircles(
|
||||
self.mask,
|
||||
cv2.HOUGH_GRADIENT,
|
||||
1,
|
||||
minDist=minDist,
|
||||
param1=50,
|
||||
param2=param2,
|
||||
minRadius=0,
|
||||
maxRadius=30,
|
||||
)
|
||||
if self.circle is not None:
|
||||
self.circle = np.uint16(np.around(self.circle))
|
||||
|
||||
@@ -17,7 +17,13 @@ PATHS = (LOGS_PATH, IMAGES_IN_PATH, IMAGES_OUT_PATH, SOUND_PATH)
|
||||
|
||||
log_level = "DEBUG" if BASE_PATH.joinpath("debug").exists() else "INFO"
|
||||
# Set up logging
|
||||
logger.add(LOGS_PATH.joinpath("detection.log"), format="{time} | {level} | {message}", level=log_level, rotation="1 MB", compression="zip")
|
||||
logger.add(
|
||||
LOGS_PATH.joinpath("detection.log"),
|
||||
format="{time} | {level} | {message}",
|
||||
level=log_level,
|
||||
rotation="1 MB",
|
||||
compression="zip",
|
||||
)
|
||||
|
||||
|
||||
@logger.catch
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import cv2
|
||||
from playsound import playsound
|
||||
from magicsound import magicsound
|
||||
|
||||
from TrafficLightDetector.paths import SOUND_PATH
|
||||
from TrafficLightDetector.traffic_light_detector import TrafficLightDetector
|
||||
|
||||
|
||||
class TrafficLightDetectorCamera(TrafficLightDetector):
|
||||
|
||||
def __init__(self, source: int, sound: bool = False) -> None:
|
||||
self.video_capture = cv2.VideoCapture(source)
|
||||
self.sound = sound
|
||||
@@ -29,4 +28,4 @@ class TrafficLightDetectorCamera(TrafficLightDetector):
|
||||
|
||||
def _make_sound(self) -> None:
|
||||
if self.signal_color == "GREEN":
|
||||
playsound(str(SOUND_PATH.joinpath("move.mp3")))
|
||||
magicsound(str(SOUND_PATH.joinpath("move.mp3")))
|
||||
|
||||
@@ -28,9 +28,27 @@ class TrafficLightDetector:
|
||||
self.roi = self.image if roi is None else roi
|
||||
self.size = self.roi.shape if roi is not None else self.image.shape
|
||||
hsv = cv2.cvtColor(self.image if roi is None else self.roi, cv2.COLOR_BGR2HSV)
|
||||
self.red = ColorAttributes("RED", self.RED, self.RED_LOWER, self.RED_UPPER, hsv, minDist=80, param2=10)
|
||||
self.yellow = ColorAttributes("YELLOW", self.YELLOW, self.YELLOW_LOWER, self.YELLOW_UPPER, hsv, minDist=60, param2=10)
|
||||
self.green = ColorAttributes("GREEN", self.GREEN, self.GREEN_LOWER, self.GREEN_UPPER, hsv, minDist=30, param2=5)
|
||||
self.red = ColorAttributes(
|
||||
"RED", self.RED, self.RED_LOWER, self.RED_UPPER, hsv, minDist=80, param2=10
|
||||
)
|
||||
self.yellow = ColorAttributes(
|
||||
"YELLOW",
|
||||
self.YELLOW,
|
||||
self.YELLOW_LOWER,
|
||||
self.YELLOW_UPPER,
|
||||
hsv,
|
||||
minDist=60,
|
||||
param2=10,
|
||||
)
|
||||
self.green = ColorAttributes(
|
||||
"GREEN",
|
||||
self.GREEN,
|
||||
self.GREEN_LOWER,
|
||||
self.GREEN_UPPER,
|
||||
hsv,
|
||||
minDist=30,
|
||||
param2=5,
|
||||
)
|
||||
self.colors = [self.red, self.yellow, self.green]
|
||||
self.detect_traffic_lights = detectTrafficLights
|
||||
self.signal_color = ""
|
||||
@@ -39,8 +57,10 @@ class TrafficLightDetector:
|
||||
gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)
|
||||
# draw rectangle around traffic lights
|
||||
for x, y, width, height in self.CASCADE.detectMultiScale(gray, 1.2, 5):
|
||||
cv2.rectangle(self.image, (x, y), (x + width, y + height), (255, 0, 0), self.BOUNDARY)
|
||||
roi = self.image[y:y + height, x:x + width]
|
||||
cv2.rectangle(
|
||||
self.image, (x, y), (x + width, y + height), (255, 0, 0), self.BOUNDARY
|
||||
)
|
||||
roi = self.image[y : y + height, x : x + width]
|
||||
self._set_image(self.image, roi)
|
||||
self._draw_circle()
|
||||
|
||||
@@ -49,20 +69,46 @@ class TrafficLightDetector:
|
||||
if color.circle is None:
|
||||
continue
|
||||
for value in color.circle[0, :]:
|
||||
if value[0] > self.size[1] or value[1] > self.size[0] or value[1] > self.size[0] * self.BOUNDARY:
|
||||
if (
|
||||
value[0] > self.size[1]
|
||||
or value[1] > self.size[0]
|
||||
or value[1] > self.size[0] * self.BOUNDARY
|
||||
):
|
||||
continue
|
||||
|
||||
h, s = 0, 0
|
||||
for i in range(-self.RADIUS, self.RADIUS):
|
||||
for j in range(-self.RADIUS, self.RADIUS):
|
||||
if (value[1] + i) >= self.size[0] or (value[0] + j) >= self.size[1]:
|
||||
if (value[1] + i) >= self.size[0] or (
|
||||
value[0] + j
|
||||
) >= self.size[1]:
|
||||
continue
|
||||
h += color.mask[value[1] + i, value[0] + j]
|
||||
s += 1
|
||||
if h / s > 100:
|
||||
cv2.circle(self.roi if self.detect_traffic_lights else self.image, (value[0], value[1]), value[2] + 10, color.color, 2) # draws circle
|
||||
cv2.circle(color.mask, (value[0], value[1]), value[2] + 30, (255, 255, 255), 2)
|
||||
cv2.circle(
|
||||
self.roi if self.detect_traffic_lights else self.image,
|
||||
(value[0], value[1]),
|
||||
value[2] + 10,
|
||||
color.color,
|
||||
2,
|
||||
) # draws circle
|
||||
cv2.circle(
|
||||
color.mask,
|
||||
(value[0], value[1]),
|
||||
value[2] + 30,
|
||||
(255, 255, 255),
|
||||
2,
|
||||
)
|
||||
if self.TEXT:
|
||||
cv2.putText(self.roi if self.detect_traffic_lights else self.image, color.name,
|
||||
(value[0], value[1]), self.FONT, 1, color.color, 2, cv2.LINE_AA) # draws text
|
||||
cv2.putText(
|
||||
self.roi if self.detect_traffic_lights else self.image,
|
||||
color.name,
|
||||
(value[0], value[1]),
|
||||
self.FONT,
|
||||
1,
|
||||
color.color,
|
||||
2,
|
||||
cv2.LINE_AA,
|
||||
) # draws text
|
||||
self.signal_color = color.name
|
||||
|
||||
@@ -7,7 +7,6 @@ from TrafficLightDetector.traffic_light_detector import TrafficLightDetector
|
||||
|
||||
|
||||
class TrafficLightDetectorImages(TrafficLightDetector):
|
||||
|
||||
def __init__(self, path: Path) -> None:
|
||||
self.path = path
|
||||
self._set_image(cv2.imread(str(self.path)))
|
||||
|
||||
Reference in New Issue
Block a user