我来为您提供几个批量图像去噪的Python案例,从简单到高级的实现方法。

基础实现:使用OpenCV的均值滤波
import cv2
import os
import glob
import numpy as np
from tqdm import tqdm
def batch_denoise_mean(input_dir, output_dir, kernel_size=3):
"""
使用均值滤波批量去噪
"""
# 创建输出目录
os.makedirs(output_dir, exist_ok=True)
# 获取所有图片文件
image_extensions = ['*.jpg', '*.jpeg', '*.png', '*.bmp', '*.tiff']
image_files = []
for ext in image_extensions:
image_files.extend(glob.glob(os.path.join(input_dir, ext)))
print(f"找到 {len(image_files)} 张图片")
for img_path in tqdm(image_files, desc="处理中"):
# 读取图像
img = cv2.imread(img_path)
if img is None:
print(f"无法读取: {img_path}")
continue
# 应用均值滤波
denoised = cv2.blur(img, (kernel_size, kernel_size))
# 保存结果
filename = os.path.basename(img_path)
output_path = os.path.join(output_dir, f"denoised_{filename}")
cv2.imwrite(output_path, denoised)
print("批量去噪完成!")
# 使用示例
# batch_denoise_mean('input_images/', 'output_images/', kernel_size=5)
使用多种去噪方法的完整实现
import cv2
import os
import numpy as np
from glob import glob
from tqdm import tqdm
import matplotlib.pyplot as plt
class ImageDenoiser:
"""图像去噪器类"""
def __init__(self):
self.methods = {
'mean': self.mean_filter,
'median': self.median_filter,
'gaussian': self.gaussian_filter,
'bilateral': self.bilateral_filter,
'nlm': self.nlm_denoise
}
def mean_filter(self, img, kernel_size=3):
"""均值滤波"""
return cv2.blur(img, (kernel_size, kernel_size))
def median_filter(self, img, kernel_size=3):
"""中值滤波"""
return cv2.medianBlur(img, kernel_size)
def gaussian_filter(self, img, kernel_size=3, sigma=0):
"""高斯滤波"""
return cv2.GaussianBlur(img, (kernel_size, kernel_size), sigma)
def bilateral_filter(self, img, d=9, sigma_color=75, sigma_space=75):
"""双边滤波"""
return cv2.bilateralFilter(img, d, sigma_color, sigma_space)
def nlm_denoise(self, img, h=10, template_window_size=7, search_window_size=21):
"""非局部均值去噪"""
if len(img.shape) == 3:
return cv2.fastNlMeansDenoisingColored(
img, None, h, h,
template_window_size, search_window_size
)
else:
return cv2.fastNlMeansDenoising(
img, None, h,
template_window_size, search_window_size
)
def batch_denoise(self, input_dir, output_dir, method='nlm', **kwargs):
"""
批量去噪主函数
"""
os.makedirs(output_dir, exist_ok=True)
# 获取图片文件
image_files = []
for ext in ['*.jpg', '*.jpeg', '*.png', '*.bmp']:
image_files.extend(glob(os.path.join(input_dir, ext)))
if not image_files:
print(f"在 {input_dir} 中没有找到图片文件")
return
print(f"找到 {len(image_files)} 张图片,使用 {method} 方法去噪")
# 统计信息
results = []
for img_path in tqdm(image_files, desc="处理进度"):
try:
# 读取图像
img = cv2.imread(img_path)
if img is None:
continue
# 获取去噪方法
denoise_func = self.methods.get(method)
if denoise_func is None:
print(f"不支持的方法: {method}")
return
# 执行去噪
denoised_img = denoise_func(img, **kwargs)
# 保存结果
filename = os.path.basename(img_path)
name, ext = os.path.splitext(filename)
output_path = os.path.join(output_dir, f"{name}_{method}{ext}")
cv2.imwrite(output_path, denoised_img)
# 记录结果
results.append({
'filename': filename,
'input_shape': img.shape,
'method': method
})
except Exception as e:
print(f"处理 {img_path} 时出错: {str(e)}")
# 打印统计信息
print(f"\n处理完成!成功处理 {len(results)} 张图片")
print(f"结果保存在: {output_dir}")
return results
# 使用示例
if __name__ == "__main__":
denoiser = ImageDenoiser()
# 1. 使用NLM方法去噪
results = denoiser.batch_denoise(
input_dir='input_images/',
output_dir='output_images/nlm/',
method='nlm',
h=15
)
# 2. 使用中值滤波
results = denoiser.batch_denoise(
input_dir='input_images/',
output_dir='output_images/median/',
method='median',
kernel_size=5
)
高级实现:自适应去噪 + 质量评估
import cv2
import os
import numpy as np
from glob import glob
from tqdm import tqdm
from skimage import metrics
from concurrent.futures import ThreadPoolExecutor
import json
class AdvancedImageDenoiser:
"""高级图像去噪器"""
def __init__(self, num_threads=4):
self.num_threads = num_threads
def estimate_noise_level(self, img):
"""估计噪声水平"""
if len(img.shape) == 3:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:
gray = img
# 使用拉普拉斯算子估计噪声
laplacian = cv2.Laplacian(gray, cv2.CV_64F)
noise_level = np.std(laplacian)
return noise_level
def adaptive_denoise(self, img):
"""自适应去噪"""
noise_level = self.estimate_noise_level(img)
if noise_level < 10:
# 低噪声,轻微处理
return cv2.GaussianBlur(img, (3, 3), 0.5)
elif noise_level < 30:
# 中等噪声
return cv2.fastNlMeansDenoisingColored(
img, None, 10, 10, 7, 21
)
else:
# 高噪声,强力去噪
denoised = cv2.medianBlur(img, 5)
return cv2.fastNlMeansDenoisingColored(
denoised, None, 15, 15, 7, 21
)
def calculate_psnr(self, img1, img2):
"""计算PSNR"""
return metrics.peak_signal_noise_ratio(img1, img2)
def calculate_ssim(self, img1, img2):
"""计算SSIM"""
if len(img1.shape) == 3:
img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
return metrics.structural_similarity(img1, img2)
def process_single_image(self, img_path, output_dir):
"""处理单张图片"""
try:
# 读取图像
img = cv2.imread(img_path)
if img is None:
return None
# 自适应去噪
denoised = self.adaptive_denoise(img)
# 计算质量指标
psnr = self.calculate_psnr(img, denoised)
ssim = self.calculate_ssim(img, denoised)
noise_level = self.estimate_noise_level(img)
# 保存结果
filename = os.path.basename(img_path)
name, ext = os.path.splitext(filename)
output_path = os.path.join(output_dir, f"{name}_denoised{ext}")
cv2.imwrite(output_path, denoised)
return {
'filename': filename,
'input_shape': img.shape,
'noise_level': noise_level,
'psnr': psnr,
'ssim': ssim,
'output_path': output_path
}
except Exception as e:
print(f"处理 {img_path} 时出错: {str(e)}")
return None
def batch_denoise_advanced(self, input_dir, output_dir, save_metadata=True):
"""
批量去噪(高级版)
"""
os.makedirs(output_dir, exist_ok=True)
# 获取图片文件
image_files = []
for ext in ['*.jpg', '*.jpeg', '*.png', '*.bmp']:
image_files.extend(glob(os.path.join(input_dir, ext)))
if not image_files:
print(f"在 {input_dir} 中没有找到图片文件")
return
print(f"找到 {len(image_files)} 张图片,开始批量去噪...")
# 多线程处理
all_results = []
with ThreadPoolExecutor(max_workers=self.num_threads) as executor:
futures = []
for img_path in image_files:
future = executor.submit(
self.process_single_image,
img_path,
output_dir
)
futures.append(future)
# 显示进度
for future in tqdm(futures, desc="处理进度"):
result = future.result()
if result:
all_results.append(result)
# 统计信息
if all_results:
avg_noise = np.mean([r['noise_level'] for r in all_results])
avg_psnr = np.mean([r['psnr'] for r in all_results])
avg_ssim = np.mean([r['ssim'] for r in all_results])
print(f"\n处理完成!")
print(f"成功处理 {len(all_results)}/{len(image_files)} 张图片")
print(f"平均噪声水平: {avg_noise:.2f}")
print(f"平均PSNR: {avg_psnr:.2f} dB")
print(f"平均SSIM: {avg_ssim:.4f}")
# 保存元数据
if save_metadata:
metadata_path = os.path.join(output_dir, 'metadata.json')
with open(metadata_path, 'w', encoding='utf-8') as f:
json.dump({
'total_processed': len(all_results),
'total_files': len(image_files),
'average_metrics': {
'noise_level': float(avg_noise),
'psnr': float(avg_psnr),
'ssim': float(avg_ssim)
},
'results': all_results
}, f, indent=2, ensure_ascii=False)
print(f"元数据已保存至: {metadata_path}")
return all_results
def create_comparison_collage(self, input_dir, output_dir, num_samples=9):
"""
创建对比图拼贴
"""
# 获取图片文件
image_files = glob(os.path.join(input_dir, '*'))
selected_files = image_files[:num_samples]
if not selected_files:
return
n_cols = 3
n_rows = (len(selected_files) + n_cols - 1) // n_cols
fig, axes = plt.subplots(n_rows, n_cols * 2, figsize=(15, 5 * n_rows))
axes = axes.flatten()
for i, img_path in enumerate(selected_files):
# 原图
img = cv2.imread(img_path)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 去噪后
denoised = self.adaptive_denoise(img)
denoised_rgb = cv2.cvtColor(denoised, cv2.COLOR_BGR2RGB)
# 显示原图
axes[2*i].imshow(img_rgb)
axes[2*i].set_title(f'原图 {i+1}')
axes[2*i].axis('off')
# 显示去噪后
axes[2*i+1].imshow(denoised_rgb)
axes[2*i+1].set_title(f'去噪后 {i+1}')
axes[2*i+1].axis('off')
plt.tight_layout()
plt.savefig(os.path.join(output_dir, 'comparison_collage.png'), dpi=150)
plt.close()
print(f"对比图已保存至: {os.path.join(output_dir, 'comparison_collage.png')}")
# 使用示例
if __name__ == "__main__":
# 创建高级去噪器
denoiser = AdvancedImageDenoiser(num_threads=4)
# 批量去噪
results = denoiser.batch_denoise_advanced(
input_dir='input_images/',
output_dir='output_images/advanced/',
save_metadata=True
)
# 创建对比图
denoiser.create_comparison_collage(
input_dir='input_images/',
output_dir='output_images/advanced/',
num_samples=6
)
带GUI的批量去噪工具
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import cv2
import os
from threading import Thread
class DenoiseApp:
"""批量去噪GUI应用"""
def __init__(self, root):
self.root = root
self.root.title("批量图像去噪工具")
self.root.geometry("600x500")
# 变量
self.input_dir = tk.StringVar()
self.output_dir = tk.StringVar()
self.method = tk.StringVar(value="nlm")
self.kernel_size = tk.IntVar(value=3)
self.progress = tk.DoubleVar()
self.setup_ui()
def setup_ui(self):
"""设置UI界面"""
# 主框架
main_frame = ttk.Frame(self.root, padding="10")
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# 输入目录
ttk.Label(main_frame, text="输入目录:").grid(row=0, column=0, sticky=tk.W, pady=5)
ttk.Entry(main_frame, textvariable=self.input_dir, width=50).grid(row=0, column=1, padx=5)
ttk.Button(main_frame, text="浏览...", command=self.browse_input).grid(row=0, column=2)
# 输出目录
ttk.Label(main_frame, text="输出目录:").grid(row=1, column=0, sticky=tk.W, pady=5)
ttk.Entry(main_frame, textvariable=self.output_dir, width=50).grid(row=1, column=1, padx=5)
ttk.Button(main_frame, text="浏览...", command=self.browse_output).grid(row=1, column=2)
# 去噪方法
ttk.Label(main_frame, text="去噪方法:").grid(row=2, column=0, sticky=tk.W, pady=5)
methods = ['mean', 'median', 'gaussian', 'bilateral', 'nlm']
method_combo = ttk.Combobox(main_frame, textvariable=self.method, values=methods)
method_combo.grid(row=2, column=1, sticky=tk.W, padx=5)
# 核大小
ttk.Label(main_frame, text="核大小:").grid(row=3, column=0, sticky=tk.W, pady=5)
ttk.Spinbox(main_frame, from_=3, to=15, increment=2,
textvariable=self.kernel_size, width=10).grid(row=3, column=1, sticky=tk.W, padx=5)
# 进度条
self.progress_bar = ttk.Progressbar(main_frame, variable=self.progress,
maximum=100, length=400)
self.progress_bar.grid(row=4, column=0, columnspan=3, pady=20)
# 状态标签
self.status_label = ttk.Label(main_frame, text="就绪")
self.status_label.grid(row=5, column=0, columnspan=3)
# 处理按钮
ttk.Button(main_frame, text="开始处理", command=self.start_processing).grid(row=6, column=1, pady=20)
def browse_input(self):
"""浏览输入目录"""
directory = filedialog.askdirectory()
if directory:
self.input_dir.set(directory)
def browse_output(self):
"""浏览输出目录"""
directory = filedialog.askdirectory()
if directory:
self.output_dir.set(directory)
def start_processing(self):
"""开始处理"""
if not self.input_dir.get() or not self.output_dir.get():
messagebox.showerror("错误", "请选择输入和输出目录")
return
# 在新线程中处理
thread = Thread(target=self.process_images)
thread.daemon = True
thread.start()
def process_images(self):
"""处理图像"""
try:
denoiser = ImageDenoiser()
input_dir = self.input_dir.get()
output_dir = self.output_dir.get()
# 获取图片文件
image_files = []
for ext in ['*.jpg', '*.jpeg', '*.png', '*.bmp']:
image_files.extend(glob(os.path.join(input_dir, ext)))
if not image_files:
self.root.after(0, lambda: messagebox.showwarning("警告", "没有找到图片文件"))
return
os.makedirs(output_dir, exist_ok=True)
for i, img_path in enumerate(image_files):
# 更新进度
progress = (i + 1) / len(image_files) * 100
self.root.after(0, lambda v=progress: self.progress.set(v))
self.root.after(0, lambda i=i, total=len(image_files):
self.status_label.config(text=f"处理中: {i+1}/{total}"))
# 处理图像
img = cv2.imread(img_path)
if img is None:
continue
# 获取去噪方法
method = self.method.get()
if method == 'mean':
denoised = cv2.blur(img, (self.kernel_size.get(), self.kernel_size.get()))
elif method == 'median':
denoised = cv2.medianBlur(img, self.kernel_size.get())
elif method == 'gaussian':
denoised = cv2.GaussianBlur(img, (self.kernel_size.get(), self.kernel_size.get()), 0)
elif method == 'bilateral':
denoised = cv2.bilateralFilter(img, 9, 75, 75)
else: # nlm
denoised = cv2.fastNlMeansDenoisingColored(img, None, 10, 10, 7, 21)
# 保存结果
filename = os.path.basename(img_path)
output_path = os.path.join(output_dir, f"denoised_{filename}")
cv2.imwrite(output_path, denoised)
# 处理完成
self.root.after(0, lambda: self.progress.set(100))
self.root.after(0, lambda: self.status_label.config(text="处理完成!"))
self.root.after(0, lambda: messagebox.showinfo("完成", "批量去噪处理完成!"))
except Exception as e:
self.root.after(0, lambda: messagebox.showerror("错误", str(e)))
self.root.after(0, lambda: self.status_label.config(text="处理出错"))
# 运行GUI应用
if __name__ == "__main__":
root = tk.Tk()
app = DenoiseApp(root)
root.mainloop()
使用方法
- 简单使用:
# 安装依赖 pip install opencv-python numpy tqdm scikit-image
运行基本去噪
denoiser = ImageDenoiser() results = denoiser.batch_denoise('input/', 'output/', method='nlm')
2. **高级使用**:
```python
# 自适应去噪 + 质量评估
denoiser = AdvancedImageDenoiser()
results = denoiser.batch_denoise_advanced('input/', 'output/')
- GUI工具:
# 运行图形界面 python denoise_gui.py
这些实现涵盖了从基础到高级的批量图像去噪方案,可以根据具体需求选择合适的实现。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播