Source code for scitex_cv._filters

#!/usr/bin/env python3
# Timestamp: 2026-01-08
# File: src/scitex/cv/_filters.py
"""Image filtering utilities using cv2."""

from __future__ import annotations

import cv2
import numpy as np


[docs] def blur( img: np.ndarray, ksize: int = 5, method: str = "gaussian", ) -> np.ndarray: """Apply blur to an image. Parameters ---------- img : np.ndarray Input image. ksize : int Kernel size (must be odd). method : str Blur method: 'gaussian', 'median', 'box', 'bilateral'. Returns ------- np.ndarray Blurred image. """ if ksize % 2 == 0: ksize += 1 if method == "gaussian": return cv2.GaussianBlur(img, (ksize, ksize), 0) elif method == "median": return cv2.medianBlur(img, ksize) elif method == "box": return cv2.blur(img, (ksize, ksize)) elif method == "bilateral": return cv2.bilateralFilter(img, ksize, 75, 75) else: raise ValueError(f"Unknown blur method: {method}")
[docs] def sharpen(img: np.ndarray, strength: float = 1.0) -> np.ndarray: """Sharpen an image. Parameters ---------- img : np.ndarray Input image. strength : float Sharpening strength. Returns ------- np.ndarray Sharpened image. """ kernel = np.array( [ [0, -1, 0], [-1, 5, -1], [0, -1, 0], ], dtype=np.float32, ) if strength != 1.0: kernel = np.eye(3) + strength * (kernel - np.eye(3)) return cv2.filter2D(img, -1, kernel)
[docs] def edge_detect( img: np.ndarray, method: str = "canny", low: int = 50, high: int = 150, ) -> np.ndarray: """Detect edges in an image. Parameters ---------- img : np.ndarray Input image. method : str Edge detection method: 'canny', 'sobel', 'laplacian'. low, high : int Thresholds for Canny detector. Returns ------- np.ndarray Edge image. """ if len(img.shape) == 3: gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) else: gray = img if method == "canny": return cv2.Canny(gray, low, high) elif method == "sobel": sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3) sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3) return np.uint8(np.sqrt(sobel_x**2 + sobel_y**2)) elif method == "laplacian": return np.uint8(np.abs(cv2.Laplacian(gray, cv2.CV_64F))) else: raise ValueError(f"Unknown edge method: {method}")
[docs] def threshold( img: np.ndarray, thresh: int = 127, maxval: int = 255, method: str = "binary", ) -> np.ndarray: """Apply thresholding to an image. Parameters ---------- img : np.ndarray Input image. thresh : int Threshold value. maxval : int Maximum value. method : str Threshold method: 'binary', 'binary_inv', 'trunc', 'tozero', 'tozero_inv', 'otsu', 'adaptive_mean', 'adaptive_gaussian'. Returns ------- np.ndarray Thresholded image. """ if len(img.shape) == 3: gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) else: gray = img method_map = { "binary": cv2.THRESH_BINARY, "binary_inv": cv2.THRESH_BINARY_INV, "trunc": cv2.THRESH_TRUNC, "tozero": cv2.THRESH_TOZERO, "tozero_inv": cv2.THRESH_TOZERO_INV, } if method == "otsu": _, result = cv2.threshold(gray, 0, maxval, cv2.THRESH_BINARY + cv2.THRESH_OTSU) elif method == "adaptive_mean": result = cv2.adaptiveThreshold( gray, maxval, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2 ) elif method == "adaptive_gaussian": result = cv2.adaptiveThreshold( gray, maxval, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2, ) else: thresh_type = method_map.get(method, cv2.THRESH_BINARY) _, result = cv2.threshold(gray, thresh, maxval, thresh_type) return result
[docs] def denoise( img: np.ndarray, strength: int = 10, method: str = "fastNl", ) -> np.ndarray: """Denoise an image. Parameters ---------- img : np.ndarray Input image. strength : int Denoising strength. method : str Denoising method: 'fastNl', 'bilateral'. Returns ------- np.ndarray Denoised image. """ if method == "fastNl": if len(img.shape) == 3: return cv2.fastNlMeansDenoisingColored(img, None, strength, strength) else: return cv2.fastNlMeansDenoising(img, None, strength) elif method == "bilateral": return cv2.bilateralFilter(img, 9, strength * 7.5, strength * 7.5) else: raise ValueError(f"Unknown denoise method: {method}")
__all__ = [ "blur", "sharpen", "edge_detect", "threshold", "denoise", ] # EOF