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}")
    # 预期输出(确定性结果):
    # 清晰图评分 > 模糊图评分(具体数值由输入决定,但大小关系确定)

运行与验证

  1. 依赖安装:pip install numpy scipy
  2. 运行方式:将上述代码保存为 focus_ml.py,执行 python focus_ml.py
  3. 通过条件:程序正常输出两个评分,且清晰图评分显著高于模糊图评分(通常高3倍以上)。若需验证真实图像,可替换 sharp_img 为任意相机拍摄的静态灰度图(如 cv2.imread(path, 0)),对同一场景拍摄多张不同离焦程度的照片,评分应随清晰度单调变化。

常见问题

  • 输入为彩色图:需先转换为灰度图(如 cv2.cvtColor(img, cv2.COLOR_BGR2GRAY))。
  • 噪声敏感:ML算子对噪声敏感,若图像噪声明显,可先做轻度高斯滤波(sigma≤1)再评分,但会略微降低对焦灵敏度。
  • 评分尺度:评分值与图像尺寸和内容相关,仅用于同一镜头序列的相对比较,不可跨场景直接对比。