本文目录导读:

我来介绍几个使用Python实现图像滤镜的完整案例,主要使用PIL(Pillow)和OpenCV库。
环境准备
首先安装必要的库:
pip install pillow opencv-python numpy
基础滤镜实现
1 灰度滤镜
from PIL import Image
import numpy as np
def grayscale_filter(image_path, output_path):
"""灰度滤镜 - 方法1:使用PIL内置方法"""
img = Image.open(image_path)
gray_img = img.convert('L')
gray_img.save(output_path)
return gray_img
def grayscale_filter_manual(image_path, output_path):
"""灰度滤镜 - 方法2:手动实现"""
img = Image.open(image_path)
pixels = np.array(img)
# 加权平均法
gray = np.dot(pixels[...,:3], [0.299, 0.587, 0.114])
gray = gray.astype(np.uint8)
result = Image.fromarray(gray)
result.save(output_path)
return result
# 使用示例
grayscale_filter('input.jpg', 'gray_output.jpg')
2 复古/怀旧滤镜
def vintage_filter(image_path, output_path):
"""复古怀旧滤镜"""
img = Image.open(image_path)
pixels = np.array(img)
# 增加暖色调
r, g, b = pixels[:,:,0], pixels[:,:,1], pixels[:,:,2]
r = np.clip(r * 0.9 + 30, 0, 255).astype(np.uint8)
g = np.clip(g * 0.85 + 20, 0, 255).astype(np.uint8)
b = np.clip(b * 0.75, 0, 255).astype(np.uint8)
result = np.stack([r, g, b], axis=2)
result = Image.fromarray(result)
result.save(output_path)
return result
3 模糊滤镜
from PIL import ImageFilter
def blur_filter(image_path, output_path, radius=5):
"""高斯模糊滤镜"""
img = Image.open(image_path)
# 使用PIL内置高斯模糊
blurred = img.filter(ImageFilter.GaussianBlur(radius=radius))
blurred.save(output_path)
return blurred
def motion_blur(image_path, output_path, size=10):
"""运动模糊效果"""
img = Image.open(image_path)
# 创建运动模糊核
kernel = np.zeros((size, size))
kernel[int((size-1)/2), :] = np.ones(size)
kernel = kernel / size
# 应用卷积
from scipy import signal
pixels = np.array(img)
if len(pixels.shape) == 3:
result = np.zeros_like(pixels)
for i in range(3):
result[:,:,i] = signal.convolve2d(
pixels[:,:,i], kernel, mode='same', boundary='symm'
)
else:
result = signal.convolve2d(pixels, kernel, mode='same', boundary='symm')
result = result.astype(np.uint8)
result = Image.fromarray(result)
result.save(output_path)
return result
4 边缘检测滤镜
def edge_detection(image_path, output_path):
"""边缘检测滤镜"""
# 方法1:使用PIL
img = Image.open(image_path).convert('L')
# 查找边缘
edges = img.filter(ImageFilter.FIND_EDGES)
edges.save(output_path)
# 方法2:使用Sobel算子
img_array = np.array(img)
# Sobel算子
sobel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
sobel_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])
from scipy import signal
grad_x = signal.convolve2d(img_array, sobel_x, mode='same', boundary='symm')
grad_y = signal.convolve2d(img_array, sobel_y, mode='same', boundary='symm')
# 计算梯度幅值
gradient = np.sqrt(grad_x**2 + grad_y**2)
gradient = (gradient / gradient.max() * 255).astype(np.uint8)
result = Image.fromarray(gradient)
result.save('edge_sobel_' + output_path)
return result
高级滤镜效果
1 卡通效果滤镜
import cv2
def cartoon_filter(image_path, output_path):
"""卡通效果滤镜"""
# 读取图像
img = cv2.imread(image_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 1. 边缘检测
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
gray = cv2.medianBlur(gray, 5)
edges = cv2.adaptiveThreshold(
gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY, 9, 9
)
# 2. 颜色量化
color = cv2.bilateralFilter(img, 9, 300, 300)
# 3. 组合边缘和颜色
cartoon = cv2.bitwise_and(color, color, mask=edges)
result = Image.fromarray(cartoon)
result.save(output_path)
return result
2 油画效果滤镜
def oil_painting_effect(image_path, output_path, radius=5, intensity=20):
"""油画效果滤镜"""
img = cv2.imread(image_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 使用OpenCV的油画效果函数
oil = cv2.xphoto.oilPainting(img, radius, intensity)
result = Image.fromarray(oil)
result.save(output_path)
return result
3 水彩效果滤镜
def watercolor_effect(image_path, output_path):
"""水彩效果滤镜"""
img = cv2.imread(image_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 1. 中值滤波去噪
filtered = cv2.medianBlur(img, 7)
# 2. 双边滤波保留边缘
filtered = cv2.bilateralFilter(filtered, 15, 75, 75)
# 3. 增加纹理效果
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
sharpened = cv2.filter2D(filtered, -1, kernel)
result = Image.fromarray(sharpened)
result.save(output_path)
return result
完整示例:照片滤镜应用
class PhotoFilter:
"""照片滤镜类"""
def __init__(self, image_path):
self.image_path = image_path
self.img = Image.open(image_path)
self.pixels = np.array(self.img)
def apply_filters(self, filters_dict, output_prefix="filtered"):
"""应用多个滤镜并保存"""
results = {}
for name, params in filters_dict.items():
if hasattr(self, f"_{name}_filter"):
method = getattr(self, f"_{name}_filter")
result = method(**params)
output_path = f"{output_prefix}_{name}.jpg"
result.save(output_path)
results[name] = output_path
return results
def _warm_filter(self, intensity=1.2):
"""暖色调滤镜"""
pixels = self.pixels.copy()
pixels[:,:,0] = np.clip(pixels[:,:,0] * intensity, 0, 255)
pixels[:,:,1] = np.clip(pixels[:,:,1] * (intensity - 0.1), 0, 255)
return Image.fromarray(pixels.astype(np.uint8))
def _cool_filter(self, intensity=1.2):
"""冷色调滤镜"""
pixels = self.pixels.copy()
pixels[:,:,2] = np.clip(pixels[:,:,2] * intensity, 0, 255)
return Image.fromarray(pixels.astype(np.uint8))
def _sepia_filter(self, depth=30):
"""棕褐色滤镜"""
pixels = self.pixels.copy()
r, g, b = pixels[:,:,0], pixels[:,:,1], pixels[:,:,2]
# 棕褐色转换
tr = 0.393 * r + 0.769 * g + 0.189 * b
tg = 0.349 * r + 0.686 * g + 0.168 * b
tb = 0.272 * r + 0.534 * g + 0.131 * b
pixels[:,:,0] = np.clip(tr + depth, 0, 255)
pixels[:,:,1] = np.clip(tg + depth/2, 0, 255)
pixels[:,:,2] = np.clip(tb, 0, 255)
return Image.fromarray(pixels.astype(np.uint8))
# 使用示例
if __name__ == "__main__":
# 初始化滤镜类
filter_app = PhotoFilter("input.jpg")
# 应用多种滤镜
filters = {
"warm": {"intensity": 1.3},
"cool": {"intensity": 1.4},
"sepia": {"depth": 40}
}
results = filter_app.apply_filters(filters)
print("生成的滤镜效果:", results)
实时滤镜(摄像头应用)
import cv2
def realtime_filter():
"""实时摄像头滤镜"""
cap = cv2.VideoCapture(0)
filters = {
'original': lambda img: img,
'gray': lambda img: cv2.cvtColor(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), cv2.COLOR_GRAY2BGR),
'edge': lambda img: cv2.cvtColor(cv2.Canny(img, 100, 200), cv2.COLOR_GRAY2BGR),
'blur': lambda img: cv2.GaussianBlur(img, (15, 15), 0)
}
current_filter = 'original'
while True:
ret, frame = cap.read()
if not ret:
break
# 应用滤镜
filtered = filters[current_filter](frame)
# 显示滤镜名称
cv2.putText(filtered, f"Filter: {current_filter}",
(10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
cv2.imshow('Camera Filter', filtered)
key = cv2.waitKey(1) & 0xFF
# 按键切换滤镜
if key == ord('q'):
break
elif key == ord('1'):
current_filter = 'original'
elif key == ord('2'):
current_filter = 'gray'
elif key == ord('3'):
current_filter = 'edge'
elif key == ord('4'):
current_filter = 'blur'
cap.release()
cv2.destroyAllWindows()
实用建议
- 性能优化:处理大图片时,先缩小尺寸再处理,然后恢复原大小
- 批处理:使用os模块遍历文件夹批量处理图片
- 参数调节:不同图片需要不同的参数设置,提供调节界面会更友好
- 保存原始:处理前先备份原始图片
这些案例涵盖了从基础到高级的图像滤镜实现,你可以根据需求选择使用。