Saltar al contenido

Introducción a la visión por computadora con Python

Guía para principiantes de visión por computadora con Python y OpenCV: procesamiento de imágenes, detección de bordes y objetos, y un clasificador.

5 min de lectura
Diagrama del flujo de visión por computadora que muestra las etapas de entrada de imagen, extracción de características y clasificación de objetos.

La visión por computadora permite que las máquinas interpreten y comprendan la información visual de imágenes y video. Para los desarrolladores web que se adentran en la IA, es una de las subáreas más tangibles — los resultados se ven de inmediato. Desde el OCR en escáneres de recibos hasta la detección de rostros en aplicaciones de cámara y la inspección de calidad en la manufactura, la visión por computadora impulsa aplicaciones con las que interactúas a diario.

Esta guía recorre los fundamentos utilizando Python y OpenCV, la biblioteca de visión por computadora de código abierto más utilizada. Cada concepto incluye código que puedes ejecutar.

Configuración del entorno

OpenCV ofrece tanto algoritmos clásicos de visión por computadora como interfaces hacia modelos de aprendizaje profundo. Comienza con los bindings de Python.

shbash
# Install OpenCV with contrib modules (extra algorithms)
pip install opencv-contrib-python numpy matplotlib
 
# Verify installation
python -c "import cv2; print(cv2.__version__)"
# Expected: 4.x.x
pypython
# Basic image operations
import cv2
import numpy as np
 
# Read an image from disk
image = cv2.imread('photo.jpg')
# OpenCV loads images as BGR (not RGB) by default
 
# Image properties
print(f"Shape: {image.shape}")       # (height, width, channels)
print(f"Data type: {image.dtype}")   # uint8 (0-255)
print(f"Size: {image.size} pixels")  # total pixel count
 
# Convert color spaces
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
 
# Resize while maintaining aspect ratio
height, width = image.shape[:2]
target_width = 800
scale = target_width / width
resized = cv2.resize(image, None, fx=scale, fy=scale, interpolation=cv2.INTER_AREA)

Filtrado y mejora de imágenes

Los filtros son los componentes básicos del procesamiento de imágenes. Reducen el ruido, realzan los bordes y preparan las imágenes para la extracción de características.

pypython
# Blurring — reduces noise, smooths details
import cv2
import numpy as np
 
image = cv2.imread('noisy_photo.jpg')
 
# Gaussian blur — weighted average, good for general noise
gaussian = cv2.GaussianBlur(image, (5, 5), 0)
 
# Median blur — preserves edges, excellent for salt-and-pepper noise
median = cv2.medianBlur(image, 5)
 
# Bilateral filter — smooths while preserving edges
bilateral = cv2.bilateralFilter(image, 9, 75, 75)
pypython
# ❌ Applying edge detection on a noisy image
# Noise creates thousands of false edges
edges_noisy = cv2.Canny(noisy_image, 100, 200)
# Result: edges everywhere — useless
 
# ✅ Blur first, then detect edges
blurred = cv2.GaussianBlur(noisy_image, (5, 5), 0)
edges_clean = cv2.Canny(blurred, 100, 200)
# Result: meaningful edges only — clean contours
pypython
# Sharpening — enhances edge contrast
sharpen_kernel = np.array([
    [0, -1, 0],
    [-1,  5, -1],
    [0, -1, 0]
])
sharpened = cv2.filter2D(image, -1, sharpen_kernel)
 
# Histogram equalization — improves contrast in low-contrast images
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
equalized = cv2.equalizeHist(gray)
 
# CLAHE — adaptive histogram equalization (better for uneven lighting)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
adaptive_eq = clahe.apply(gray)

Detección de bordes y contornos

La detección de bordes encuentra los límites entre regiones de una imagen. Los contornos trazan esos límites como curvas conectadas, lo cual resulta útil para la detección de formas y la segmentación de objetos.

pypython
# Canny edge detection — the most widely used edge detector
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
 
# Two thresholds: lower and upper
# Edges with gradient > upper → strong edges (kept)
# Edges with gradient between lower and upper → kept only if connected to strong edge
# Edges with gradient < lower → discarded
edges = cv2.Canny(blurred, 50, 150)
 
# Find contours from edges
contours, hierarchy = cv2.findContours(
    edges,
    cv2.RETR_EXTERNAL,     # Only outermost contours
    cv2.CHAIN_APPROX_SIMPLE # Compress straight lines
)
 
# Draw contours on the original image
output = image.copy()
cv2.drawContours(output, contours, -1, (0, 255, 0), 2)
print(f"Found {len(contours)} contours")
pypython
# Practical example: detecting rectangles (documents, cards)
def find_rectangles(image: np.ndarray) -> list:
    """Find rectangular contours in an image."""
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    edges = cv2.Canny(blurred, 50, 150)
 
    contours, _ = cv2.findContours(
        edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
    )
 
    rectangles = []
    for contour in contours:
        # Approximate contour to a polygon
        perimeter = cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, 0.02 * perimeter, True)
 
        # If polygon has 4 vertices and is large enough, it's a rectangle
        area = cv2.contourArea(contour)
        if len(approx) == 4 and area > 1000:
            rectangles.append(approx)
 
    return rectangles
 
