A powerful yet user-friendly OpenCV wrapper that makes computer vision accessible for everyone. Easy OpenCV provides a streamlined interface to perform complex computer vision operations with simple, intuitive function calls.
"Computer vision simplified with human-readable function calls and sensible defaults"
pip install easy-opencv-wrapperfrom easy_opencv import cv  # Note: underscores, not hyphens!Requirements: Python 3.7+ β’ OpenCV 4.5+ β’ NumPy 1.19+ β’ Pillow 8.0+
π Critical: The PyPI package name is
easy-opencv-wrapper(with hyphens), but you import it aseasy_opencv(with underscores). This is standard Python convention. See INSTALLATION_GUIDE.md for troubleshooting.
# β WRONG - These will cause ModuleNotFoundError
import easy_opencv_wrapper
import easy-opencv
# β
 CORRECT - This is how you import Easy OpenCV
from easy_opencv import cvRun our verification script to test your installation:
python verify_import.pyThis script will test both correct and incorrect imports and verify basic functionality.
from easy_opencv import cv
# Load and enhance image (handles errors automatically)
image = cv.load_image('photo.jpg')
enhanced = cv.apply_noise_reduction(image)
enhanced = cv.adjust_brightness_contrast(enhanced, brightness=10, contrast=1.2)
# Detect faces and draw boxes
faces = cv.detect_faces(enhanced)
for (x, y, w, h) in faces:
    enhanced = cv.draw_rectangle(enhanced, (x, y), (x+w, y+h), color=(0, 255, 0))
# Save result
cv.save_image(enhanced, 'enhanced_photo.jpg')Easy OpenCV dramatically reduces the complexity of computer vision code while maintaining all the power of OpenCV underneath. It helps you:
- Write 50-70% less code for common tasks
- Eliminate boilerplate code with smart defaults
- Focus on your application instead of OpenCV's complex API
- Reduce errors with built-in validation and clearer error messages
- Learn computer vision concepts with intuitive function names
# OpenCV original:
img = cv2.imread('image.jpg')
if img is None:
    raise FileNotFoundError("Image not found")
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
blurred = cv2.GaussianBlur(img_rgb, (15, 15), 0)
edges = cv2.Canny(blurred, 100, 200)
# Easy OpenCV equivalent:
img = cv.load_image('image.jpg', mode='rgb')  # Load and convert in one step
blurred = cv.apply_gaussian_blur(img, kernel_size=15)
edges = cv.apply_edge_detection(blurred)π See DIFFERENCE.md for 22+ side-by-side code comparisons and EASY_OPENCV_BENEFITS.md for detailed benefits analysis.
- Intuitive API Design: Human-readable function names and parameters
- Intelligent Defaults: Functions work out-of-the-box with sensible parameters
- Automatic Processing: Many preprocessing steps are handled automatically
- Built-in Error Handling: Validation and clear error messages
- Comprehensive Documentation: Every function has detailed docstrings with examples
- Image Operations: Load, save, resize, crop, and convert images with simple function calls
- Video Processing: Handle video files, extract frames, and create videos from image sequences
- Image Processing: Apply filters, enhance images, and perform various image transformations
- Feature Detection: Detect corners, keypoints, contours, and match features between images
- Object Detection: π Class-based system with automatic webcam fallback - Face, eye, motion, and DNN object detection
- Drawing Operations: Draw shapes, text, and annotations on images
- Filters: Apply various filters including blur, sharpen, vintage, cartoon effects
- Transformations: Rotate, flip, warp, and apply perspective transformations
- Utilities: Helper functions for FPS counting, color picking, and image comparison
Easy OpenCV now features a powerful class-based object detection system with automatic webcam fallback:
from easy_opencv import FaceDetector, EyeDetector, ColorDetector
# π― Face detection with automatic webcam fallback
detector = FaceDetector()
results = detector.detect_from_source()  # Uses webcam if no source provided
# π¨ Detect red objects from webcam
color_detector = ColorDetector(target_color='red')
results = color_detector.detect_from_source()
# πΉ Motion detection with live preview
motion_detector = MotionDetector()
results = motion_detector.detect_from_source(show_live=True)
# π₯ Alternative webcam access methods
video = cv.load_video(0)  # Use camera index 0 (default webcam)
# Or use the WebcamCapture class for more control
webcam = cv.WebcamCapture()
webcam.capture(camera_id=0, save_path="recording.mp4")  # With optional recordingKey Features:
- π₯ Automatic webcam fallback when no image/video path provided
- π Support for images, videos, and live webcam streams
- ποΈ Reusable detector objects with custom parameters
- π Built-in live visualization with bounding boxes
- π Full backward compatibility with legacy functions
For reliable webcam access, there are several approaches:
# Method 1: Using the load_video function with camera index
video = cv.load_video(0)  # 0 = default webcam
while True:
    ret, frame = video.read()
    if not ret:
        break
    # Process frame
    cv.show_image(frame, 'Video', wait=False)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
