# Computer Vision Developer

> Hands-on computer vision development covering image classification with transfer learning, object detection with YOLO and Faster R-CNN, semantic and instance segmentation, OpenCV image processing, data augmentation strategies, model optimization for edge deployment, video processing, and metrics for measuring model performance. Use when the user asks about computer vision developer, computer vision developer best practices, or needs guidance on computer vision developer implementation. Do NOT use when the user needs a different specialized skill or is asking about an unrelated technology domain.

- Skill: `ferroxlabs/computer-vision-developer` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add ferroxlabs/computer-vision-developer`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ferroxlabs/computer-vision-developer/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: Apache-2.0
- Author: FerroxLabs (https://skillmd.com/u/ferroxlabs)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/ferroxlabs/computer-vision-developer

---


# Computer Vision Developer

## Overview

Computer vision development involves building systems that extract meaningful information from images and video. This skill covers practical implementation of core CV tasks: classification, detection, segmentation, and image processing. The focus is on production-ready code using modern frameworks (PyTorch, YOLO, OpenCV), with emphasis on data preparation, training strategies, measuring results, and deployment optimization.

## Image Classification

### Transfer Learning Pipeline

```python
import torch
import torch.nn as nn
from torchvision import models, transforms
from torch.utils.data import DataLoader, Dataset

# Data augmentation and normalization
train_transform = transforms.Compose([
    transforms.RandomResizedCrop(224, scale=(0.8, 1.0)),
    transforms.RandomHorizontalFlip(),
    transforms.RandomRotation(15),
    transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),
    transforms.RandomAffine(degrees=0, translate=(0.1, 0.1)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    transforms.RandomErasing(p=0.1),
])

val_transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

# Transfer learning with frozen backbone
class CustomClassifier(nn.Module):
    def __init__(self, num_classes, freeze_backbone=True):
        super().__init__()
        self.backbone = models.efficientnet_v2_s(weights='IMAGENET1K_V1')

        if freeze_backbone:
            for param in self.backbone.parameters():
                param.requires_grad = False

        # Replace classifier head
        in_features = self.backbone.classifier[1].in_features
        self.backbone.classifier = nn.Sequential(
            nn.Dropout(p=0.3),
            nn.Linear(in_features, 512),
            nn.ReLU(),
            nn.Dropout(p=0.2),
            nn.Linear(512, num_classes),
        )

    def forward(self, x):
        return self.backbone(x)

    def unfreeze_backbone(self, num_layers=3):
        """Gradually unfreeze backbone layers for fine-tuning."""
        layers = list(self.backbone.features.children())
        for layer in layers[-num_layers:]:
            for param in layer.parameters():
                param.requires_grad = True
```

### Training Loop with Best Practices

```python
def train_classifier(model, train_loader, val_loader, num_epochs=30):
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model = model.to(device)

    # Phase 1: Train head only (backbone frozen)
    optimizer = torch.optim.AdamW(
        filter(lambda p: p.requires_grad, model.parameters()),
        lr=1e-3, weight_decay=1e-4
    )
    scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=10)
    criterion = nn.CrossEntropyLoss(label_smoothing=0.1)

    best_val_acc = 0
    patience = 5
    patience_counter = 0

    for epoch in range(num_epochs):
        # Unfreeze backbone after warm-up
        if epoch == 10:
            model.unfreeze_backbone(num_layers=3)
            optimizer = torch.optim.AdamW([
                {'params': model.backbone.features.parameters(), 'lr': 1e-5},
                {'params': model.backbone.classifier.parameters(), 'lr': 1e-4},
            ], weight_decay=1e-4)
            scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=20)

        # Training phase
        model.train()
        running_loss = 0
        correct = 0
        total = 0

        for images, labels in train_loader:
            images, labels = images.to(device), labels.to(device)
            optimizer.zero_grad()

            outputs = model(images)
            loss = criterion(outputs, labels)
            loss.backward()

            torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
            optimizer.step()

            running_loss += loss.item()
            _, predicted = outputs.max(1)
            total += labels.size(0)
            correct += predicted.eq(labels).sum().item()

        scheduler.step()

        # Validation phase
        val_acc = measure_accuracy(model, val_loader, device)
        print(f"Epoch {epoch}: Loss={running_loss/len(train_loader):.4f}, "
              f"Train Acc={100.*correct/total:.1f}%, Val Acc={val_acc:.1f}%")

        # Early stopping
        if val_acc > best_val_acc:
            best_val_acc = val_acc
            torch.save(model.state_dict(), 'best_model.pth')
            patience_counter = 0
        else:
            patience_counter += 1
            if patience_counter >= patience:
                print(f"Early stopping at epoch {epoch}")
                break
