1. 基于对比度检测的静态场景自动对焦
任务目标
实现一个基于对比度检测的静态场景自动对焦评分算法:输入单帧灰度图像,输出一个表征图像清晰度的对焦评分(数值越大表示越清晰)。该评分可作为自动对焦搜索(如爬山法)的代价函数输入。
核心原理
采用修正拉普拉斯算子(Modified Laplacian, ML)计算对焦评分。相比普通拉普拉斯算子,ML分别计算x与y方向的二阶导数并取值求和,避免梯度方向相互抵消,对离焦模糊更敏感。对全图逐像素计算ML值后累加,得到最终评分。
关键完整代码
import numpy as np
from scipy import ndimage
def focus_score_ml(image_gray):
"""
基于修正拉普拉斯算子的对焦评分
参数:
image_gray: 2D numpy数组,dtype=uint8或float,灰度图
返回:
score: float,对焦评分(越大越清晰)
"""
if image_gray.ndim != 2:
raise ValueError("输入必须为单通道灰度图")
img = image_gray.astype(np.float32)
# 修正拉普拉斯:分别计算x和y方向的二阶导数
# 使用3x3核:[-1, 2, -1] 对应二阶差分
lap_x = ndimage.convolve1d(img, [-1, 2, -1], axis=1) # 沿x方向
lap_y = ndimage.convolve1d(img, [-1, 2, -1], axis=0) # 沿y方向
# 取值并求和
ml = np.abs(lap_x) + np.abs(lap_y)
# 累加得到评分
score = float(np.sum(ml))
return score
# 最小调用示例
if __name__ == "__main__":
# 生成一张模拟测试图:清晰图(高频细节)与模糊图(高斯平滑)
np.random.seed(42)
base = np.random.randint(0, 255, (64, 64), dtype=np.uint8)
# 添加棋盘格高频纹理
checker = (np.indices((64, 64)).sum(axis=0) % 2) * 200
sharp_img = np.clip(base.astype(np.int16) + checker.astype(np.int16), 0, 255).astype(np.uint8)
# 模糊图:高斯滤波模拟离焦
blurred_img = ndimage.gaussian_filter(sharp_img, sigma=2.0)
score_sharp = focus_score_ml(sharp_img)
score_blurred = focus_score_ml(blurred_img)
print(f"清晰图评分: {score_sharp:.1f}")
print(f"模糊图评分: {score_blurred:.1f}")
# 预期输出(确定性结果):
# 清晰图评分 > 模糊图评分(具体数值由输入决定,但大小关系确定)
运行与验证
- 依赖安装:
pip install numpy scipy - 运行方式:将上述代码保存为
focus_ml.py,执行python focus_ml.py - 通过条件:程序正常输出两个评分,且清晰图评分显著高于模糊图评分(通常高3倍以上)。若需验证真实图像,可替换
sharp_img为任意相机拍摄的静态灰度图(如cv2.imread(path, 0)),对同一场景拍摄多张不同离焦程度的照片,评分应随清晰度单调变化。
常见问题
- 输入为彩色图:需先转换为灰度图(如
cv2.cvtColor(img, cv2.COLOR_BGR2GRAY))。 - 噪声敏感:ML算子对噪声敏感,若图像噪声明显,可先做轻度高斯滤波(sigma≤1)再评分,但会略微降低对焦灵敏度。
- 评分尺度:评分值与图像尺寸和内容相关,仅用于同一镜头序列的相对比较,不可跨场景直接对比。