video.release()
# Method 2: Using WebcamCapture class for interactive controls
webcam = cv.WebcamCapture()
webcam.capture(camera_id=0)  # Interactive session with keyboard controls
# Method 3: Using object detectors with built-in webcam support
detector = FaceDetector()
detector.detect_from_source(source=None)  # None defaults to webcam
β οΈ Note: When usingcv.show_image()in a video loop, setwait=Falseto prevent blocking.
pip install easy-opencvgit clone https://github.com/yourusername/easy-opencv.git
cd easy-opencv
pip install -r requirements.txt
pip install -e .- Python 3.7+
- OpenCV 4.5.0+
- NumPy 1.19.0+
- Pillow 8.0.0+
from easy_opencv import cv
# Load an image (automatically handles errors and converts to preferred format)
image = cv.load_image('path/to/image.jpg', mode='rgb')
# Get image information
info = cv.get_image_info(image)
print(f"Image dimensions: {info['width']}x{info['height']}, channels: {info['channels']}")
# Resize with aspect ratio preservation
resized = cv.resize_image(image, width=800)  # Height calculated automatically
# Apply a filter with one simple function call
blurred = cv.apply_gaussian_blur(image, kernel_size=15)
# Show the result (handles window creation and keypress waiting)
cv.show_image(blurred, 'Blurred Image')
# Save the result with quality control
cv.save_image(blurred, 'output.jpg', quality=95)from easy_opencv import cv
# Load image (handles errors automatically)
image = cv.load_image('portrait.jpg')
# Detect faces with simple parameters
faces = cv.detect_faces(image, scale_factor=1.1, min_neighbors=5)
# Process each face
for i, (x, y, w, h) in enumerate(faces):
    # Draw rectangle with built-in function
    image = cv.draw_rectangle(image, (x, y), (x+w, y+h), color=(0, 255, 0), thickness=2)
    # Add label with customization options
    image = cv.draw_text(image, f"Face {i+1}", (x, y-10),
                         font_scale=0.5, color=(255, 255, 255),
                         background=True, bg_color=(0, 200, 0))
    # Extract face region for further processing
    face_img = cv.crop_image(image, x, y, w, h)
    # Detect eyes within the face
    eyes = cv.detect_eyes(face_img)
    print(f"Found {len(eyes)} eyes in face {i+1}")
# Save and display the result
cv.save_image(image, 'detected_faces.jpg')
cv.show_image(image, 'Face Detection Results')from easy_opencv import cv
# Start with a single image
image = cv.load_image('scene.jpg')
# Create multiple processed versions
grayscale = cv.convert_color_space(image, 'rgb', 'gray')
blurred = cv.apply_gaussian_blur(image, kernel_size=15)
edges = cv.apply_edge_detection(image)
vintage = cv.apply_vintage_filter(image, intensity=0.7)
cartoon = cv.apply_cartoon_filter(image)
# Create a comparison grid with labels
images = [image, grayscale, blurred, edges, vintage, cartoon]
labels = ["Original", "Grayscale", "Blurred", "Edges", "Vintage", "Cartoon"]
# Add labels to images
labeled_images = []
for img, label in zip(images, labels):
    img_with_label = cv.draw_text(img.copy(), label, (10, 30),
                                  font_scale=0.8, color=(255, 255, 255),
                                  background=True)
    labeled_images.append(img_with_label)
