opencv-python图像增强十:图像高光去除

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一,简介

在图像中,高光区域指的是那些亮度极高、细节信息极少的区域,这些区域通常呈现出纯白色或接近白色。这是因为高光区域反射了大部分入射光,使得图像传感器捕捉到的信息非常有限。高光区域可能是由多种因素引起的:

  1. 直接反射:当光线直接照射到物体表面时,如果物体表面非常光滑或有反光材料,光线会被直接反射,形成高光。
  2. 强光照射:当物体处于强烈的光照下,尤其是当光源非常接近物体时,物体表面的一部分区域会因为光线过于集中而形成高光。
  3. 镜面反射:当物体表面非常光滑,且光线从特定角度照射时,光线会形成镜面反射,形成一个明亮的高光点。

高光区域在图像中可能会导致图像质量下降,因为它们通常缺乏细节信息,而且可能与其他亮度较低的区域形成对比,导致视觉上的不适。为了改善图像质量,恢复被高光掩盖的细节信息,在图像处理中通常会处理高光区域。在本文中介绍一种基于连通域分析与图像修复的opencv图像高光去除方法:

二,方案简述:

首先通过图像二值化定位过亮区域,这一步骤将图像转换为黑白二值图像,其中高光区域通常表现为白色。接着,使用连通域分析确定这些高光区域,这一分析方法将图像中的像素分为不同的连通区域,从而识别出高光区域。最后,进行图像修复,以恢复被高光区域遮挡的细节信息,提高图像的整体质量。

三,算法实现步骤:

3.1 定位高光区域并生成蒙版

在进行图像处理时,首先将彩色图像转换为灰度图像以简化处理。然后,应用高斯模糊滤波器平滑图像并减少噪声。接着,通过阈值处理将图像转换为二值图像,其中高于阈值的像素被设为白色。为了进一步去除噪声和细化边缘,对二值图像进行腐蚀操作,随后通过膨胀操作扩大高亮区域。连通组件分析用于识别图像中的不同区域,并创建一个与处理后图像大小相同的掩码,初始化为0。遍历分析得到的标签图像,构建包含每个标签的掩码,并计算非零像素数量。如果连通组件的像素数量大于300,则将其添加到最终掩码中。最终,返回的掩码只包含图像中较大的连通组件,可用于进一步的图像分析或处理。连通域分析的函数为cv2.connectedComponentsWithStats()

函数介绍:
cv2.connectedComponentsWithStats 是 OpenCV 中的一个函数,用于对二值图像进行连通组件分析,并返回每个连通组件的标签、位置、大小等信息。该函数广泛应用于图像分割、目标检测、形状分析等任务。
输入:
● binary_image: 一个二值图像,通常是通过阈值处理得到的,其中非零像素表示前景,零像素表示背景。
● connectivity: 邻域连接性,可以是 4 或 8。4 表示仅考虑水平和垂直方向上的相邻像素,8 表示考虑水平和垂直方向以及四个对角线方向上的相邻像素。
输出:
● num_labels: 图像中连通组件的数量。
● labels: 每个像素的标签,表示该像素属于哪个连通组件。
● stats: 每个连通组件的统计信息,包括面积、边界框的位置和大小等。
● centroids: 每个连通组件的中心坐标

代码案例:

def create_mask(image):
    # 定义一个函数 create_mask,接受一个名为 image 的参数,该参数是一个 OpenCV 图像对象。

    # 将输入的彩色图像转换为灰度图像
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 对灰度图像应用高斯模糊滤波器
    blurred = cv2.GaussianBlur(gray, (9,9), 0)

    # 对模糊后的图像应用阈值处理,将其转换为二值图像
    _, thresh_img = cv2.threshold(blurred, 230, 255, cv2.THRESH_BINARY)
    kernel = np.ones((3, 3), dtype=np.uint8)
    # 对二值图像应用腐蚀操作,去除噪声
    thresh_img = cv2.erode(thresh_img,kernel, iterations=2)

    # 对腐蚀后的图像应用膨胀操作,扩大高亮区域
    thresh_img = cv2.dilate(thresh_img, kernel,iterations=4)

    # 对阈值处理后的图像进行连通组件分析
    num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh_img, connectivity=8)
    # 创建一个与阈值处理后的图像大小相同的掩码,所有像素初始化为0
    mask = np.zeros(thresh_img.shape, dtype="uint8")

    # 遍历连通组件分析得到的标签图像中的所有唯一标签
    for label in np.unique(labels):
        # 如果标签是背景标签(通常为0),则忽略它
        if label == 0:
            continue
        # 否则,构建包含当前标签的掩码,并计算掩码中非零像素的数量
        labelMask = np.zeros(thresh_img.shape, dtype="uint8")
        labelMask[labels == label] = 255
        # 显示当前标签的掩码
        numPixels = cv2.countNonZero(labelMask)  # 计算掩码中非零像素的数量
        # 如果连通组件中的像素数量足够大,则将其添加到我们的掩码中
        if numPixels > 300:
            cv2.imshow("mask", labelMask)
            mask = cv2.add(mask, labelMask)  # 将当前标签的掩码与之前创建的掩码相加
    return mask  # 返回最终的掩码

