Saltar a contenido

Seguimiento

Seguir línea negra en escala de grises

# Ejemplo de seguimiento de línea negra en escala de grises
#
# Crear un robot de seguimiento de línea requiere mucho esfuerzo. Este script de ejemplo muestra
# cómo realizar la parte de visión artificial del robot de seguimiento de línea. Puedes utilizar
# el resultado de este script para controlar un robot de tracción diferencial y que siga una línea.
# Este script solo genera un único valor de giro que indica al robot que gire a la izquierda o a la
# derecha.
#
# Para que este script funcione correctamente, debes apuntar la cámara hacia una línea en un ángulo
# de aproximadamente 45 grados. Asegúrate de que solo la línea se encuentre dentro del campo de visión
# de la cámara.

import sensor, image, time, math

# Traza una línea negra
GRAYSCALE_THRESHOLD = [(0, 64)]

# Cada región de interés (ROI) es (x, y, w, h). El algoritmo de detección de líneas intentará
# encontrar el centro del bloque más grande en cada ROI. A continuación, se promediará la
# posición x de los centros con diferentes pesos, asignando el mayor peso a la ROI situada cerca
# de la parte inferior de la imagen y menos peso a la siguiente ROI, y así sucesivamente
ROIS = [ # [ROI, pesos]
        (0, 100, 160, 20, 0.7), # Tendrás que ajustar los pesos de tu aplicación
        (0,  50, 160, 20, 0.3), # en función de la configuración de tu robot
        (0,   0, 160, 20, 0.1)
       ]

# Calcula el divisor de peso (lo calculamos para que no tengas que sumar los pesos hasta llegar a 1).
weight_sum = 0
for r in ROIS: weight_sum += r[4] # r[4] es el peso del ROI

# Configuración de la cámara...
sensor.reset() # Inicializa el sensor
sensor.set_pixformat(sensor.GRAYSCALE) # usa escala de grises
sensor.set_framesize(sensor.QQVGA) # usa QQVGA para mayor velocidad
sensor.skip_frames(time = 2000) # Hace que los nuevos ajustes surtan efecto
sensor.set_auto_gain(False) # Debe estar desactivado para el seguimiento del color
sensor.set_auto_whitebal(False) # Debe estar desactivado para el seguimiento del color
clock = time.clock() # Rastrea los FPS

while(True):
    clock.tick() # Sigue los milisegundos transcurridos entre instantáneas (snapshots).
    img = sensor.snapshot() # Toma una foto y devuelve la imagen

    centroid_sum = 0

    for r in ROIS:
        blobs = img.find_blobs(GRAYSCALE_THRESHOLD, roi=r[0:4], merge=True)

        if blobs:
            # Encuentra la mancha con más píxeles
            largest_blob = max(blobs, key=lambda b: b.pixels())

            # Dibuja un rectángulo alrededor de la mancha
            img.draw_rectangle(largest_blob.rect())
            img.draw_cross(largest_blob.cx(),
                           largest_blob.cy())

            centroid_sum += largest_blob.cx() * r[4]

    center_pos = (centroid_sum / weight_sum) # Determinar el centro de la línea

    # Convierte center_pos en un ángulo de desviación. Estamos utilizando una operación no lineal
    # para que la respuesta sea más fuerte cuanto más nos alejemos de la línea. Las operaciones no
    # lineales son útiles en la salida de algoritmos como este para provocar un "desencadenante"
    # de respuesta.
    deflection_angle = 0

    # El 80 proviene de la mitad de la resolución X, el 60 proviene de la mitad de la resolución Y.
    # La ecuación siguiente solo calcula el ángulo de un triángulo en el que el lado opuesto del
    # triángulo es la desviación de la posición central con respecto al centro y el lado adyacente
    # es la mitad de la resolución Y. Esto limita el ángulo resultante a entre -45 y 45 aproximadamente
    # (no es exactamente -45 y 45).
    deflection_angle = -math.atan((center_pos-80)/60)

    # Convierte el ángulo en radianes a grados
    deflection_angle = math.degrees(deflection_angle)

    # Ahora tienes un ángulo que te indica cuánto girar el robot, el cual incorpora la parte de la
    # línea más cercana al robot y las partes de la línea más alejadas del robot para obtener una
    # mejor predicción.
    print("Ángulo de giro: %f" % deflection_angle)

    print(clock.fps())

Descargar el programa Seguir_linea_negra_escala_grises.py

Ecua

# Ejemplo de información del histograma de la imagen
#
# Este script calcula el histograma de la imagen y lo imprime.

import sensor, image, time

sensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE) # o RGB565.
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # Debe estar desactivado para el seguimiento del color
sensor.set_auto_whitebal(False) # Debe estar desactivado para el seguimiento del color
clock = time.clock()

while(True):
    clock.tick()
    img = sensor.snapshot()
    # Obtiene el histograma en escala de grises de la imagen en 8 intervalos.
    # El valor predeterminado de los intervalos es 256 y puede estar entre 2 y 256.
    print(img.get_histogram(bins=8))
    print(clock.fps())

Descargar el programa info_histograma_imagen.py

Reconocimiento de combinaciones multicolores