# Create image grid (automatically handles different sized images)
grid = cv.create_image_grid(labeled_images, grid_size=(2, 3))
# Show the results
cv.show_image(grid, "Image Processing Effects")| Function | Description | Key Features | 
|---|---|---|
| load_image(path, mode='color') | Load images in different color modes | Handles errors, auto-converts color spaces | 
| save_image(image, path, quality=95) | Save images with quality control | Supports multiple formats, compression control | 
| resize_image(image, width=None, height=None, scale=None) | Flexible image resizing | Preserves aspect ratio, multiple methods | 
| crop_image(image, x, y, width, height) | Crop images to specified regions | Boundary checking, aspect ratio options | 
| convert_color_space(image, src_space='bgr', dst_space='rgb') | Convert between color spaces | Intuitive naming ('rgb' vs 'COLOR_BGR2RGB') | 
| merge_channels(channels) | Merge image channels | Automatic validation | 
| split_channels(image) | Split image into channels | Returns named tuple for clarity | 
π NEW Class-Based API with Webcam Support:
# Import the new video operation classes
from easy_opencv import VideoLoader, VideoPlayer, WebcamCapture, VideoAnalyzer
# Load video files or webcam streams
loader = VideoLoader()
video = loader.load("video.mp4")  # or loader.load(0) for webcam
# Play videos with advanced controls
player = VideoPlayer(default_speed=1.0, default_loop=True)
player.play("video.mp4")  # Interactive playback with controls
# Analyze video content
analyzer = VideoAnalyzer()
info = analyzer.get_info("video.mp4")
motion_data = analyzer.analyze_motion("video.mp4")
# Capture from webcam with recording
webcam = WebcamCapture()
webcam.capture(camera_id=0, save_path="recording.mp4")Available Video Classes:
- VideoLoader- Loading videos from files or webcam sources
- VideoSaver- Saving videos with customizable parameters
- VideoPlayer- Playing videos with advanced playback controls
- FrameExtractor- Extracting frames from videos
- VideoAnalyzer- Analyzing video properties and motion
- WebcamCapture- Capturing from webcams with interactive controls
Legacy Functions (Still Supported):
| Function | Description | Key Features | 
|---|---|---|
| load_video(path) | Load video files | Metadata extraction, error handling | 
| extract_frames(video_path, output_dir, frame_interval=1) | Extract frames from videos | Progress tracking, flexible naming | 
| create_video_from_frames(frame_paths, output_path, fps=30.0) | Create videos from image sequences | Auto resolution detection, codec options | 
| webcam_capture(camera_id=0, save_path=None) | Capture from webcam | Interactive controls, recording options | 
| get_video_info(video_path) | Get video metadata | FPS, resolution, duration, codec | 
| apply_video_filter(video_path, filter_func, output_path=None) | Process entire videos | Progress bar, parallel processing | 
| Function | Description | Key Features | 
|---|---|---|
| apply_blur(image, blur_type='gaussian', strength=5) | Apply various blur effects | Multiple algorithms, automatic kernel handling | 
| apply_edge_detection(image, method='canny') | Edge detection algorithms | Auto-threshold, pre-processing | 
| apply_threshold(image, threshold_type='binary') | Thresholding techniques | Multiple methods, auto-threshold option | 
| adjust_brightness_contrast(image, brightness=0, contrast=1.0) | Brightness/contrast adjustment | Preview option, clip protection | 
| equalize_histogram(image, adaptive=False) | Enhance image contrast | CLAHE adaptive option | 
| remove_noise(image, method='median') | Noise removal | Multiple algorithms | 
| sharpen_image(image, strength=1.0) | Sharpen images | Unsharp mask option | 
| invert_colors(image) | Invert image colors | Handles all color spaces | 
| Function | Description | Key Features | 
|---|---|---|
| detect_corners(image, method='harris') | Corner detection | Multiple algorithms, filtration | 
| detect_keypoints(image, detector='sift') | Keypoint detection | Multiple detectors (SIFT, ORB, etc.) | 
| match_features(desc1, desc2, method='bf') | Feature matching | Ratio test, RANSAC options | 
| detect_contours(image, threshold_value=127) | Contour detection | Hierarchy, filtering options | 
| find_template(image, template, method='ccoeff') | Template matching | Multiple methods, threshold | 
| find_lines(image, method='hough') | Line detection | Standard and probabilistic Hough | 
| find_circles(image) | Circle detection | Parameter optimization | 
| match_histograms(source, reference) | Match histogram between images | Channel-wise matching | 
π NEW Class-Based API with Webcam Support:
# Import the new detection classes
from easy_opencv import FaceDetector, EyeDetector, ColorDetector, MotionDetector
# Face detection with automatic webcam fallback
face_detector = FaceDetector(scale_factor=1.1, min_neighbors=5)
results = face_detector.detect_from_source()  # Uses webcam automatically
# Color detection from webcam
color_detector = ColorDetector(target_color='red', tolerance=20)
results = color_detector.detect_from_source(show_live=True)
# Motion detection with video output
motion_detector = MotionDetector(sensitivity=500)
results = motion_detector.detect_from_source(output_path="motion.mp4")Available Detector Classes:
- FaceDetector- Face detection using Haar cascades
- EyeDetector- Eye detection using Haar cascades
- CascadeDetector- Generic cascade detector for custom XML files
- MotionDetector- Motion detection with background subtraction
- CircleDetector- Circle detection using Hough Transform
- LineDetector- Line detection using Hough Transform
- ColorDetector- Color-based object detection in HSV space
- DNNObjectDetector- Deep learning object detection (SSD MobileNet V2)
Legacy Functions (Still Supported):
| Function | Description | Key Features | 
|---|---|---|
| detect_faces(image, scale_factor=1.1) | Face detection | Multiple models, confidence control | 
| detect_eyes(image, scale_factor=1.1) | Eye detection | Works within face regions | 
| detect_motion(video_path, sensitivity=500) | Motion detection | ROI selection, threshold control | 
| color_detection(image, target_color='red') | Color-based detection | HSV/RGB support, tolerance setting | 
| detect_objects_dnn(image) | DNN object detection | Pre-trained models, confidence threshold | 
| Function | Description | Key Features | 
|---|---|---|
| draw_rectangle(image, start_point, end_point, color=(0,255,0)) | Draw rectangles | Fill, opacity, rounded corners | 
| draw_circle(image, center, radius, color=(0,255,0)) | Draw circles | Fill, opacity control | 
| draw_text(image, text, position, font_scale=1.0) | Add text to images | Background, auto-positioning | 
| draw_bounding_boxes(image, boxes, labels=None) | Draw multiple bounding boxes | Labels, confidence scores | 
| draw_polygon(image, points, color=(0,255,0)) | Draw polygons | Fill, antialiased | 
| draw_arrow(image, start_point, end_point, color=(0,255,0)) | Draw arrows | Width, head size control | 
| draw_grid(image, grid_size, color=(128,128,128)) | Draw grid lines | Thickness, style options | 
| draw_crosshair(image, position, size=20, color=(0,255,0)) | Draw crosshair | Thickness, style options | 
| Function | Description | Key Features | 
|---|---|---|
| apply_gaussian_blur(image, kernel_size=15) | Gaussian blur filter | Auto odd kernel size | 
| apply_vintage_filter(image, intensity=0.5) | Vintage/sepia effect | Adjustable intensity | 
| apply_cartoon_filter(image) | Cartoon effect | Style parameters | 
| apply_motion_blur(image, size=15, angle=0) | Motion blur effect | Direction control | 
| apply_emboss_filter(image) | Emboss effect | Strength, direction | 
| apply_pencil_sketch(image, strength=0.5) | Pencil sketch effect | Color/grayscale options | 
| apply_hdr_effect(image) | HDR effect | Intensity control | 
| apply_custom_kernel(image, kernel) | Apply custom convolution | Border handling options | 
| Function | Description | Key Features | 
|---|---|---|
| rotate_image(image, angle, center=None) | Rotate images | Auto center, border handling | 
| flip_image(image, direction='horizontal') | Flip images | Multiple directions | 
| apply_perspective_transform(image, src_points, dst_points) | Perspective transformation | Auto size preservation | 
| apply_fisheye_effect(image, strength=0.5) | Fisheye lens effect | Adjustable strength | 
| warp_image(image, transform_matrix) | Apply affine/perspective warp | Border handling | 
| translate_image(image, x_shift, y_shift) | Translate images | Border handling | 
| resize_with_padding(image, width, height) | Resize with padding | Border color, position | 
| apply_barrel_distortion(image, strength=0.5) | Barrel distortion | Center point, strength | 
| Function | Description | Key Features | 
|---|---|---|
| fps_counter() | FPS measurement | Running average, display | 
| color_picker(image) | Interactive color picking | RGB/HSV display, zoom | 
| image_comparison(image1, image2, method='side_by_side') | Compare images | Multiple methods | 
| create_image_grid(images, grid_size) | Create image grids | Auto-sizing, padding, titles | 
| apply_watermark(image, text) | Add watermarks | Position, opacity | 
| get_dominant_colors(image, num_colors=5) | Extract dominant colors | K-means clustering | 
| auto_canny(image, sigma=0.33) | Automatic edge detection | Adaptive thresholds | 
| get_image_hash(image, hash_method='phash') | Generate image hash | Multiple algorithms | 
from easy_opencv import cv
# Load and process an image with error handling
try:
    image = cv.load_image('input.jpg', mode='rgb')
