🚗 Reconocimiento de Placas Vehiculares con Python: YOLO, OpenCV y PaddleOCR
🚗 ¡Hola, hola, Omesitos! En este post aprenderemos a reconocer el contenido de placas vehiculares. Para ello entrenaremos un modelo que detecte matriculas vehiculares usando YOLO. Una vez detectada la placa extraeremos el texto con PaddleOCR. ¡Así que vamos a empezar!
¿Cómo reconocer placas vehiculares con visión artificial en Python?

Antes de pasar al código debemos tener en claro el proceso que vamos a llevar a cabo. Entonces, supongamos que tenemos la imagen de un auto en donde se vea la placa vehicular. ¿Qué tendríamos que hacer para extraer su texto?
- Identificar el ROI o región de interés dentro de la imagen, es decir la placa vehicular. ¿Cómo lo haremos? Mediante un modelo de detección de objetos, que entrenaremos.
- Una vez que tengamos la región de interés será necesario agrandar un poco ese área para prevenir cualquier error, por si el detector de placas vehiculares corta alguna sección de la placa.
- Como ya tenemos la región de interés, podemos aplicar reconocimiento óptico de caracteres u OCR, para ello usaremos Paddle OCR, ¿por qué? Es bastante bueno en sus resultados y nos ayuda si es que el texto tiene cierta inclinación. Aunque puede tener un tiempo de ejecución un poquito más grande que Tesseract OCR, por ejemplo.
- Una vez que extraigamos el texto será necesario tratarlo un poco. Por la diferencia de placas entre distintos países, en donde se podría usar guiones, espacios o puntos entre los caracteres, nosotros extraeremos únicamente los números y letras.
Ahora que tenemos el proceso claro, vamos a empezar con entrenar el modelo para detectar placas vehiculares.
📌 Nota importante: Esta sección contiene únicamente la programación empleada. Si deseas una explicación paso a paso con mayor detalle, no olvides revisar el video completo disponible en el canal.
Detección de placas de autos con YOLO
Como lo había comentado previamente, necesitamos identificar el área de interés en donde esté presente la placa vehicular, entonces entrenaremos un modelo de detección de placas vehiculares (a partir de otro preentrenado para detección de distintos objetos) con ayuda de Ultralytics YOLO. Además trabajaremos con herramientas como Google Colab, para acelerar el entrenamiento.
A continuación, te comparto la programación utilizada durante el video.
1. Instalación de librerías necesarias 🛠️
!pip install roboflow ultralytics
2. Descarga de Dataset desde Roboflow 🗂️
El Dataset seleccionado en esta ocasión es: license-plate Computer Vision Model. Este se encuentra en Roboflow y sus imágenes son similares a las de un control de entrada y salida de autos, por lo que puede ser útil si necesitas realizar un proyecto similar.
from roboflow import Roboflow rf = Roboflow(api_key="YOUR-API-KEY") project = rf.workspace("licenseplate-s6fjf").project("license-plate-xmnzu") version = project.version(1) dataset = version.download("yolov11")
3. Carga del modelo base YOLOv11 🤖
from ultralytics import YOLO model = YOLO("yolo11m.pt")
4. Entrenamiento del modelo personalizado 🤖🏋️
data_path = "/content/license-plate-1/data.yaml" results = model.train(data=data_path, epochs=15, imgsz=640)
5. ¡A hacer predicciones! 🤖
# Cargamos el modelo ya entrenado custom_model = YOLO("/content/runs/detect/train/weights/best.pt") # Realizamos predicciones sobre algunas imágenes res = custom_model("/content/license-plate-1/test/images")
# Visualizamos los resultados de las detecciones for r in res: r.show()
Aplicar el modelo y extraer el texto de las placas vehiculares
Una vez que tenemos el modelo de detección de placas vehiculares, pasaremos a aplicarlo sobre la imagen de entrada, luego identificamos la sección de interés agrandándola un poco para aplicar PaddleOCR y extraer el texto. Finalmente, para estandarizar el resultado del reconocimiento, solo se visualizará letras desde la A a la Z y números del 0 al 9.
# Importar librerías necesarias from ultralytics import YOLO from paddleocr import PaddleOCR import cv2 import imutils import re # Cargar imagen de entrada image = cv2.imread("./Inputs/image_001.jpg") # Inicializar modelos model = YOLO("best.pt") # Modelo YOLO entrenado para detectar placas vehiculares ocr = PaddleOCR(use_angle_cls=True, lang='en') # OCR con corrección de inclinación # Ejecutar YOLO sobre la imagen results = model(image) #print(results[0].boxes) for result in results: # Filtrar solo las detecciones de clase "placa" (cls == 0) index_plates = (result.boxes.cls == 0).nonzero(as_tuple=True)[0] #print(index_plates) for idx in index_plates: # Obtener confianza de la caja conf = result.boxes.conf[idx].item() if conf > 0.7: # Obtener las coordenadas de la caja xyxy = result.boxes.xyxy[idx].squeeze().tolist() x1, y1 = int(xyxy[0]), int(xyxy[1]) x2, y2 = int(xyxy[2]), int(xyxy[3]) # Recortar imagen de la placa con padding plate_image = image[y1-15:y2+15, x1-15:x2+15] # Ejecutar OCR con PaddleOCR result_ocr = ocr.predict(cv2.cvtColor(plate_image, cv2.COLOR_BGR2RGB)) #print(result_ocr) # Ordenar los textos detectados de izquierda a derecha boxes = result_ocr[0]['rec_boxes'] texts = result_ocr[0]['rec_texts'] left_to_right = sorted(zip(boxes, texts), key=lambda x: min(x[0][::2])) print(f"left_to_right:", left_to_right) # Filtrar por whitelist (solo letras mayúsculas y números) whitelist_pattern = re.compile(r'^[A-Z0-9]+$') left_to_right = ''.join([t for _, t in left_to_right]) output_text = ''.join([t for t in left_to_right if whitelist_pattern.fullmatch(t)]) print(f"output_text: {output_text}") # Visualización cv2.imshow("plate_image", plate_image) # Dibujar resultados sobre la imagen cv2.rectangle(image, (x1 - 10, y1 - 35), (x2 + 10, y2-(y2 -y1)), (0, 255, 0), -1) cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(image, output_text, (x1-7, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 0), 2) # Mostrar imagen final cv2.imshow("Image", imutils.resize(image, width=720)) cv2.waitKey(0) cv2.destroyAllWindows()
Y podremos obtener un resultados como los siguientes:


Y eso ha sido todo por este post, Omesito/a. 😊
¡Cuídate mucho y nos vemos en el siguiente tutorial!