Project

General

Profile

semaforo.py

Versión final - Tiara Canepa, 01/06/2026 11:41 AM

Download (6.76 KB)

 
1
import cv2
2
import time
3
import socket
4
from grovepi import *
5
from enum import Enum
6

    
7
hog = cv2.HOGDescriptor()
8
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
9

    
10
cap = cv2.VideoCapture(0)
11
cap.open("peatones-dublin.mp4", cv2.CAP_FFMPEG)
12

    
13
class Estado(Enum):
14
    ROJO = 1
15
    AMARILLO = 2
16
    VERDE = 3
17

    
18
class Ultrasonico:
19

    
20
    def __init__(self, pin):
21
        self.pin = pin
22
        self.activo = True
23
        self.distancia = 0
24

    
25
        pinMode(pin, "INPUT")
26

    
27
    def activar(self):
28
        self.activo = True
29

    
30
    def desactivar(self):
31
        self.activo = False
32

    
33
    def getDistancia(self):
34
        try:
35
            distance = ultrasonicRead(self.pin)
36
            return distance
37
        except IOError as e:
38
            print("Error: " + str(e))
39

    
40
class Camara:
41

    
42
    def __init__(self):
43
        self.activo = True
44
        self.cap = cv2.VideoCapture(0)
45

    
46
    def activar(self):
47
        self.activo = True
48

    
49
    def desactivar(self):
50
        self.activo = False
51

    
52
    def getImagen(self):
53
        ret, frame = self.cap.read()
54

    
55
        return ret, frame
56

    
57
class Buzzer:
58

    
59
    def __init__(self, pin):
60
        self.pin = pin
61
        self.activo = True
62
        self.volumen = 50
63

    
64
        pinMode(pin, "OUTPUT")
65

    
66
    def activar(self):
67
        self.activo = True
68

    
69
    def desactivar(self):
70
        self.activo = False
71

    
72
    # TODO
73
    def pulsar(self, tiempo):
74
        pass
75

    
76
    def setVolumen(self, newVolumen):
77
        self.volumen = newVolumen
78

    
79
class Led:
80

    
81
    def __init__(self, pin):
82
        self.pin = pin
83
        self.activo = False
84

    
85
        pinMode(pin, "OUTPUT")
86

    
87
    def prender(self):
88
        digitalWrite(self.pin, 1)
89

    
90
    def apagar(self):
91
        digitalWrite(self.pin, 0)
92

    
93
class Boton:
94

    
95
    def __init__(self, pin):
96
        self.pin = pin
97

    
98
        pinMode(pin, "INPUT")
99

    
100
    def getEstado(self):
101
        try:
102
            status = digitalRead(self.pin)
103
            print("Button pressed")
104
            return status
105
        except IOError as e:
106
            print("Error: " + str(e))
107

    
108
class Sistema:
109

    
110
    def __init__(self, pinUts = 2, pinBoton = 3, pinBuzzer = 4, \
111
                pinLedRojo = 5, pinLedAmarillo = 6, pinLedVerde = 7):
112
        self.ultrasonico = Ultrasonico(pinUts)
113
        self.boton = Boton(pinBoton)
114
        self.buzzer = Buzzer(pinBuzzer)
115
        self.ledRojo = Led(pinLedRojo)
116
        self.ledAmarillo = Led(pinLedAmarillo)
117
        self.ledVerde = Led(pinLedVerde)
118
        self.camara = Camara()
119
        self.timer = Timer(SEGUNDOS_INTERVALO_FOTO)
120
        self.timerEstado = Timer(SEGUNDOS_SEMAFORO)
121

    
122
        self.prioridadPeatones = 0
123
        self.prioridadVehiculos = 100
124
        self.cantidadPeatones = 0
125
        self.distanciaVehiculos = 0
126
        
127
        self.setEstado(Estado.ROJO)
128

    
129
    def setEstado(self, nuevoEstado):
130
        self.estado = nuevoEstado
131

    
132
        if nuevoEstado == Estado.ROJO:
133
            self.ledAmarillo.apagar()
134
            self.ledVerde.apagar()
135
            self.ledRojo.prender()
136
        elif nuevoEstado == Estado.AMARILLO:
137
            self.ledVerde.apagar()
138
            self.ledRojo.apagar()
139
            self.ledAmarillo.prender()
140
        else:
141
            self.ledRojo.apagar()
142
            self.ledAmarillo.apagar()
143
            self.ledVerde.prender()
144
            