# Reconocimiento de combinaciones multicolores
#
# Este ejemplo muestra el seguimiento de códigos multicolores utilizando el sensor IA
#
# Un código de color es una mancha compuesta por dos o más colores. El ejemplo siguiente solo
# rastreará objetos de color que contengan dos o más de los colores que se indican a continuación.

import sensor, image, time

# Umbrales de seguimiento del color (L mín., L máx., A mín., A máx., B mín., B máx.)
# Los siguientes umbrales realizan un seguimiento general de los elementos rojos/verdes.
# Es posible que desees ajustarlos...
thresholds = [(30, 100, 15, 127, 15, 127), # generic_red_thresholds -> el índice es 0, por lo que el código es == (1 << 0)
              (30, 100, -64, -8, -32, 32), # generic_green_thresholds -> el índice es 1, por lo que el código es == (1 << 1)
              (0, 15, 0, 40, -80, -20)] # generic_blue_thresholds -> el índice es 2, por lo que el código es == (1 << 2)
# Los códigos se combinan con la operación OR cuando 'merge=True' para 'find_blobs'

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # Debe estar desactivado para el seguimiento del color
sensor.set_auto_whitebal(False) # Debe estar desactivado para el seguimiento del color
clock = time.clock()

# Solo las manchas que tienen más píxeles que 'pixel_threshold' y más área que 'area_threshold'
# son devueltas por 'find_blobs'.
# Cambia 'pixels_threshold' y 'area_threshold' si cambias la resolución de la cámara.
# Se debe establecer 'merge=True' para fusionar las manchas de color superpuestas para los
# códigos de color.

while(True):
    clock.tick()
    img = sensor.snapshot()
    for blob in img.find_blobs(thresholds, pixels_threshold=100, area_threshold=100, merge=True):
        if blob.code() == 3: # r/g code
            img.draw_rectangle(blob.rect())
            img.draw_cross(blob.cx(), blob.cy())
            img.draw_string(blob.x() + 2, blob.y() + 2, "r/g")
        if blob.code() == 5: # r/b code
            img.draw_rectangle(blob.rect())
            img.draw_cross(blob.cx(), blob.cy())
            img.draw_string(blob.x() + 2, blob.y() + 2, "r/b")
        if blob.code() == 6: # g/b code
            img.draw_rectangle(blob.rect())
            img.draw_cross(blob.cx(), blob.cy())
            img.draw_string(blob.x() + 2, blob.y() + 2, "g/b")
        if blob.code() == 7: # r/g/b code
            img.draw_rectangle(blob.rect())
            img.draw_cross(blob.cx(), blob.cy())
            img.draw_string(blob.x() + 2, blob.y() + 2, "r/g/b")
    print(clock.fps())

Descargar el programa reconocimiento_multicolor.py

Reconocimiento de un solo color

# Reconocimiento de un solo color
#
# Este ejemplo muestra el seguimiento de códigos de un solo color el sensor IA
#
# Un código de color es una mancha compuesta por dos o más colores. El ejemplo siguiente solo
# rastreará objetos de color que contengan  los dos colores siguientes.

import sensor, image, time, math

# Umbrales de seguimiento del color (L mín., L máx., A mín., A máx., B mín., B máx.)
# Los siguientes umbrales realizan un seguimiento general de los elementos rojos/verdes.
# Es posible que desees ajustarlos...
thresholds = [(30, 100, 15, 127, 15, 127), # generic_red_thresholds -> el índice es 0, por lo que el código es == (1 << 0)
              (30, 100, -64, -8, -32, 32)] # generic_green_thresholds -> el índice es 1, por lo que el código es == (1 << 1)
#  Los códigos se combinan con la operación OR cuando 'merge=True' para 'find_blobs'

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # Debe estar desactivado para el seguimiento del color
sensor.set_auto_whitebal(False) # Debe estar desactivado para el seguimiento del color
clock = time.clock()

# Solo las manchas que tienen más píxeles que 'pixel_threshold' y más área que 'area_threshold'
# son devueltas por 'find_blobs'.
# Cambia 'pixels_threshold' y 'area_threshold' si cambias la resolución de la cámara.
# Se debe establecer 'merge=True' para fusionar las manchas de color superpuestas para los
# códigos de color.

while(True):
    clock.tick()
    img = sensor.snapshot()
    for blob in img.find_blobs(thresholds, pixels_threshold=100, area_threshold=100, merge=True):
        if blob.code() == 3: # r/g codigo == (1 << 1) | (1 << 0)
            # Estos valores dependen de que la mancha no sea circular; de lo contrario, serán inestables.
            # if blob.elongation() > 0.5:
            #     img.draw_edges(blob.min_corners(), color=(255,0,0))
            #     img.draw_line(blob.major_axis_line(), color=(0,255,0))
            #     img.draw_line(blob.minor_axis_line(), color=(0,0,255))
            # Estos valores son estables en todo momento
            img.draw_rectangle(blob.rect())
            img.draw_cross(blob.cx(), blob.cy())
            # Nota: la rotación del blob es única solo para 0-180.
            img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=20)
    print(clock.fps())

Descargar el programa Reconocimiento_un_color.py