OpenCV实现以指定焦点为中心的渐进式模糊效果技术咨询
实现焦点渐进模糊的OpenCV思路
核心逻辑
要实现连续平滑的渐进模糊,核心是让每个像素的模糊程度与它到指定焦点的距离正相关,避免生硬的区域划分。通过生成多级模糊图像+平滑权重融合的方式,既能保证效率,又能实现无断层的模糊过渡。
具体步骤
- 计算距离映射:以焦点坐标为中心,计算图像每个像素到焦点的欧氏距离,再将距离归一化后映射到模糊核的尺寸范围(注意OpenCV高斯模糊核必须是奇数)。这里用平滑的线性映射,也可以根据需求调整映射曲线(比如平方曲线让模糊递增更快)。
- 生成多级模糊图:对原图做不同程度的高斯模糊,核大小从1(原图)到设定的最大核尺寸,步长为2(保证奇数),得到一组模糊程度依次递增的图像。
- 构建平滑权重图:根据每个像素的距离对应的核尺寸,计算它在相邻两级模糊图之间的权重比例,确保模糊过渡无断层。
- 融合模糊图像:按照权重图将多级模糊图像加权融合,得到最终的渐进模糊效果。
代码示例(Python + OpenCV)
import cv2 import numpy as np def progressive_blur(img, focus_x, focus_y, max_kernel_size=31): # 确保最大模糊核为奇数 if max_kernel_size % 2 == 0: max_kernel_size += 1 h, w = img.shape[:2] # 生成每个像素到焦点的欧氏距离图 y_grid, x_grid = np.mgrid[:h, :w] distances = np.sqrt((x_grid - focus_x)**2 + (y_grid - focus_y)**2) # 归一化距离并映射到模糊核的半长(核大小=2*k+1) max_dist = np.max(distances) normalized_dist = distances / max_dist k_values = normalized_dist * ((max_kernel_size - 1) // 2) # 生成不同模糊级别的图像 blur_imgs = [] kernel_sizes = range(1, max_kernel_size + 1, 2) for k in kernel_sizes: blur_imgs.append(cv2.GaussianBlur(img, (k, k), 0)) # 初始化结果图像 result = np.zeros_like(img, dtype=np.float32) # 融合相邻模糊级别 for i in range(len(kernel_sizes) - 1): current_k = (kernel_sizes[i] - 1) // 2 next_k = (kernel_sizes[i+1] - 1) // 2 # 筛选当前区间内的像素 mask = (k_values >= current_k) & (k_values < next_k) if not np.any(mask): continue # 计算融合权重 weight = (k_values[mask] - current_k) / (next_k - current_k) # 适配彩色图像的通道维度 if img.ndim == 3: weight = np.expand_dims(weight, axis=-1) # 加权融合 result[mask] = (1 - weight) * blur_imgs[i][mask] + weight * blur_imgs[i+1][mask] # 处理最大模糊级别的区域 mask = k_values >= ((max_kernel_size - 1) // 2) result[mask] = blur_imgs[-1][mask] return result.astype(np.uint8) # 测试用法 if __name__ == "__main__": img = cv2.imread("test.jpg") # 假设焦点在图像中心 focus_x = img.shape[1] // 2 focus_y = img.shape[0] // 2 blurred_img = progressive_blur(img, focus_x, focus_y, max_kernel_size=31) cv2.imwrite("progressive_blur.jpg", blurred_img)
优化建议
- 效率优化:如果处理大尺寸图像,可以先对图像降采样,处理后再升采样,减少计算量。
- 模糊类型调整:用
cv2.bilateralFilter代替高斯模糊,能在模糊的同时保留图像边缘,效果更自然。 - 映射曲线调整:修改距离到核尺寸的映射方式,比如用
k_values = np.square(normalized_dist) * ...让模糊递增速率先慢后快,或者用平方根曲线让速率先快后慢,适配不同视觉需求。
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

