openISP学习12-EE — Edge Enhancement(边缘增强)

文章目录

这里的边缘检测算子采用的类拉普拉斯算子的变种, 关于拉普拉斯算子,我们再前面数字图像处理中已经有介绍过了.它的原理就是判单当前像素和周围像素(3x3)加权就和的平均值.下面详细介绍一下

1.算法原理

边缘增强通过提取图像中的边缘响应,并将其叠加到原始图像上,使边缘更加清晰锐利。我们主要从下面几点来说一下.

处理流程

复制代码
原图 → 边缘滤波器 → 边缘图(edgemap) → 非线性增益 → 叠加到原图

边缘滤波器

使用 3×5 的滤波器(可配置),默认为类拉普拉斯算子,根据这个算子,可求出当前像素和3x5邻域内像素的加权平均值,正常非边缘地带,得到的是0,而当像素剧烈变化时(这个剧烈到何种程度我们可以自定义阈值),即边缘地带, 加权求和平均值不为0,

复制代码
edge_filter = [[-1, 0, -1, 0, -1],
               [-1, 0,  8, 0, -1],
               [-1, 0, -1, 0, -1]]

edgemap[y,x] = Σ(img × edge_filter) / 8

非线性增益函数(emlut)

使用双阈值非线性映射,抑制弱噪声,增强强边缘, 需要结合后面的测试代码一起理解一下.

这里用户判断当前的map值是否在自定义的阈值范围(即差值在一定范围认为是边缘,否则为0).如果是边缘的话,会对边缘乘一个系数,以加强边缘.

复制代码
val < -thres[1]           → gain[1] × val   (强负边缘,大增益)
-thres[1] ≤ val ≤ -thres[0] → 0             (弱负响应,抑制)
-thres[0] < val < thres[0]  → gain[0] × val  (微弱,小增益)
thres[0] ≤ val ≤ thres[1]  → 0             (弱正响应,抑制)
val > thres[1]             → gain[1] × val  (强正边缘,大增益)

2.算法核心算法

  • 关键参数
    这个在下面测试代码中,默认定义的有参数.
参数 说明 典型值
edge_filter 3×5 边缘提取核 类拉普拉斯
gain[0] 弱边缘增益(/256) 32
gain[1] 强边缘增益(/256) 128
thres[0] 弱边缘阈值 32
thres[1] 强边缘阈值 64
emclip 增益量 clip 范围 -64, 64
  • 最终输出
    原图加上边缘的信息,能够在图像中看到边缘信息.

    ee_output[y,x] = original[y,x] + emlut(edgemap[y,x])

  • 核心代码

python 复制代码
class EE:
    'Edge Enhancement'

    def __init__(self, img, edge_filter, gain, thres, emclip):
        self.img = img
        self.edge_filter = edge_filter
        self.gain = gain
        self.thres = thres
        self.emclip = emclip

	# 为了方便后续卷积,对图像进行填边操作
    def padding(self):
        img_pad = np.pad(self.img, ((1, 1), (2, 2)), 'reflect')
        return img_pad
	# 放置图像像素溢出,像素在(0,255)之间
    def clipping(self):
        np.clip(self.img, 0, 255, out=self.img)
        return self.img

    def emlut(self, val, thres, gain, clip):
        lut = 0
        if val < -thres[1]: # 根据拉普拉斯算子看,此种情况是当前像素值比周围像素暗
            lut = gain[1] * val
        elif val < -thres[0] and val > -thres[1]:
            lut = 0
        elif val < thres[0] and val > -thres[1]:
            lut = gain[0] * val
        # 根据拉普拉斯算子看,此种情况是当前像素值比周围像素亮,但不多
        elif val > thres[0] and val < thres[1]: 
            lut = 0
        # 根据拉普拉斯算子看,此种情况是当前像素值比周围像素亮很多
        elif val > thres[1]:
            lut = gain[1] * val
        # np.clip(lut, clip[0], clip[1], out=lut)
        lut = max(clip[0], min(lut / 256, clip[1]))
        return lut

    def execute(self):
        img_pad = self.padding()
        img_h = self.img.shape[0]
        img_w = self.img.shape[1]
        ee_img = np.empty((img_h, img_w), np.int16)
        em_img = np.empty((img_h, img_w), np.int16)
        for y in range(img_pad.shape[0] - 2):
            for x in range(img_pad.shape[1] - 4):
            	#对当前像素做卷积,求和,平均
                em_img[y,x] = np.sum(np.multiply(img_pad[y:y+3, x:x+5], self.edge_filter[:, :])) / 8
                # 原图+边缘信息,即边缘加强后的图像
                ee_img[y,x] = img_pad[y+1,x+2] + self.emlut(em_img[y,x], self.thres, self.gain, self.emclip)
        self.img = ee_img
        return self.clipping(), em_img

3.测试代码

python 复制代码
    def _default_params(self):
        edge_filter = np.array([
            [-1, 0, -1, 0, -1],
            [-1, 0,  8, 0, -1],
            [-1, 0, -1, 0, -1],
        ], dtype=float)
        gain   = [32, 128]
        thres  = [32, 64] # 在这个范围内的<-64,以及>64都认为是边缘上的点
        emclip = [-64, 64]
        return edge_filter, gain, thres, emclip
    def test_step_edge_nonzero_response(self):
        """
        包含阶跃边缘的图像(左半 20,右半 100),
        边界附近的 edgemap 应有非零响应。
        """
		# 生成一个16x20的的图像,左边10列为深灰色,右边10列为灰色
        img = np.zeros((16, 20), dtype=np.int16)
        img[:, :10] = 20
        img[:, 10:] = 100
        edge_filter, gain, thres, emclip = self._default_params()
        ee = EE(img.copy(), edge_filter, gain, thres, emclip)
        ee_out, em_out = ee.execute()
        show_gray_images(img, em_out,"left", "right-edgemap")
        show_gray_images(img, ee_out,"left", "right-edgemap+img")
        print(f"em_out2:{em_out}")
  • degeMap显示效果
    显示degeMap效果,这里中间能看到有一个不一样的带装图像

    实际的边缘map信息edegeMap矩阵如下所示

    [[ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0 -30 -30 30 30 0 0 0 0 0 0 0 0]]

  • edgeMap+原图
    叠加后能看到边缘加强

相关推荐
Litluecat1 小时前
配合多角色提示语4,学习AI漫剧(刚开始学)
人工智能·学习·计算机视觉
qq_8573058192 小时前
OpenCV入门
人工智能·opencv·计算机视觉
小白狮ww2 小时前
3B 参数,毫秒级响应:LocateAnything 如何重新定义开放世界目标检测
人工智能·目标检测·计算机视觉·视觉检测·大语言模型·nvidia·locateanything
Jasonakeke2 小时前
CLion + OpenCV + Utf8 终极解决方案
人工智能·opencv·计算机视觉
叫我:松哥2 小时前
基于深度学习的辣椒叶片病害识别系统设计实现,融合CBAM注意力机制的改进ResNet-50模型和YOLO检测,准确率达96%
图像处理·人工智能·深度学习·yolo·flask·bootstrap·注意力机制
我不姓周不唱朋友3 小时前
讲讲ISP图像处理中的不适定性问题
图像处理
梦想三三3 小时前
基于 PyTorch 的食物图像分类CNN 训练全流程
人工智能·pytorch·计算机视觉·cnn
armwind3 小时前
openISP学习14-HSC — Hue/Saturation Control(色调/饱和度控制)
图像处理·计算机视觉
听我哔哔3 小时前
GPT-Image2生图能力解析:AI图像生成落地新范式
人工智能·计算机视觉