3.2 图像高光区域修复

在获取到图像的高光区域后,下一步就是对图像的高光区域进行修复,opencv提供了一个图像修复的函数cv2.inpaint。函数介绍:
cv2.inpaint 是 OpenCV 中的一个函数,用于在图像中填充遮挡区域。这个函数可以用于修复图像中的污点、划痕或其他类型的遮挡,从而恢复被遮挡部分的图像内容。

输入
● src: 输入的图像,这是您想要修复的图像。
● inpaintMask: 输入的掩码,该掩码标记了需要修复的区域。如果掩码中的像素值为255,则对应的图像像素将被修复;如果掩码中的像素值为0,则对应的图像像素将被保留不变。
● inpaintRadius: 修复的半径,这个参数定义了修复区域的大小。较大的半径可以更好地修复遮挡区域,但可能会影响周围像素。
● flags: 用于指定修复算法。cv2.INPAINT_TELEA 和 cv2.INPAINT_NS 是两种常见的修复算法。cv2.INPAINT_TELEA 是基于偏微分方程的算法,适用于较小的修复区域;cv2.INPAINT_NS 是基于非结构化稀疏样本的算法,适用于较大的修复区域。
输出
● inpainted_image: 返回一个修复后的图像,该图像包含遮挡区域的修复内容。

函数使用:

inpainted_image = cv2.inpaint(img, mask, 10, cv2.INPAINT_TELEA)

四,整体代码实现

代码如下(示例):

import cv2
import numpy as np


def create_mask(image):
    # 定义一个函数 create_mask,接受一个名为 image 的参数,该参数是一个 OpenCV 图像对象。

    # 将输入的彩色图像转换为灰度图像
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 对灰度图像应用高斯模糊滤波器
    blurred = cv2.GaussianBlur(gray, (9,9), 0)

    # 对模糊后的图像应用阈值处理,将其转换为二值图像
    _, thresh_img = cv2.threshold(blurred, 230, 255, cv2.THRESH_BINARY)
    kernel = np.ones((3, 3), dtype=np.uint8)
    # 对二值图像应用腐蚀操作,去除噪声
    thresh_img = cv2.erode(thresh_img,kernel, iterations=2)

    # 对腐蚀后的图像应用膨胀操作,扩大高亮区域
    thresh_img = cv2.dilate(thresh_img, kernel,iterations=4)

    # 对阈值处理后的图像进行连通组件分析
    num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh_img, connectivity=8)

    # 创建一个与阈值处理后的图像大小相同的掩码,所有像素初始化为0
    mask = np.zeros(thresh_img.shape, dtype="uint8")

    # 遍历连通组件分析得到的标签图像中的所有唯一标签
    for label in np.unique(labels):
        # 如果标签是背景标签(通常为0),则忽略它
        if label == 0:
            continue
        # 否则,构建包含当前标签的掩码,并计算掩码中非零像素的数量
        labelMask = np.zeros(thresh_img.shape, dtype="uint8")
        labelMask[labels == label] = 255
        # 显示当前标签的掩码
        numPixels = cv2.countNonZero(labelMask)  # 计算掩码中非零像素的数量
        # 如果连通组件中的像素数量足够大,则将其添加到我们的掩码中
        if numPixels > 300:
            cv2.imshow("mask", labelMask)
            mask = cv2.add(mask, labelMask)  # 将当前标签的掩码与之前创建的掩码相加
    return mask  # 返回最终的掩码


img = cv2.imread(r"F:\traditional_vison\1724045476967.png")
mask = create_mask(img)
inpainted_image = cv2.inpaint(img, mask, 10, cv2.INPAINT_TELEA)
cv2.imshow("mask2",inpainted_image)
cv2.waitKey(0)

五,效果:

高光图像:
在这里插入图片描述
高光区域:在这里插入图片描述

修正后的图像:
在这里插入图片描述

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值