145
    def apagarTodo(self):
146
        self.ledAmarillo.apagar()
147
        self.ledVerde.apagar()
148
        self.ledRojo.apagar()
149

    
150
    def cambiarPaso(self):
151
        if self.estado == Estado.ROJO:
152
            self.setEstado(Estado.VERDE)
153

    
154
        elif self.estado == Estado.VERDE:
155
            self.setEstado(Estado.AMARILLO)
156
            time.sleep(3)
157
            self.setEstado(Estado.ROJO)
158

    
159
    def isPasoPeatones(self):
160
        return self.estado == Estado.ROJO
161

    
162
    # TODO
163
    def activarBuzzer(self):
164
        self.buzzer.activar()
165

    
166
    # TODO
167
    def calcularPrioridades(self):
168
        self.prioridadPeatones = 0
169
        self.prioridadVehiculos = 100
170

    
171
    def getCantidadPersonas(self):
172
        """Se usan HOGDescriptors para reconocer personas.
173
           Devuelve los rectángulos que encierran a las personas detectadas"""
174

    
175
        ret, frame = self.camara.getImagen()
176

    
177
        if not ret:
178
            print("Error obteniendo frame.")
179
            return -1
180

    
181
        # Reducir resolución para mayor rendimiento
182
        frame = cv2.resize(frame, (960, 540))
183
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
184

    
185
        personas, _ = hog.detectMultiScale(
186
            gray,
187
            winStride=(4,4),
188
            padding=(32,32),
189
            scale=1.3
190
            )
191

    
192
        return personas
193

    
194
class Timer:
195

    
196
    def __init__(self, segundos):
197
        self.startTime = time.time()
198
        self.tiempoPasado = 0
199
        self.segundos = segundos
200

    
201
    def timerTerminado(self):
202
        return self.tiempoPasado >= self.segundos
203

    
204
    def reiniciar(self):
205
        self.startTime = time.time()
206
        self.tiempoPasado = 0
207

    
208
    def actualizarTiempo(self):
209
        delta = time.time() - self.startTime
210
        self.startTime = time.time()
211
        self.tiempoPasado += delta
212

    
213
SEGUNDOS_SEMAFORO = 15
214
METROS_DISTANCIA_AUTO = 50
215
SEGUNDOS_INTERVALO_FOTO = 3
216
SEGUNDOS_INCREMENTO_TIMER = 3
217

    
218
def main():
219
    sistema = Sistema()
220
    personas = 0
221
    distancia = 100
222
    timerSegundo = Timer(1)
223

    
224
    try:
225

    
226
        while True:
227
            
228
            # Foto cada 3 segundos
229
            if sistema.timer.timerTerminado():
230
                distancia = sistema.ultrasonico.getDistancia()
231
                personas = len(sistema.getCantidadPersonas())
232
                print(f"Distancia: {distancia}")
233
                print(f"Personas: {personas}")
234
                sistema.timer.reiniciar()
235

    
236
                if personas == -1:
237
                    continue
238

    
239
            # Si hay autos esperando y ha pasado un segundo desde el último chequeo
240
            if sistema.isPasoPeatones() and timerSegundo.timerTerminado():
241
                timerSegundo.reiniciar()
242
                if distancia <= METROS_DISTANCIA_AUTO:
243
                    sistema.timerEstado.tiempoPasado += SEGUNDOS_INCREMENTO_TIMER
244
                    print("Reduciendo tiempo")
245

    
246
            # Si hay personas esperando y ha pasado un segundo desde el último chequeo
247
            elif not sistema.isPasoPeatones() and timerSegundo.timerTerminado():
248
                timerSegundo.reiniciar()
249
                if personas >= 3 and distancia >= METROS_DISTANCIA_AUTO:
250
                    sistema.timerEstado.tiempoPasado += SEGUNDOS_INCREMENTO_TIMER
251

    
252
            # Si el timer indica que hay que cambiar el paso
253
            if sistema.timerEstado.timerTerminado():
254
                sistema.cambiarPaso()
255
                sistema.timerEstado.reiniciar()
256

    
257
            sistema.timer.actualizarTiempo()
258
            sistema.timerEstado.actualizarTiempo()
259
            timerSegundo.actualizarTiempo()
260
            
261
    except KeyboardInterrupt:
262
        sistema.apagarTodo()
263

    
264
if __name__ == "__main__":
265
    main()
266

    
267
    cap.release()
268
    cv2.destroyAllWindows()