rects = find_rectangles(image)
print(f"Found {len(rects)} rectangular regions")

Detección de objetos con cascadas Haar

Las cascadas Haar son clasificadores preentrenados para detectar objetos específicos — rostros, ojos, automóviles. Son rápidas, pero menos precisas que los modelos de aprendizaje profundo.

pypython
# Face detection using pre-trained Haar cascade
face_cascade = cv2.CascadeClassifier(
    cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
)
 
image = cv2.imread('group_photo.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 
# Detect faces
faces = face_cascade.detectMultiScale(
    gray,
    scaleFactor=1.1,   # Image scale reduction at each level
    minNeighbors=5,     # Minimum neighbor detections to keep
    minSize=(30, 30)    # Minimum face size in pixels
)
 
# Draw bounding boxes
output = image.copy()
for (x, y, w, h) in faces:
    cv2.rectangle(output, (x, y), (x + w, y + h), (0, 255, 0), 2)
 
print(f"Detected {len(faces)} faces")
 
# Save result
cv2.imwrite('faces_detected.jpg', output)
pypython
# ❌ Running detection at original resolution for real-time video
# 4K frame → detection takes 200ms → 5 FPS maximum
faces = face_cascade.detectMultiScale(full_resolution_frame)
 
# ✅ Resize for detection, map coordinates back to original
scale = 0.25
small_frame = cv2.resize(frame, None, fx=scale, fy=scale)
small_gray = cv2.cvtColor(small_frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(small_gray)
# Map coordinates back: multiply by 1/scale
faces_original = [(int(x/scale), int(y/scale), int(w/scale), int(h/scale))
                  for (x, y, w, h) in faces]
# Detection runs at 60+ FPS on downscaled frames

Construcción de un clasificador de imágenes simple

Para un reconocimiento de objetos más preciso, utiliza un modelo de aprendizaje profundo preentrenado. El módulo DNN de OpenCV puede cargar modelos de TensorFlow, PyTorch y ONNX.

pypython
# Image classification using a pre-trained MobileNet model
import cv2
import numpy as np
 
# Load pre-trained MobileNet SSD
model = cv2.dnn.readNetFromTensorflow(
    'frozen_inference_graph.pb',
    'ssd_mobilenet_v2.pbtxt'
)
 
CLASSES = [
    'background', 'person', 'bicycle', 'car', 'motorcycle',
    'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
    'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird',
    'cat', 'dog', 'horse', 'sheep', 'cow',
]
 
def detect_objects(image: np.ndarray, confidence_threshold: float = 0.5):
    """Detect objects in an image using MobileNet SSD."""
    height, width = image.shape[:2]
 
    # Prepare input blob
    blob = cv2.dnn.blobFromImage(
        image, 1.0/127.5, (300, 300), (127.5, 127.5, 127.5),
        swapRB=True, crop=False
    )
 
    model.setInput(blob)
    detections = model.forward()
 
    results = []
    for i in range(detections.shape[2]):
        confidence = detections[0, 0, i, 2]
        if confidence > confidence_threshold:
            class_id = int(detections[0, 0, i, 1])
            box = detections[0, 0, i, 3:7] * np.array(
                [width, height, width, height]
            )
            x1, y1, x2, y2 = box.astype(int)
            results.append({
                'class': CLASSES[class_id],
                'confidence': float(confidence),
                'box': (x1, y1, x2, y2),
            })
 
    return results
 
image = cv2.imread('street_scene.jpg')
objects = detect_objects(image)
for obj in objects:
    print(f"{obj['class']}: {obj['confidence']:.2f}")

Puntos clave

  1. OpenCV ofrece visión por computadora clásica y basada en aprendizaje profundo — desde el filtrado básico hasta la inferencia con DNN, todo en una sola biblioteca
  2. Preprocesa siempre antes de analizar — aplica desenfoque para eliminar el ruido, convierte los espacios de color y redimensiona para mejorar el rendimiento
  3. La detección de bordes combinada con la búsqueda de contornos resuelve muchos problemas prácticos — escaneo de documentos, detección de formas y segmentación de regiones
  4. Las cascadas Haar son rápidas pero limitadas — úsalas para la detección de rostros en tiempo real y cambia a modelos de aprendizaje profundo para mayor precisión
  5. Redimensiona para la detección y luego reasigna las coordenadas — ejecutar la detección sobre fotogramas reducidos convierte 5 FPS en más de 60 FPS
  6. Los modelos preentrenados (MobileNet, YOLO) gestionan la detección general de objetos — ajústalos a tu caso de uso específico para lograr precisión en producción
Wilfredo Rujel

Wilfredo Rujel

Ingeniero de Software Full Stack

Compartir esta publicaciónX