第三章 实战准备:Python环境搭建与图像处理基础
说实话,每次带新人入门手机摄影算法,我最怕听到的就是「环境装好了,但跑不起来」。我自己也踩过不少坑,所以这一章咱们把基础打扎实。你想想看,如果连图像都读不进来、噪声都模拟不对,后面那些高级去噪算法根本没法验证。
3.1 Python环境搭建:三件套的安装
我个人习惯用 Anaconda 管理环境,省心。你直接用 pip 也行,但记得别把包装乱了。
# 创建一个干净的环境
conda create -n denoise python=3.9
conda activate denoise
# 安装核心三件套
pip install numpy==1.24.3
pip install opencv-python==4.8.0
pip install scikit-image==0.21.0
⚠️ 版本坑提醒: 我曾经因为 NumPy 版本太高,导致 OpenCV 的某些函数报错。建议锁定我上面给的版本号,兼容性最好。
为什么要这三样?
- NumPy:图像本质就是多维数组,没有它寸步难行
- OpenCV:读取、显示、基础处理,效率极高
- Scikit-image:算法丰富,PSNR/SSIM 直接调用,省得自己写
3.2 图像读取与显示:别被坑了
图像读取看似简单,其实暗藏玄机。OpenCV 默认读进来是 BGR 格式,而 Scikit-image 是 RGB。这个差异我当年调试了整整一个下午才发现。
import cv2
import matplotlib.pyplot as plt
from skimage import io
# OpenCV 读取(BGR)
img_cv = cv2.imread('photo.jpg')
print(f"OpenCV 读取形状: {img_cv.shape}") # (H, W, 3)
# Scikit-image 读取(RGB)
img_sk = io.imread('photo.jpg')
print(f"Scikit-image 读取形状: {img_sk.shape}")
# 正确显示:OpenCV 需要转换
img_rgb = cv2.cvtColor(img_cv, cv2.COLOR_BGR2RGB)
plt.imshow(img_rgb)
plt.title('正确显示')
plt.show()
💡 我的习惯: 统一用 Scikit-image 读取,省去颜色转换的麻烦。除非你需要用 OpenCV 的快速处理功能。
3.3 噪声模拟:造出真实感
做去噪算法,你得先有噪声数据。手机摄影中最常见的是高斯噪声和椒盐噪声。我在项目中遇到过一个问题:模拟的噪声太「干净」,导致算法在真实场景下表现很差。
import numpy as np
import cv2
def add_gaussian_noise(image, mean=0, sigma=25):
"""添加高斯噪声"""
noise = np.random.normal(mean, sigma, image.shape)
noisy = image + noise
return np.clip(noisy, 0, 255).astype(np.uint8)
def add_salt_pepper_noise(image, prob=0.02):
"""添加椒盐噪声"""
output = image.copy()
# 椒噪声(黑点)
salt_mask = np.random.random(image.shape[:2]) < prob/2
output[salt_mask] = 0
# 盐噪声(白点)
pepper_mask = np.random.random(image.shape[:2]) < prob/2
output[pepper_mask] = 255
return output
# 测试
img = cv2.imread('photo.jpg', cv2.IMREAD_GRAYSCALE)
noisy_gauss = add_gaussian_noise(img, sigma=30)
noisy_sp = add_salt_pepper_noise(img, prob=0.05)
关键参数说明:
sigma:高斯噪声的标准差,手机摄影中通常 10-50prob:椒盐噪声概率,0.01-0.05 比较真实- 记得
np.clip防止像素值溢出
3.4 评估指标:PSNR 和 SSIM
算法好不好,得用数据说话。PSNR 看像素级差异,SSIM 看结构相似度。我个人的经验是:PSNR 高不一定视觉好,但 SSIM 高通常意味着人眼看着舒服。
from skimage.metrics import peak_signal_noise_ratio as psnr
from skimage.metrics import structural_similarity as ssim
# 计算指标
psnr_value = psnr(img, noisy_gauss, data_range=255)
ssim_value = ssim(img, noisy_gauss, data_range=255)
print(f"PSNR: {psnr_value:.2f} dB")
print(f"SSIM: {ssim_value:.4f}")
# 批量评估
def evaluate_denoising(original, denoised):
psnr_val = psnr(original, denoised, data_range=255)
ssim_val = ssim(original, denoised, data_range=255)
return {'PSNR': psnr_val, 'SSIM': ssim_val}
| 指标 | 范围 | 含义 | 手机摄影参考值 |
|---|---|---|---|
| PSNR | 0~∞ dB | 像素级误差 | >30 dB 可接受,>40 dB 优秀 |
| SSIM | -1~1 | 结构相似度 | >0.9 视觉上几乎无差异 |
⚠️ 评估陷阱: 我曾经用 PSNR 优化算法,结果图像被过度平滑,细节全没了。记住:SSIM 更贴近人眼感知,两者要结合看。
3.5 知识体系总览
下面这张图是我自己整理的,把本章的核心逻辑串起来了。你照着这个流程走,基本不会出错。
3.6 完整实战脚本
最后,我把上面所有内容整合成一个脚本。你直接跑一遍,就能验证环境是否正常。
import numpy as np
import cv2
import matplotlib.pyplot as plt
from skimage import io
from skimage.metrics import peak_signal_noise_ratio as psnr
from skimage.metrics import structural_similarity as ssim
def main():
# 1. 读取图像
img = io.imread('test_photo.jpg')
print(f"原始图像: {img.shape}, 范围: {img.min()}-{img.max()}")
# 2. 添加噪声
noise = np.random.normal(0, 25, img.shape)
noisy = np.clip(img + noise, 0, 255).astype(np.uint8)
# 3. 评估
psnr_val = psnr(img, noisy, data_range=255)
ssim_val = ssim(img, noisy, data_range=255, channel_axis=-1)
print(f"PSNR: {psnr_val:.2f} dB")
print(f"SSIM: {ssim_val:.4f}")
# 4. 显示
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.imshow(img)
plt.title('原始图像')
plt.subplot(1, 2, 2)
plt.imshow(noisy)
plt.title(f'噪声图像 (PSNR={psnr_val:.1f}dB)')
plt.show()
if __name__ == '__main__':
main()
💡 调试技巧: 如果图像显示偏色,99% 是颜色通道顺序问题。用
cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 转换一下就好。
嗯,这一章的内容就这些。环境搭好了、图像能读了、噪声会模拟了、评估指标也掌握了——后面的去噪算法实战,你就能放开手脚去试了。
公众号:蓝海资料掘金营,微信deep3321