```

## Object Detection with YOLO

### YOLOv8 Training and Inference

```python
from ultralytics import YOLO

# Train custom YOLO model
model = YOLO('yolov8m.pt')  # Start from pretrained

results = model.train(
    data='dataset.yaml',       # Dataset configuration
    epochs=100,
    imgsz=640,
    batch=16,
    patience=20,               # Early stopping patience
    optimizer='AdamW',
    lr0=0.001,
    lrf=0.01,                  # Final LR = lr0 * lrf
    warmup_epochs=3,
    augment=True,
    mosaic=1.0,                # Mosaic augmentation
    mixup=0.1,                 # Mixup augmentation
    close_mosaic=10,           # Disable mosaic last 10 epochs
    device='0',                # GPU device
    project='runs/detect',
    name='custom-detector',
)

# Inference
model = YOLO('runs/detect/custom-detector/weights/best.pt')
results = model.predict(
    source='test_images/',
    conf=0.25,                 # Confidence threshold
    iou=0.45,                  # NMS IoU threshold
    max_det=100,               # Max detections per image
    save=True,
    save_txt=True,             # Save labels
)

# Process results
for result in results:
    boxes = result.boxes
    for box in boxes:
        x1, y1, x2, y2 = box.xyxy[0].tolist()
        confidence = box.conf[0].item()
        class_id = int(box.cls[0].item())
        class_name = model.names[class_id]
        print(f"{class_name}: {confidence:.2f} at [{x1:.0f},{y1:.0f},{x2:.0f},{y2:.0f}]")
```

### Dataset Configuration

```yaml
# dataset.yaml
path: /data/my_dataset
train: images/train
val: images/val
test: images/test

nc: 5  # number of classes
names:
  0: car
  1: truck
  2: pedestrian
  3: bicycle
  4: traffic_sign

# Label format (YOLO): class_id center_x center_y width height (normalized 0-1)
# Example labels/train/image001.txt:
# 0 0.5 0.4 0.3 0.2
# 2 0.7 0.8 0.05 0.15
```

## Image Segmentation

### Semantic Segmentation with SegFormer

```python
from transformers import SegformerForSemanticSegmentation, SegformerImageProcessor
import torch
import numpy as np

class SemanticSegmentor:
    def __init__(self, model_name="nvidia/segformer-b2-finetuned-cityscapes-1024-1024"):
        self.processor = SegformerImageProcessor.from_pretrained(model_name)
        self.model = SegformerForSemanticSegmentation.from_pretrained(model_name)

    def segment(self, image):
        """Segment image and return per-pixel class labels."""
        inputs = self.processor(images=image, return_tensors="pt")

        with torch.no_grad():
            outputs = self.model(**inputs)

        logits = outputs.logits  # (batch, num_classes, H/4, W/4)

        # Upsample to original size
        upsampled = torch.nn.functional.interpolate(
            logits,
            size=image.size[::-1],  # (H, W)
            mode='bilinear',
            align_corners=False,
        )

        seg_map = upsampled.argmax(dim=1).squeeze().numpy()
        return seg_map

    def overlay_segmentation(self, image, seg_map, alpha=0.5):
        """Create colored overlay of segmentation on original image."""
        color_map = self._get_color_map()
        colored_seg = color_map[seg_map]
        overlay = (np.array(image) * (1 - alpha) + colored_seg * alpha).astype(np.uint8)
        return overlay
```

## OpenCV Image Processing

### Common Operations

```python
import cv2
import numpy as np