except Exception as e:
    print(f"Error loading image: {e}")
    image = cv.create_blank_image(800, 600, color=(240, 240, 240))  # Create blank image as fallback
# Get image information
info = cv.get_image_info(image)
print(f"Image size: {info['width']}x{info['height']}, {info['channels']} channels, {info['dtype']} type")
# Resize with aspect ratio preservation (multiple methods available)
resized = cv.resize_image(image, width=800, method='lanczos')  # Higher quality algorithm
# Apply enhancement pipeline
enhanced = image.copy()
enhanced = cv.remove_noise(enhanced, method='bilateral')  # Preserve edges while removing noise
enhanced = cv.adjust_brightness_contrast(enhanced, brightness=10, contrast=1.2)
enhanced = cv.apply_unsharp_mask(enhanced, radius=2.0, amount=1.0)  # Sharpen details
# Create side-by-side comparison with labels
comparison = cv.image_comparison(image, enhanced, method='side_by_side', labels=['Original', 'Enhanced'])
cv.save_image(comparison, 'comparison.jpg', quality=95)from easy_opencv import cv
import time
# Start the FPS counter
fps = cv.fps_counter()
# Load an image with faces
image = cv.load_image('group_photo.jpg', mode='rgb')
# Face detection with confidence control
faces = cv.detect_faces(image, scale_factor=1.1, min_neighbors=5, min_size=(30, 30))
print(f"Found {len(faces)} faces in the image")
# For each face, detect features and add annotations
result = image.copy()
for i, (x, y, w, h) in enumerate(faces):
    # Extract the face region
    face_img = cv.crop_image(image, x, y, w, h)
    # Get the face region information
    face_info = f"Face {i+1}"
    # Detect eyes within this face
    eyes = cv.detect_eyes(face_img)
    if len(eyes) > 0:
        face_info += f" ({len(eyes)} eyes)"
    # Try to detect a smile
    smile_detected = cv.detect_smile(face_img)
    if smile_detected:
        face_info += ", smiling"
    # Draw enhanced bounding box with information
    result = cv.draw_rectangle(result, (x, y), (x+w, y+h), color=(0, 255, 0), thickness=2)
    result = cv.draw_text(result, face_info, (x, y-10), font_scale=0.5,
                         color=(255, 255, 255), background=True, bg_color=(0, 128, 0))
