使用暗通道先验过滤雾天图像

引言

雾天图像由于能见度降低,往往会导致图像对比度较低,影响后续计算机视觉任务的效果。本文介绍一种基于暗通道先验的方法,通过计算图像的暗通道均值,快速判断图像是否为雾天。

暗通道先验的理论基础

暗通道先验由 He 等人在论文《Single Image Haze Removal Using Dark Channel Prior》中提出,其核心假设是:在无雾自然图像的大多数非天空区域,至少在一个颜色通道上,总会有一些像素值接近于零。因此,雾天图像的暗通道均值会显著高于无雾图像。

暗通道定义为:
J dark ( x ) = min ⁡ y ∈ Ω ( x ) ( min ⁡ c ∈ { r , g , b } J c ( y ) ) J_{\text{dark}}(x) = \min_{y\in\Omega(x)} \left(\min_{c \in \{r,g,b\}} J^c(y)\right) Jdark(x)=yΩ(x)min(c{r,g,b}minJc(y))

  • J ( x ) 是输入图像; J(x) 是输入图像; J(x)是输入图像;
  • Ω ( x ) 是以像素 x 为中心的局部窗口; \Omega(x) 是以像素 x 为中心的局部窗口; Ω(x)是以像素x为中心的局部窗口;
  • min ⁡ c ∈ { r , g , b } 是对 R / G / B 三个通道取最小值。 \min_{c \in \{r, g, b\}} 是对 R/G/B 三个通道取最小值。 minc{r,g,b}是对R/G/B三个通道取最小值。

代码实现

以下是基于暗通道先验判定雾天图像的主要实现步骤:
1. 计算暗通道
通过对图像的每个像素点,在局部窗口内取最小值,并在三个颜色通道上取最小值,得到暗通道图像。
2. Resize 提高效率
为了减少计算量,可以在计算暗通道之前对图像进行缩放。缩小图像分辨率不会显著影响暗通道的均值结果,但能显著提升计算效率。
3.判断雾天
通过统计暗通道的均值,设置阈值进行判定。当暗通道均值高于阈值时,认为是雾天图像。
以下是核心代码:

class FogDetector:
    def __init__(self, dark_channel_threshold=0.4, resize_factor=0.5):
        """
        初始化检测器
        :param dark_channel_threshold: 暗通道阈值,低于该值判定为无雾图像
        :param resize_factor: 缩放比例,用于降低图像分辨率以提升计算效率
        """
        self.dark_channel_threshold = dark_channel_threshold
        self.resize_factor = resize_factor

    def get_dark_channel(self, image, patch_size=15):
        """
        计算图像的暗通道
        :param image: 输入的 BGR 图像
        :param patch_size: 暗通道计算的窗口大小
        :return: 暗通道图
        """
        # 转换为浮点型,归一化到 [0,1]
        image = image.astype(np.float32) / 255.0

        # 获取最小通道
        min_channel = np.min(image, axis=2)

        # 使用最小滤波计算暗通道
        kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (patch_size, patch_size))
        dark_channel = cv2.erode(min_channel, kernel)

        return dark_channel

    def is_foggy(self, image_path):
        """
        判断图像是否有雾
        :param image_path: 图像路径
        :return: 如果图像有雾返回 True,无雾返回 False
        """
        # 读取图像
        image = cv2.imread(image_path)
        if image is None:
            print(f"无法读取图像: {image_path}")
            return True  # 默认有雾,丢弃图像

        # 缩放图像以提升计算效率
        new_width = int(image.shape[1] * self.resize_factor)
        new_height = int(image.shape[0] * self.resize_factor)
        resized_image = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_AREA)

        # 计算暗通道
        dark_channel = self.get_dark_channel(resized_image)

        # 统计暗通道的平均值
        dark_channel_mean = np.mean(dark_channel)

        # 打印调试信息
        print(f"暗通道均值: {dark_channel_mean} - 图像: {image_path}")

        # 判断是否有雾
        return dark_channel_mean > self.dark_channel_threshold

使用方式

假设我们有一个图像文件夹 your_image_folder,需要对其中的图像进行雾天检测:

fog_detector = FogDetector(dark_channel_threshold=0.4)

image_folder = "your_image_folder"
for image_name in os.listdir(image_folder):
    image_path = os.path.join(image_folder, image_name)
    if fog_detector.is_foggy(image_path):
        print(f"图像 {image_name} 为雾天图像")
    else:
        print(f"图像 {image_name} 为无雾图像")

参数说明

  • dark_channel_threshold:设置暗通道均值的阈值,越高越严格。
  • resize_factor:缩放比例,用于提高计算效率,设置为 0.5 表示将图像宽高各缩小一半。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值