ai-art-director / filters.py
Alexandros Popov
included precommit.
6894106
raw
history blame
5.21 kB
import os
import tempfile
import cv2
import numpy as np
from PIL import Image
from smolagents import tool
def apply_filters(image: np.ndarray) -> list[np.ndarray]:
"""Applies a series of filters to the input image.
Args:
image (np.ndarray): Input image in BGR format.
Returns:
list[np.ndarray]: List of filtered images in BGR format.
"""
filtered_images = []
# Filter 1: Contrast adjustment
filtered_images.append(adjust_contrast(image))
# Filter 2: Saturation boost
filtered_images.append(adjust_saturation(image))
# Filter 3: Exposure adjustment
filtered_images.append(adjust_exposure(image))
# Filter 4: Denoised
filtered_images.append(denoise_image(image))
# Filter 5: Vignette effect
filtered_images.append(apply_vignette(image))
return filtered_images
@tool
def adjust_contrast(image: np.ndarray, alpha: float = 1.5) -> np.ndarray:
"""Adjusts the contrast of the image.
Args:
image (np.ndarray): Input image in BGR format.
alpha (float, optional): Contrast control (1.0-3.0). 1.0 means no change. Defaults to 1.5.
Returns:
np.ndarray: Contrast adjusted image in BGR format.
"""
return cv2.convertScaleAbs(image, alpha=alpha, beta=0)
@tool
def adjust_saturation(image: np.ndarray, saturation_scale: float = 1.0) -> np.ndarray:
"""Adjusts the saturation of the image.
Args:
image (np.ndarray): Input image in BGR format.
saturation_scale (float, optional): Saturation scale factor. 1.0 means no change. Defaults to 1.0.
Returns:
np.ndarray: Saturation adjusted image in BGR format.
"""
hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV).astype(np.float32)
hsv_img[:, :, 1] *= saturation_scale
hsv_img[:, :, 1] = np.clip(hsv_img[:, :, 1], 0, 255)
return cv2.cvtColor(hsv_img.astype(np.uint8), cv2.COLOR_HSV2BGR)
@tool
def adjust_exposure(image: np.ndarray, beta: int = 50) -> np.ndarray:
"""Adjusts the exposure (brightness) of the image.
Args:
image (np.ndarray): Input image in BGR format.
beta (int, optional): Brightness control. Positive values increase brightness, negative decrease. Defaults 50.
Returns:
np.ndarray: Exposure adjusted image in BGR format.
"""
return cv2.convertScaleAbs(image, alpha=1.0, beta=beta)
@tool
def denoise_image(image: np.ndarray, h: int = 10) -> np.ndarray:
"""Denoises the image using Non-local Means Denoising algorithm.
Args:
image (np.ndarray): Input image in BGR format.
h (int, optional): Filter strength. Higher h value removes noise better but removes details. Defaults to 10.
Returns:
np.ndarray: Denoised image in BGR format.
"""
return cv2.fastNlMeansDenoisingColored(image, None, h, h, 7, 21)
@tool
def crop_image(image: np.ndarray, x: int, y: int, width: int, height: int) -> np.ndarray:
"""Crops the image to the specified rectangle.
Args:
image (np.ndarray): Input image in BGR format.
x (int): Top-left x-coordinate.
y (int): Top-left y-coordinate.
width (int): Width of the crop rectangle.
height (int): Height of the crop rectangle.
Returns:
np.ndarray: Cropped image in BGR format.
"""
return image[y : y + height, x : x + width]
@tool
def apply_vignette(image: np.ndarray, level: int = 2) -> np.ndarray:
"""Applies a vignette effect to the image.
Args:
image (np.ndarray): Input image in BGR format.
level (int, optional): Intensity of the vignette effect. Defaults to 2.
Returns:
np.ndarray: Image with vignette effect applied in BGR format.
"""
rows, cols = image.shape[:2]
kernel_x = cv2.getGaussianKernel(cols, cols / level)
kernel_y = cv2.getGaussianKernel(rows, rows / level)
kernel = kernel_y * kernel_x.T
mask = kernel / kernel.max()
vignette = np.copy(image)
for i in range(3):
vignette[:, :, i] = vignette[:, :, i] * mask
return vignette
@tool
def load_image_as_bgr(image_path: str) -> np.ndarray:
"""Loads an image from path and converts it to BGR format for OpenCV.
Args:
image_path (str): Path to the image file.
Returns:
np.ndarray: Image in BGR format as numpy array.
"""
image = Image.open(image_path)
image_np = np.array(image)
return cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
@tool
def save_image(image: np.ndarray, image_path: str) -> None:
"""Saves an image to the specified path.
Args:
image (np.ndarray): Image to save.
image_path (str): Path to save the image.
"""
cv2.imwrite(image_path, image)
if __name__ == "__main__":
# Load a test image
test_image_np = load_image_as_bgr("test_image.jpg")
# Apply all filters
filtered_images = apply_filters(test_image_np)
# Save results
dir = tempfile.mkdtemp()
for i, filtered_img in enumerate(filtered_images):
output_path = os.path.join(dir, f"filter_{i+1}.jpg")
rgb_img = cv2.cvtColor(filtered_img, cv2.COLOR_BGR2RGB)
Image.fromarray(rgb_img).save(output_path)
print(f"Saved {output_path}")