# Color-based object detection in HSV space for more robust detection
red_mask = cv.color_detection(image, target_color='red', color_space='hsv', tolerance=15)
red_objects = cv.detect_contours(red_mask, min_area=100)
print(f"Found {len(red_objects)} red objects")
# Add red object outlines to the result
result = cv.draw_contour(result, red_objects, color=(0, 0, 255), thickness=2)
# Calculate and display FPS
fps_value = fps.get()
result = cv.draw_text(result, f"FPS: {fps_value:.1f}", (10, 30), font_scale=0.7,
                     color=(255, 255, 255), background=True)
# Save the final result
cv.save_image(result, 'detection_results.jpg')from easy_opencv import cv
# Load two images for feature matching
img1 = cv.load_image('scene.jpg', mode='rgb')
img2 = cv.load_image('object.jpg', mode='rgb')
# Detect keypoints and compute descriptors (SIFT by default)
keypoints1, descriptors1 = cv.detect_keypoints(img1, detector='sift')
keypoints2, descriptors2 = cv.detect_keypoints(img2, detector='sift')
print(f"Found {len(keypoints1)} keypoints in image 1")
print(f"Found {len(keypoints2)} keypoints in image 2")
# Match features between images
matches = cv.match_features(descriptors1, descriptors2, method='flann', ratio_threshold=0.7)
print(f"Found {len(matches)} good matches")
# Draw matches between images
match_img = cv.draw_matches(img1, keypoints1, img2, keypoints2, matches)
# Draw keypoints on original images
img1_kp = cv.draw_keypoints(img1, keypoints1)
img2_kp = cv.draw_keypoints(img2, keypoints2)
# Create a comparison grid
grid = cv.create_image_grid([img1_kp, img2_kp, match_img],
                           grid_size=(2, 2),
                           labels=["Image 1 Keypoints", "Image 2 Keypoints", "Matches"])
