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+原图
    叠加后能看到边缘加强

相关推荐
AI的探索之旅15 小时前
97 个 OpenCV 实例(三十):双目立体,从标定到点云
人工智能·opencv·计算机视觉
美狐美颜SDK开放平台15 小时前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
拉你进_教堂18 小时前
小龙虾技能之【Parkinson‘s & Epileptic Behavior Recognition Skill | 帕金森癫痫行为识别技能】简介
人工智能·计算机视觉·多模态大模型·openclaw小龙虾技能
PascalXie19 小时前
人形机器人的“眼睛“:多目视觉方案怎么选?
计算机视觉·机器人
普密斯科技19 小时前
替代传统影像仪,摄像头磨切片测量新方案实测
计算机视觉·集成测试·测量
YOLO数据集集合21 小时前
天空红外小目标检测数据集 | 红外小目标 天空目标检测 无人机检测 鸟类识别 低空安防9099期
人工智能·目标检测·计算机视觉·目标跟踪·无人机·无人机视角·直升机检测
江屿风1 天前
【认识深度学习】【深度学习分类与计算机视觉任务要点解析】流食般投喂
大数据·人工智能·深度学习·计算机视觉·目标跟踪·自然语言处理·语音识别
kaixin_啊啊1 天前
Micam 多容器太吃资源?用 Go2RTC + EasyNVR 给小米摄像头换一套轻量本地录像方案
图像处理·人工智能·摄像头
浔溺1 天前
al+大数据每日学习笔记41
opencv·计算机视觉
美狐美颜SDK开放平台1 天前
直播APP源码与视频美颜sdk如何配合?一套完整开发思路
android·人工智能·计算机视觉·音视频·直播美颜sdk