class ImageProcessor:
    """Production image processing pipeline with OpenCV."""

    def preprocess_for_model(self, image_path, target_size=(640, 640)):
        """Standard preprocessing pipeline."""
        img = cv2.imread(image_path)
        if img is None:
            raise ValueError(f"Cannot read image: {image_path}")

        # Color space conversion (OpenCV loads as BGR)
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

        # Resize maintaining aspect ratio with padding
        img_resized = self.letterbox_resize(img_rgb, target_size)

        # Normalize to [0, 1]
        img_normalized = img_resized.astype(np.float32) / 255.0

        return img_normalized

    def letterbox_resize(self, image, target_size, fill_color=(114, 114, 114)):
        """Resize with padding to maintain aspect ratio."""
        h, w = image.shape[:2]
        target_h, target_w = target_size

        scale = min(target_w / w, target_h / h)
        new_w, new_h = int(w * scale), int(h * scale)

        resized = cv2.resize(image, (new_w, new_h), interpolation=cv2.INTER_LINEAR)

        canvas = np.full((target_h, target_w, 3), fill_color, dtype=np.uint8)
        top = (target_h - new_h) // 2
        left = (target_w - new_w) // 2
        canvas[top:top + new_h, left:left + new_w] = resized

        return canvas

    def detect_edges(self, image, low_threshold=50, high_threshold=150):
        """Canny edge detection with preprocessing."""
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        blurred = cv2.GaussianBlur(gray, (5, 5), 1.4)
        edges = cv2.Canny(blurred, low_threshold, high_threshold)
        return edges

    def find_contours(self, image, min_area=100):
        """Find and filter contours by area."""
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        _, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
        contours, hierarchy = cv2.findContours(
            thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
        )
        return [c for c in contours if cv2.contourArea(c) >= min_area]

    def apply_perspective_transform(self, image, src_points, dst_size):
        """Apply perspective transformation (e.g., document straightening)."""
        dst_points = np.float32([
            [0, 0], [dst_size[0], 0],
            [dst_size[0], dst_size[1]], [0, dst_size[1]]
        ])
        matrix = cv2.getPerspectiveTransform(
            np.float32(src_points), dst_points
        )
        return cv2.warpPerspective(image, matrix, dst_size)
```

## Data Augmentation Strategies

### Augmentation by Task Type

```
Task                Recommended Augmentations         Avoid
---------------------------------------------------------------------------
Classification      RandomCrop, Flip, ColorJitter,    Aggressive geometric
                    Rotation, RandomErasing,          transforms that change
                    Mixup, CutMix                     class semantics

Object Detection    Mosaic, RandomScale, Flip,        Transforms that move
                    HSV augmentation, Copy-Paste      objects off-frame without
                                                      updating labels

Segmentation        Elastic transform, RandomCrop,    Transforms that create
                    Flip, Scale, ColorJitter          ambiguous boundaries

Medical Imaging     Rotation, Elastic deformation,    Aggressive color jitter
                    Flip (if anatomically valid),     (colors carry meaning),
                    Intensity normalization           Flips that change anatomy

OCR/Document        Perspective transform, slight     Heavy rotation,
                    rotation, noise, blur             color changes
```

## Model Optimization for Deployment

### ONNX Export and Quantization

```python
import torch
import onnx
from onnxruntime.quantization import quantize_dynamic, QuantType

# Export to ONNX
dummy_input = torch.randn(1, 3, 640, 640)

torch.onnx.export(
    model,
    dummy_input,
    "model.onnx",
    opset_version=17,
    input_names=['input'],
    output_names=['output'],
    dynamic_axes={'input': {0: 'batch_size'}, 'output': {0: 'batch_size'}},
)

# Verify ONNX model
onnx_model = onnx.load("model.onnx")
onnx.checker.check_model(onnx_model)

# Dynamic quantization (INT8)
quantize_dynamic(
    "model.onnx",
    "model_quantized.onnx",
    weight_type=QuantType.QInt8,
)

# Size comparison
import os
original_size = os.path.getsize("model.onnx") / 1e6
quantized_size = os.path.getsize("model_quantized.onnx") / 1e6
print(f"Original: {original_size:.1f}MB, Quantized: {quantized_size:.1f}MB")
print(f"Compression ratio: {original_size / quantized_size:.1f}x")
```

## Performance Metrics

### Metrics by Task

```
Classification:
  - Accuracy, Precision, Recall, F1-Score
  - Confusion Matrix
  - Top-k Accuracy (for many classes)
  - AUC-ROC (binary)

