Vision Troubleshooting
Common vision problems and solutions
Camera Issues
Camera Not Detected
Symptoms:
- "Camera not found" error
- OpMode fails to initialize
- Blank camera preview
Causes &Solutions:
-
Wrong hardware name
// Check your configuration file WebcamName webcam = hardwareMap.get(WebcamName.class, "Webcam 1"); // Name must match exactly (case-sensitive!) -
USB connection loose
- Reconnect USB cable
- Try different USB port
- Check for damaged cables
-
Camera not in configuration
- Open Robot Controller app
- Configure → Select active configuration
- Add webcam device
- Save configuration
-
Insufficient power
- Camera draws significant power
- Use powered USB hub if multiple devices
- Check battery voltage
Black Screen / No Preview
Symptoms:
- Camera initializes but shows black
- No image on Driver Station
Solutions:
-
Enable live view
visionPortal = new VisionPortal.Builder() .setCamera(webcamName) .enableLiveView(true) // Ensure this is true .addProcessor(processor) .build(); -
Check camera monitor ID
// For EasyOpenCV int cameraMonitorViewId = hardwareMap.appContext .getResources() .getIdentifier("cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName()); -
Verify camera permissions
- Android needs camera permission
- Check Robot Controller app settings
-
Test with different camera
- Hardware failure possible
- Try known-working camera
Poor Image Quality
Symptoms:
- Blurry images
- Dark or overexposed
- Color artifacts
Solutions:
-
Adjust camera settings
// After camera opens webcam.startStreaming(640, 360, OpenCvCameraRotation.UPRIGHT); // Adjust exposure (if supported) ExposureControl exposureControl = webcam.getExposureControl(); if (exposureControl.getMode() != ExposureControl.Mode.Manual) { exposureControl.setMode(ExposureControl.Mode.Manual); exposureControl.setExposure(50, TimeUnit.MILLISECONDS); } -
Clean camera lens
- Dirt and smudges reduce quality
- Use microfiber cloth
-
Improve lighting
- Add LED lights to robot
- Position for consistent illumination
- Avoid shadows on target
-
Reduce motion blur
- Decrease exposure time
- Stabilize camera mount
- Process at lower speeds
Detection Issues
No Objects Detected
Symptoms:
- Blobs list is empty
- AprilTags not found
- Pipeline returns nothing
Debugging Steps:
-
Verify color thresholds
// Test in EOCV-Sim first // Add telemetry to see mask Imgproc.cvtColor(input, hsv, Imgproc.COLOR_RGB2HSV); Core.inRange(hsv, lower, upper, mask); // Show percentage of image matching double matchPercent = Core.mean(mask).val[0] / 255.0 * 100; telemetry.addData("Match %", matchPercent); -
Check region of interest
// Make sure ROI covers target area .setRoi(ImageRegion.entireFrame()) // Test with full frame first -
Verify object is in frame
- Stream to Driver Station
- Confirm object visible
- Check camera angle
-
Adjust area filters
// Remove filters temporarily to see all detections // ColorBlobLocatorProcessor.Util.filterByArea(50, 50000, blobs); // Then tighten filters once detection works -
Lighting variations
- Test under competition lighting
- Adjust thresholds for different conditions
- Use adaptive techniques
False Positives
Symptoms:
- Detecting wrong objects
- Multiple unwanted detections
- Background noise
Solutions:
-
Tighten color thresholds
// Narrow the range Scalar lower = new Scalar(100, 150, 100); // More restrictive Scalar upper = new Scalar(120, 255, 255); -
Add area filtering
// Filter by expected object size ColorBlobLocatorProcessor.Util.filterByArea(1000, 5000, blobs); -
Use density filtering
// Filter out hollow/sparse detections ColorBlobLocatorProcessor.Util.filterByDensity(0.7, blobs); -
Restrict ROI
// Only look where object should be .setRoi(ImageRegion.asUnityCenterCoordinates(-0.5, 0, 0.5, 1)) -
Add shape validation
// Check aspect ratio for (ColorBlobLocatorProcessor.Blob blob : blobs) { double aspectRatio = blob.getAspectRatio(); if (aspectRatio > 0.8 && aspectRatio < 1.2) { // Roughly square, might be our target } }
Inconsistent Detection
Symptoms:
- Detection works sometimes
- Flickers on/off
- Position jumps around
Solutions:
-
Add hysteresis
private int detectionConfidence = 0; private final int CONFIDENCE_THRESHOLD = 3; if (objectDetected) { detectionConfidence++; } else { detectionConfidence = 0; } boolean confirmed = detectionConfidence >= CONFIDENCE_THRESHOLD; -
Average multiple frames
private Queue<Double> recentXPositions = new LinkedList<>(); private final int FRAME_HISTORY = 5; recentXPositions.add(currentX); if (recentXPositions.size() > FRAME_HISTORY) { recentXPositions.poll(); } double averageX = recentXPositions.stream() .mapToDouble(Double::doubleValue) .average() .orElse(0); -
Stabilize lighting
- Add consistent light source
- Disable auto-exposure
- Shield from ambient changes
-
Improve thresholds
- Test under various conditions
- Build tolerance into ranges
- Use multiple color spaces
Performance Issues
Low Frame Rate
Symptoms:
- Choppy video preview
- Delayed responses
- Frame drops
Solutions:
-
Reduce resolution
.setCameraResolution(new Size(320, 240)) // Lower res -
Increase decimation (AprilTags)
AprilTagProcessor.Builder() .setDecimation(3) // Process every 3rd pixel -
Disable live view
.enableLiveView(false) // No preview = less work -
Optimize pipeline
// Reuse Mat objects (don't create new ones each frame) private Mat hsv = new Mat(); private Mat mask = new Mat(); @Override public Mat processFrame(Mat input) { // Reuse hsv and mask instead of creating new return input; } -
Process fewer frames
private int frameCount = 0; @Override public Mat processFrame(Mat input) { if (frameCount++ % 3 == 0) { // Only process every 3rd frame doExpensiveProcessing(input); } return input; } -
Disable unused processors
visionPortal.setProcessorEnabled(processor, false);
High CPU Usage
Symptoms:
- Robot control loop slows down
- Mecanum drive feels sluggish
- Telemetry updates slowly
Solutions:
-
Close vision when not needed
// After autonomous detection visionPortal.setProcessorEnabled(colorProcessor, false); -
Use lower resolution
.setCameraResolution(new Size(320, 240)) -
Simplify processing
- Remove unnecessary operations
- Use simpler color spaces
- Reduce morphological operations
-
Profile your code
long startTime = System.nanoTime(); // Do expensive operation long elapsedMs = (System.nanoTime() - startTime) / 1000000; telemetry.addData("Processing Time (ms)", elapsedMs);
Memory Issues
Symptoms:
- OutOfMemoryError
- Garbage collection pauses
- Crashes after running
Solutions:
-
Release submats
Mat crop = input.submat(roi); // ... use crop ... crop.release(); // IMPORTANT! -
Reuse Mat objects
// Don't do this: Mat hsv = new Mat(); // Creates new Mat every frame! // Do this instead: private Mat hsv = new Mat(); // Reuse same Mat -
Clear contours
List<MatOfPoint> contours = new ArrayList<>(); // ... find contours ... // Release when done for (MatOfPoint contour : contours) { contour.release(); } contours.clear();
AprilTag Specific Issues
Tags Not Detected
Solutions:
-
Check distance and angle
- Move within 1-4 feet
- Face tag head-on (< 30° angle)
-
Verify tag library
.setTagLibrary(AprilTagGameDatabase.getCurrentGameTagLibrary()) -
Improve lighting
- AprilTags need good contrast
- Avoid shadows and glare
-
Check tag size configuration
- Ensure tag size matches physical tags
- Verify units (inches vs mm)
Inaccurate Pose Data
Solutions:
-
Camera calibration
- Use proper lens intrinsics
- Calibrate with checkerboard pattern
-
View tags at better angles
- Best accuracy head-on
- Avoid extreme angles
-
Use multiple tags
- Triangulate from multiple detections
- Average pose estimates
EasyOpenCV vs VisionPortal Issues
Pipeline Works in EOCV-Sim but Not on Robot
Common causes:
-
Different resolutions
// Make sure resolution matches simulator .setCameraResolution(new Size(640, 480)) -
Color space differences
- Robot camera may have different color response
- Retune thresholds with actual camera
-
Lighting conditions
- Simulator uses test images
- Robot has dynamic lighting
- Add tolerance to thresholds
Migration Issues
Moving from EasyOpenCV to VisionPortal:
-
Different coordinate systems
// EasyOpenCV: Origin at top-left // VisionPortal: Same, but check your processor -
API differences
// EasyOpenCV public Mat processFrame(Mat input) { ... } // VisionPortal public void processFrame(Mat input, long captureTimeNanos) { ... } // Note: void return, different signature
Debugging Techniques
Add Visual Feedback
// Draw what you're detecting
Imgproc.rectangle(input, roi, new Scalar(0, 255, 0), 2);
Imgproc.putText(input, "Target: " + target, new Point(10, 30),
Imgproc.FONT_HERSHEY_SIMPLEX, 1, new Scalar(255, 0, 0), 2);Telemetry Everything
telemetry.addData("Blobs Found", blobs.size());
telemetry.addData("Largest Blob Area", largestBlob.getContourArea());
telemetry.addData("Center X", centerX);
telemetry.addData("Processing Time (ms)", processingTimeMs);
telemetry.update();Log to File
// For detailed debugging
try {
FileWriter writer = new FileWriter("/sdcard/FIRST/vision_log.txt", true);
writer.write(String.format("%d,%.2f,%.2f\n",
System.currentTimeMillis(), x, y));
writer.close();
} catch (IOException e) {
// Handle error
}Test Incrementally
- Test camera initialization alone
- Add simple pass-through pipeline
- Add color conversion
- Add thresholding
- Add contour detection
- Add filtering and logic
Identify exactly where issues occur!
Getting Help
If you're still stuck:
- Check FTC Discord - Active community, fast responses
- Post on FTC Forums - Official support
- Review SDK Examples - Look at
FtcRobotController/samples - Enable verbose logging - Catch hidden errors
- Ask your mentor - They may have seen it before
Quick Reference Checklist
When vision isn't working, check:
- Camera plugged in and powered
- Hardware name matches configuration
- Camera opens successfully (no errors)
- Objects visible in camera preview
- Color in right range (test in EOCV-Sim)
- ROI includes target area
- Filters not too restrictive
- Good lighting conditions
- Resolution appropriate
- Pipeline returning valid data
- No errors in DS logs
Next Steps
- Review Vision Basics for fundamentals
- See Vision Integration for architecture
- Try EOCV-Sim for offline debugging