cv.show_image(grid, "Feature Matching")from easy_opencv import cv
import os
# Get information about a video file
video_info = cv.get_video_info('input_video.mp4')
print(f"Video dimensions: {video_info['width']}x{video_info['height']}")
print(f"Frame rate: {video_info['fps']:.2f} fps, Duration: {video_info['duration']:.2f} seconds")
print(f"Total frames: {video_info['frame_count']}, Codec: {video_info['codec']}")
# Extract frames with progress tracking
output_dir = 'extracted_frames'
if not os.path.exists(output_dir):
    os.makedirs(output_dir)
# Extract every 10th frame (10% of the video) with progress feedback
frame_paths = cv.extract_frames('input_video.mp4', output_dir,
                               frame_interval=10,
                               show_progress=True,
                               filename_format='frame_{:04d}.jpg')
print(f"Extracted {len(frame_paths)} frames to {output_dir}")
# Process extracted frames with a filter
processed_frames = []
for frame_path in frame_paths:
    frame = cv.load_image(frame_path)
    processed = cv.apply_vintage_filter(frame, intensity=0.6)
    output_path = frame_path.replace('.jpg', '_vintage.jpg')
    cv.save_image(processed, output_path)
    processed_frames.append(output_path)
# Create a new video from processed frames with custom settings
cv.create_video_from_frames(
    processed_frames,
    'vintage_video.mp4',
    fps=24.0,
    codec='mp4v',  # Codec options: 'mp4v', 'avc1', 'xvid', etc.
    size=None,     # Auto-detect from first frame
    is_color=True
)
# Motion detection with mask and visualization
cv.detect_motion(
    'input_video.mp4',
    'motion_output.mp4',
    sensitivity=500,
    min_area=500,
    blur_size=15,
    dilate_iterations=2,
    draw_bounding_boxes=True,
    show_progress=True
)from easy_opencv import cv
import numpy as np
# Create a blank canvas for drawing
canvas = cv.create_blank_image(800, 600, color=(240, 240, 240))
# Interactive color picker tool (click to get color values)
def on_color_pick(color, x, y):
    print(f"Picked color at ({x}, {y}): RGB={color}, HEX=#{color[0]:02x}{color[1]:02x}{color[2]:02x}")
cv.color_picker(image, window_name='Color Picker', callback=on_color_pick)
# Compare image processing methods with custom layout
original = cv.load_image('sample.jpg')
methods = {
    'Original': original,
    'Grayscale': cv.convert_color_space(original, 'rgb', 'gray'),
    'Blurred': cv.apply_gaussian_blur(original, kernel_size=15),
    'Edges': cv.apply_edge_detection(original),
    'Cartoon': cv.apply_cartoon_filter(original),
    'Vintage': cv.apply_vintage_filter(original)
}
# Create a comparison with multiple layouts
comparisons = {
    'Side by Side': cv.image_comparison(methods['Original'], methods['Cartoon'], method='side_by_side'),
    'Slider': cv.image_comparison(methods['Original'], methods['Vintage'], method='slider'),
    'Split': cv.image_comparison(methods['Original'], methods['Edges'], method='split'),
    'Blend': cv.image_comparison(methods['Original'], methods['Blurred'], method='blend', alpha=0.5)
}
# Create image grid with auto-sizing and labels
grid = cv.create_image_grid(
    list(methods.values()),
    grid_size=(2, 3),
    image_size=(300, 200),  # Target size for each grid cell
    padding=10,            # Padding between images
    background_color=(20, 20, 20),
    labels=list(methods.keys())
)
# Add watermark
grid = cv.apply_watermark(
    grid,
    text="Easy OpenCV Demo",
    position='bottom_right',
    font_scale=0.8,
    color=(255, 255, 255),
    opacity=0.7
)
cv.show_image(grid, 'Effect Comparison')
# Analyze image histograms
hist = cv.calculate_histogram(original)
hist_image = cv.draw_histogram(hist, size=(600, 400))
cv.show_image(hist_image, 'RGB Histogram')from easy_opencv import cv
# Start webcam capture with options
def frame_processor(frame):
    """Process each frame from the webcam"""
    # Apply real-time cartoon effect
    cartoon = cv.apply_cartoon_filter(frame)
    # Add FPS counter to the frame
    fps = cv.fps_counter().get()
    cartoon = cv.draw_text(cartoon, f"FPS: {fps:.1f}", (10, 30),
                          font_scale=0.7, color=(255, 255, 255), background=True)
    return cartoon