Object Detection:
  - mAP@0.5 (IoU threshold 0.5)
  - mAP@0.5:0.95 (COCO metric, averaged over IoU 0.5 to 0.95)
  - Precision-Recall curve per class
  - Inference FPS

Segmentation:
  - mIoU (mean Intersection over Union)
  - Pixel Accuracy
  - Dice Coefficient (F1 for segmentation)
  - Boundary F1 Score
```

## Video Processing

```python
class VideoProcessor:
    """Process video frames with detection model."""

    def process_video(self, video_path, model, output_path, skip_frames=1):
        cap = cv2.VideoCapture(video_path)
        fps = cap.get(cv2.CAP_PROP_FPS)
        width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

        writer = cv2.VideoWriter(
            output_path, cv2.VideoWriter_fourcc(*'mp4v'),
            fps / skip_frames, (width, height)
        )

        frame_count = 0
        while cap.isOpened():
            ret, frame = cap.read()
            if not ret:
                break

            if frame_count % skip_frames == 0:
                results = model.predict(frame, conf=0.25, verbose=False)
                annotated = results[0].plot()
                writer.write(annotated)

            frame_count += 1

        cap.release()
        writer.release()
```

## CV Development Checklist

```
Data:
  [ ] Collected diverse, representative training data
  [ ] Labels verified by domain expert (spot-check 5%)
  [ ] Train/val/test split with no data leakage
  [ ] Augmentation strategy appropriate for task
  [ ] Class distribution analyzed and addressed

Training:
  [ ] Transfer learning from relevant pretrained model
  [ ] Learning rate finder or known-good schedule
  [ ] Early stopping to prevent overfitting
  [ ] Multi-scale training for detection/segmentation
  [ ] Training monitored with loss curves and metrics

Assessment:
  [ ] Tested on held-out test set (never seen during training)
  [ ] Per-class metrics analyzed (not just average)
  [ ] Failure cases visually inspected
  [ ] Performance tested on edge cases
  [ ] Speed benchmarked (FPS on target hardware)

Deployment:
  [ ] Model exported to ONNX or TensorRT
  [ ] Quantization applied if latency-critical
  [ ] Input preprocessing matches training pipeline exactly
  [ ] Confidence thresholds tuned for production use case
  [ ] Monitoring for prediction distribution shifts
```

## When to Use

**Use this skill when:**
- Designing or implementing computer vision developer solutions
- Reviewing or improving existing computer vision developer approaches
- Making architectural or implementation decisions about computer vision developer
- Learning computer vision developer patterns and best practices
- Troubleshooting computer vision developer-related issues

**Do NOT use this skill when:**
- The question is about a fundamentally different technology domain
- A more specific sibling skill covers the exact topic needed
- The user needs a complete hands-on tutorial rather than expert guidance

## Output Format

```markdown
# Computer Vision Developer Analysis

## Context Assessment
[Situation summary and constraints]

## Recommended Approach
[Primary recommendation with rationale]

## Implementation Steps
1. [Step with specific details]
2. [Step with specific details]
3. [Step with specific details]

## Trade-offs and Considerations
- [Key trade-off 1]
- [Key trade-off 2]

## Next Steps
- [Immediate action item]
- [Follow-up action item]
```

## Example

**Input:** "Help me implement computer vision developer for a medium-scale production application"

**Output:** A structured analysis covering current state assessment, recommended computer vision developer approach with specific patterns, implementation roadmap with milestones, and risk mitigation strategies tailored to the application scale and constraints.

## Edge Cases

- **Legacy system integration:** When computer vision developer must coexist with legacy approaches, provide a gradual migration path rather than a complete rewrite
- **Scale mismatch:** When the solution complexity exceeds the project scale, recommend a simpler approach and note when to revisit
- **Team skill gaps:** When the team lacks experience with the recommended approach, include learning resources and simpler alternatives
- **Conflicting requirements:** When constraints conflict (e.g., performance vs. maintainability), explicitly state the trade-off and recommend based on stated priorities

