Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Complete OpenCV computer vision system for Python. PROACTIVELY activate for: (1) Image loading with cv2.imread (BGR format gotcha), (2) Video capture with cv2.VideoCapture, (3) Color space conversion (BGR to RGB, HSV, grayscale), (4) Image filtering (GaussianBlur, medianBlur, bilateralFilter), (5) Edge detection (Canny), (6) Contour detection with cv2.findContours, (7) Image resizing with interpolation methods, (8) Template matching, (9) Feature detection (SIFT, ORB, AKAZE), (10) Drawing functions (rectangle, circle, text), (11) Video writing with cv2.VideoWriter, (12) Morphological operations, (13) Deep learning with cv2.dnn module, (14) GPU acceleration with cv2.cuda, (15) Coordinate system (x,y vs row,col) gotchas. Provides: Image processing patterns, video capture/writing, memory management, performance optimization, Jupyter notebook workarounds. Ensures correct BGR handling and memory-safe OpenCV usage.
Quick Reference
Function
Purpose
Gotcha
cv2.imread(path)
Load image
Returns None if path invalid (no error!)
cv2.imwrite(path, img)
Save image
Expects BGR, not RGB
cv2.cvtColor(img, code)
Color conversion
BGR is default, not RGB
cv2.VideoCapture(src)
Video/camera input
Always check isOpened() and release()
cv2.VideoWriter(...)
Save video
Expects BGR frames, codec matters
cv2.resize(img, (w, h))
Resize image
Size is (width, height), not (height, width)
Coordinate System
Order
Usage
NumPy indexing
img[row, col] = img[y, x]
Pixel access
Image shape
(height, width, channels)
Shape is (rows, cols, ch)
OpenCV functions
(x, y)
Drawing functions
Resize/ROI
(width, height)
Size parameters
Color Conversion
Code
Note
BGR to RGB
cv2.COLOR_BGR2RGB
For Matplotlib display
BGR to Gray
cv2.COLOR_BGR2GRAY
Single channel output
BGR to HSV
cv2.COLOR_BGR2HSV
H: 0-179, S/V: 0-255
Interpolation
Best For
Speed
INTER_NEAREST
Speed, pixelated OK
Fastest
INTER_LINEAR
General purpose (default)
Fast
INTER_AREA
Downscaling
Medium
INTER_CUBIC
Upscaling quality
Slow
INTER_LANCZOS4
Best upscaling
Slowest
When to Use This Skill
Use for computer vision and image processing:
Loading, displaying, and saving images
Video capture from cameras or files
Image filtering and transformations
Edge and contour detection
Object detection and template matching
Feature detection and matching
Deep learning inference with DNN module
Related skills:
For NumPy arrays: see python-fundamentals-313
For async processing: see python-asyncio
For type hints: see python-type-hints
OpenCV Python Complete Guide (2025)
Overview
OpenCV (Open Source Computer Vision Library) is the most popular computer vision library. Python bindings (opencv-python) provide access to all functionality through NumPy arrays. OpenCV uses BGR color format by default, which is a critical gotcha.
Installation
# CPU-only (most common)
pip install opencv-python
# With contrib modules (SIFT, SURF, extra features)
pip install opencv-contrib-python
# Headless (no GUI, for servers)
pip install opencv-python-headless
# Verify installation
python -c "import cv2; print(cv2.__version__)"
Critical Gotchas
1. BGR vs RGB Color Format
The #1 source of OpenCV bugs. OpenCV uses BGR, not RGB.
import cv2
import numpy as np
from matplotlib import pyplot as plt
# OpenCV reads images in BGR format
img_bgr = cv2.imread("image.jpg") # BGR!# WRONG: Display BGR directly with Matplotlib# plt.imshow(img_bgr) # Colors will be wrong!# CORRECT: Convert to RGB for Matplotlib
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
plt.imshow(img_rgb)
plt.show()
# CORRECT: Save with OpenCV (expects BGR)
cv2.imwrite("output.jpg", img_bgr) # Correct colors# WRONG: Save RGB with OpenCV# cv2.imwrite("output.jpg", img_rgb) # Colors will be wrong!
PIL/Pillow Integration:
from PIL import Image
import cv2
import numpy as np
# PIL uses RGB, OpenCV uses BGR
pil_image = Image.open("image.jpg") # RGB
cv_image = np.array(pil_image) # Still RGB!
cv_image_bgr = cv2.cvtColor(cv_image, cv2.COLOR_RGB2BGR) # Now BGR# Going back to PIL
cv_result = cv2.GaussianBlur(cv_image_bgr, (5, 5), 0)
cv_result_rgb = cv2.cvtColor(cv_result, cv2.COLOR_BGR2RGB)
pil_result = Image.fromarray(cv_result_rgb)
import cv2
import numpy as np
# Create kernel
kernel = np.ones((5, 5), np.uint8)
# Or use getStructuringElement for different shapes
kernel_rect = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
kernel_ellipse = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
kernel_cross = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
# Erosion - shrinks white regions
eroded = cv2.erode(img, kernel, iterations=1)
# Dilation - expands white regions
dilated = cv2.dilate(img, kernel, iterations=1)
# Opening - erosion followed by dilation (removes noise)
opened = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
# Closing - dilation followed by erosion (fills holes)
closed = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
# Gradient - dilation minus erosion (edge detection)
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
# Top hat - original minus opening
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
# Black hat - closing minus original
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
Contour Detection
Finding Contours
import cv2
import numpy as np
img = cv2.imread("image.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Threshold or use Canny for edge detection
_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# Find contours
contours, hierarchy = cv2.findContours(
thresh,
cv2.RETR_EXTERNAL, # Retrieval mode
cv2.CHAIN_APPROX_SIMPLE # Contour approximation
)
# Retrieval modes:# RETR_EXTERNAL - only outermost contours# RETR_LIST - all contours, no hierarchy# RETR_CCOMP - two-level hierarchy# RETR_TREE - full hierarchy# Approximation methods:# CHAIN_APPROX_NONE - all points# CHAIN_APPROX_SIMPLE - compress horizontal, vertical, diagonal segments# Draw contours
cv2.drawContours(img, contours, -1, (0, 255, 0), 2)
# -1 draws all contours, or specify index# Draw single contour
cv2.drawContours(img, contours, 0, (0, 255, 0), 2)
Contour Properties
import cv2
import numpy as np
# For each contourfor cnt in contours:
# Area
area = cv2.contourArea(cnt)
# Perimeter (arc length)
perimeter = cv2.arcLength(cnt, closed=True)
# Bounding rectangle (upright)
x, y, w, h = cv2.boundingRect(cnt)
# Rotated bounding rectangle
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
# Minimum enclosing circle
(cx, cy), radius = cv2.minEnclosingCircle(cnt)
# Fit ellipse (requires at least 5 points)iflen(cnt) >= 5:
ellipse = cv2.fitEllipse(cnt)
# Convex hull
hull = cv2.convexHull(cnt)
# Centroid using moments
M = cv2.moments(cnt)
if M["m00"] != 0:
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])
# Approximate polygon
epsilon = 0.02 * perimeter
approx = cv2.approxPolyDP(cnt, epsilon, closed=True)
Image Resizing and Transformations
Resizing
import cv2
img = cv2.imread("image.jpg")
# Resize to specific dimensions# Note: (width, height) not (height, width)!
resized = cv2.resize(img, (640, 480))
# Resize by scale factor
scaled = cv2.resize(img, None, fx=0.5, fy=0.5)
# With interpolation method# INTER_NEAREST - fastest, blocky# INTER_LINEAR - default, good balance# INTER_AREA - best for shrinking# INTER_CUBIC - better quality for enlarging# INTER_LANCZOS4 - best quality for enlarging# Downscaling - use INTER_AREA
small = cv2.resize(img, (320, 240), interpolation=cv2.INTER_AREA)
# Upscaling - use INTER_CUBIC or INTER_LANCZOS4
large = cv2.resize(img, (1920, 1080), interpolation=cv2.INTER_CUBIC)
Rotation and Flipping
import cv2
import numpy as np
img = cv2.imread("image.jpg")
h, w = img.shape[:2]
# Flip
flipped_h = cv2.flip(img, 1) # Horizontal
flipped_v = cv2.flip(img, 0) # Vertical
flipped_both = cv2.flip(img, -1) # Both# Rotate 90, 180, 270 degrees
rot_90 = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)
rot_180 = cv2.rotate(img, cv2.ROTATE_180)
rot_270 = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)
# Rotate by arbitrary angle
angle = 45
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, angle, scale=1.0)
rotated = cv2.warpAffine(img, M, (w, h))
# Rotate and expand canvas to fitdefrotate_bound(image, angle):
h, w = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
cos = np.abs(M[0, 0])
sin = np.abs(M[0, 1])
new_w = int((h * sin) + (w * cos))
new_h = int((h * cos) + (w * sin))
M[0, 2] += (new_w / 2) - center[0]
M[1, 2] += (new_h / 2) - center[1]
return cv2.warpAffine(image, M, (new_w, new_h))
Perspective Transform
import cv2
import numpy as np
img = cv2.imread("document.jpg")
# Define source points (corners of object in image)
src_pts = np.float32([
[100, 200], # top-left
[500, 180], # top-right
[550, 400], # bottom-right
[80, 420] # bottom-left
])
# Define destination points (where they should map to)
dst_pts = np.float32([
[0, 0],
[400, 0],
[400, 300],
[0, 300]
])
# Get perspective transform matrix
M = cv2.getPerspectiveTransform(src_pts, dst_pts)
# Apply transform
warped = cv2.warpPerspective(img, M, (400, 300))
Template Matching
import cv2
import numpy as np
img = cv2.imread("image.jpg")
template = cv2.imread("template.jpg")
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray_template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
h, w = gray_template.shape
# Match template
result = cv2.matchTemplate(gray_img, gray_template, cv2.TM_CCOEFF_NORMED)
# Methods:# TM_SQDIFF, TM_SQDIFF_NORMED - min value is best match# TM_CCORR, TM_CCORR_NORMED - max value is best match# TM_CCOEFF, TM_CCOEFF_NORMED - max value is best match (recommended)# Find best match location
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
# For TM_CCOEFF_NORMED, use max_loc
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
# Draw rectangle around match
cv2.rectangle(img, top_left, bottom_right, (0, 255, 0), 2)
# Multiple matches with thresholding
threshold = 0.8
loc = np.where(result >= threshold)
for pt inzip(*loc[::-1]): # Note: loc is (y, x), zip reverses
cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0, 255, 0), 2)
import cv2
img1 = cv2.imread("image1.jpg", cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread("image2.jpg", cv2.IMREAD_GRAYSCALE)
# Create SIFT detector
sift = cv2.SIFT_create()
# Detect and compute
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
# Use FLANN matcher for SIFT (faster for large datasets)
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
# KNN match
matches = flann.knnMatch(des1, des2, k=2)
# Apply Lowe's ratio test
good_matches = []
for m, n in matches:
if m.distance < 0.7 * n.distance:
good_matches.append(m)
DNN Module (Deep Learning Inference)
import cv2
import numpy as np
# Load model# TensorFlow (.pb)
net = cv2.dnn.readNetFromTensorflow("model.pb", "config.pbtxt")
# ONNX
net = cv2.dnn.readNetFromONNX("model.onnx")
# Darknet/YOLO
net = cv2.dnn.readNetFromDarknet("yolov3.cfg", "yolov3.weights")
# Caffe
net = cv2.dnn.readNetFromCaffe("deploy.prototxt", "model.caffemodel")
# Set backend and target
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)
# Or for GPU: DNN_TARGET_CUDA# Prepare input blob
img = cv2.imread("image.jpg")
blob = cv2.dnn.blobFromImage(
img,
scalefactor=1/255.0, # Normalize to 0-1
size=(416, 416), # Network input size
mean=(0, 0, 0), # Subtract mean
swapRB=True, # BGR to RGB!
crop=False
)
# Run inference
net.setInput(blob)
output = net.forward()
# Or get specific layers: net.forward(["layer1", "layer2"])
Displaying Images (GUI)
OpenCV Windows
import cv2
img = cv2.imread("image.jpg")
# Create window
cv2.namedWindow("Window", cv2.WINDOW_NORMAL) # Resizable# cv2.WINDOW_AUTOSIZE - fixed size# Show image
cv2.imshow("Window", img)
# Wait for key press
key = cv2.waitKey(0) # 0 = wait forever# key = cv2.waitKey(1) # 1ms, for video loops# Clean up
cv2.destroyAllWindows()
# cv2.destroyWindow("Window") # Specific window# Note: waitKey returns -1 if no key pressed, or ASCII valueif cv2.waitKey(1) & 0xFF == ord('q'):
break
Jupyter Notebook Workaround
cv2.imshow() doesn't work well in Jupyter notebooks!
import cv2
import numpy as np
from matplotlib import pyplot as plt
from IPython.display import display, Image as IPImage
import io
# Method 1: Use Matplotlib (recommended)defshow_image(img, title="Image"):
"""Display image in Jupyter using Matplotlib."""iflen(img.shape) == 3:
# Convert BGR to RGB
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
else:
img_rgb = img
plt.figure(figsize=(10, 8))
plt.imshow(img_rgb, cmap='gray'iflen(img.shape) == 2elseNone)
plt.title(title)
plt.axis('off')
plt.show()
# Method 2: Use IPython displaydefshow_image_ipython(img):
"""Display image using IPython display."""
_, encoded = cv2.imencode('.png', img)
display(IPImage(data=encoded.tobytes()))
# Method 3: Use cv2_imshow from google.colab (in Colab)# from google.colab.patches import cv2_imshow# cv2_imshow(img)
Performance Tips
Memory Management
import cv2
import numpy as np
# 1. Reuse arrays instead of creating new ones
frame = np.empty((480, 640, 3), dtype=np.uint8)
cap = cv2.VideoCapture(0)
whileTrue:
ret = cap.read(frame) # Reuses frame arrayifnot ret:
break# 2. Use views instead of copies when possible
roi = img[100:200, 100:200] # This is a view, not a copy
roi_copy = img[100:200, 100:200].copy() # This creates a copy# 3. Process in-place when possible
cv2.GaussianBlur(img, (5, 5), 0, dst=img) # In-place# 4. Use appropriate data types
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # uint8# Don't convert to float64 unless necessary# 5. Pre-allocate for batch processing
results = np.empty((num_images, h, w, 3), dtype=np.uint8)
for i, img_path inenumerate(paths):
results[i] = process(cv2.imread(img_path))
Vectorized Operations
import cv2
import numpy as np
# BAD: Using loopsfor i inrange(img.shape[0]):
for j inrange(img.shape[1]):
img[i, j] = img[i, j] * 2# GOOD: Vectorized with NumPy/OpenCV
img = img * 2# NumPy broadcasting# or
img = cv2.multiply(img, 2) # OpenCV (handles overflow)# Use OpenCV functions over NumPy when available# OpenCV is optimized with SIMD, multi-threading# OpenCV (faster)
result = cv2.countNonZero(mask)
# NumPy (slower for this)
result = np.count_nonzero(mask)
GPU Acceleration (CUDA)
import cv2
# Check CUDA availabilityprint(cv2.cuda.getCudaEnabledDeviceCount())
if cv2.cuda.getCudaEnabledDeviceCount() > 0:
# Upload image to GPU
gpu_img = cv2.cuda_GpuMat()
gpu_img.upload(img)
# GPU operations
gpu_gray = cv2.cuda.cvtColor(gpu_img, cv2.COLOR_BGR2GRAY)
gpu_blur = cv2.cuda.createGaussianFilter(
cv2.CV_8UC1, cv2.CV_8UC1, (5, 5), 0
).apply(gpu_gray)
# Download back to CPU
result = gpu_blur.download()
else:
# Fallback to CPU
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
result = cv2.GaussianBlur(gray, (5, 5), 0)