# Start webcam capture with the frame processor
cv.webcam_capture(
    camera_id=0,              # Use default camera
    frame_processor=frame_processor,
    window_name="Cartoon Webcam",
    save_path="webcam_recording.mp4",  # Optional recording
    record_fps=30.0,
    width=640,
    height=480
)Error: ModuleNotFoundError: No module named 'easy_opencv_wrapper'
Solution: Use the correct import statement: from easy_opencv import cv
Error: ModuleNotFoundError: No module named 'easy-opencv'
Solution: The package name uses underscores in imports, not hyphens: from easy_opencv import cv
Error: AttributeError: 'EasyCV' object has no attribute 'open_webcam'
Solution: Use cv.load_video(0) instead for webcam access, or the WebcamCapture class.
Error: Webcam freezes when using show_image in a loop
Solution: Set wait=False in cv.show_image() when using it in a video loop.
# Correct way to use show_image in a video loop
while True:
    ret, frame = video.read()
    if not ret:
        break
    cv.show_image(frame, 'Video', wait=False)  # Set wait=False to prevent blocking
    if cv2.waitKey(1) & 0xFF == ord('q'):
        breakError: No key detection when processing video frames
Solution: Use direct OpenCV for keyboard detection:
import cv2  # Import OpenCV directly for keyboard handling
# In your video loop
if cv2.waitKey(1) & 0xFF == ord('q'):
    break  # Exit on 'q' key pressIf you encounter problems not covered in this troubleshooting guide:
- Check our Documentation folder for more examples
- See DIFFERENCE.md for detailed code comparisons
- File an issue on our GitHub repository
- Join our community Discord server for live help
Remember that Easy OpenCV is a wrapper around OpenCV, so you can always mix both APIs when needed for specific functionality.
- Python 3.7+: Core language support
- OpenCV 4.5.0+: Core computer vision functionality
- NumPy 1.19.0+: Numerical processing
- Pillow 8.0.0+: Image processing support
| Resource | Description | 
|---|---|
| DIFFERENCES.md | 22+ Side-by-side code comparisons between OpenCV and Easy OpenCV for common tasks | 
| EASY_OPENCV_BENEFITS.md | Detailed analysis of benefits and performance considerations | 
| USAGE_GUIDE.md | Comprehensive guide with detailed explanations and step-by-step tutorials | 
| WHY_EASY_OPENCV.md | In-depth explanation of design philosophy and technical benefits | 
| PROJECT_STRUCTURE.md | Package organization and module overview for developers | 
| TEST_ANALYSIS_REPORT.md | Detailed test coverage analysis and recommendations | 
| DEBUGGED_SUMMARY.md | Summary of debugging processes and resolved issues | 
# Install the package
pip install easy-opencv
# Import the library
from easy_opencv import cv
# Load an image and convert to RGB in one line
img = cv.load_image('photo.jpg', mode='rgb')
# Apply multiple effects sequentially
enhanced = cv.adjust_brightness_contrast(img, brightness=10, contrast=1.2)
cartoon = cv.apply_cartoon_filter(enhanced)
# Show the result and save
cv.show_image(cartoon, "Cartoon Effect")
cv.save_image(cartoon, "cartoon_result.jpg")- Write 50-70% less code for common computer vision tasks
- Eliminate complex parameters with intuitive function calls
- Avoid common errors with built-in validation
- Improve readability with consistent API design
- Learn computer vision with intuitive function names
- Simplify color space handling with semantic naming
For developers already familiar with OpenCV, Easy OpenCV makes your code cleaner and more maintainable. For newcomers to computer vision, it provides a gentle learning curve with powerful functionality.
See the EASY_OPENCV_BENEFITS.md document for a detailed analysis of these benefits.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (git checkout -b feature/amazing-feature)
- Commit your changes (git commit -m 'Add some amazing feature')
- Push to the branch (git push origin feature/amazing-feature)
- Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
  Made with β€οΈ for computer vision enthusiasts everywhere
  Easy OpenCV - Computer vision made simple