专栏首页音视频技术学习笔记图像处理基础-USM锐化

图像处理基础-USM锐化

一、为什么要用USM锐化?

上一篇讲拉普拉斯锐化,不能提供精细的调整,在photoshop中采用USM(Unsharp mask)可以进一步优化。目的是:

  1. 可以微调锐化程度
  2. 设置锐化阈值,想针对边界更清晰的点锐化处理,这个清晰程度就是锐化阈值

二、USM锐化原理

第一步:对原图进行模糊,然后用原图 - 模糊图,得到一张差值,差值即像素颜色突变的点,即边界

第二步:原图 + 差值,即边界处得到增强

从信号处理的角度理解:

三、代码实现分析

  1. 定义强度amount[0, 100],处理到[0, 128]的范围,0-100对用户更好理解 amount = amount * 128 / 100;
  2. 对原图生成高斯模糊图 FastGaussFilter(gaussData, width, height, stride, radius);
  3. 遍历图片像素,生成一张遮罩pMask // 大于 阈值threshold pMask对应的点设置成128, 否则设置成0
for(j = 0; j < height; j++)
{
    for(i = 0; i < width; i++)
    {
        pMask[0] = abs(pSrc[0] - pDst[0]) < threshold ? 0 : 128;
        pMask[1] = abs(pSrc[1] - pDst[1]) < threshold ? 0 : 128;
        pMask[2] = abs(pSrc[2] - pDst[2]) < threshold ? 0 : 128;
        pDst += 4;
        pSrc += 4;
        pMask += 4;
    }
    pDst += offset;
    pSrc += offset;
    pMask += offset;
}
  1. 锐化增强 // 计算像素差 // 原图 + 像素差 * 系数 (amount决定),到这一步就能看到效果了 // 针对阈值做处理,根据前面生成的pMask遮罩,pMask[0|1|2] == 0则不增强,使用原像素pSrc[0|1|2] (注意 * 128 >> 7 == 1),pMask[0|1|2] == 128,则增强,采用rgb * pMask[0|1|2] >> 7,即rgb * 系数
for(j = 0; j < height; j++)
{
    for(i = 0; i < width; i++)
    {
        // 计算像素差
        b = pSrc[0] - pDst[0];
        g = pSrc[1] - pDst[1];
        r = pSrc[2] - pDst[2];

        // 原值 + 像素差 * 系数 (amount >> 7 == [0, 128]/128 == [0, 1.0])
        // 即得到 rgb = 原值 + 像素差 * [0, 1]
        b = (pSrc[0] + ((b * amount) >> 7));
        g = (pSrc[1] + ((g * amount) >> 7));
        r = (pSrc[2] + ((r * amount) >> 7));
        
        b = (b * pMask[0] + pSrc[0] * (128 - pMask[0])) >> 7;
        g = (g * pMask[1] + pSrc[1] * (128 - pMask[1])) >> 7;
        r = (r * pMask[2] + pSrc[2] * (128 - pMask[2])) >> 7;

        pSrc[0] = CLIP3(b, 0, 255);
        pSrc[1] = CLIP3(g, 0, 255);
        pSrc[2] = CLIP3(r, 0, 255);
        pSrc += 4;
        pDst += 4;
        pMask += 4;
    }
    pSrc += offset;
    pDst += offset;
    pMask += offset;
}

补充,在最后一步锐化处理前,对mask进行了一次高斯模糊,目的是将遮罩均匀到图像边缘,过渡更自然,“0” 和 “128”过于绝对,锐化的效果太尖锐,这里不明白的,参考下面完整代码

完整代码:

#include"f_USM.h"
#include"f_GaussFilter.h"
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<stdio.h>
#include"Commen.h"

int f_USM(unsigned char* srcData,int width, int height,int stride,int radius, int amount, int threshold)
{
    int ret = 0;
    if(radius == 0)
        return ret;
    radius = CLIP3(radius, 0, 100);
    amount = CLIP3(amount, 0,500);
    threshold = CLIP3(threshold, 0,255);
    unsigned char* gaussData = (unsigned char*)malloc(sizeof(unsigned char) * height * stride);
    memcpy(gaussData, srcData, sizeof(unsigned char) * height * stride);
    f_FastGaussFilter(gaussData, width, height, stride, radius);
    int i, j, r, g, b, offset;
    offset = stride - width * 4;

    // 将 amount 均匀到[0, 128] 的范围内,如果输入值是[0, 100]
    // 128有什么特殊的含义呢?128 = 256 / 2,即RGB色值的一半
    // 一半是锐化的临界点
    amount = amount * 128 / 100;
    unsigned char* pSrc = srcData;
    unsigned char* pDst = gaussData;
    unsigned char* maskData = (unsigned char*)malloc(sizeof(unsigned char) * height * stride);
    unsigned char* pMask = maskData;
    for(j = 0; j < height; j++)
    {
        for(i = 0; i < width; i++)
        {
            pMask[0] = abs(pSrc[0] - pDst[0]) < threshold ? 0 : 128;
            pMask[1] = abs(pSrc[1] - pDst[1]) < threshold ? 0 : 128;
            pMask[2] = abs(pSrc[2] - pDst[2]) < threshold ? 0 : 128;
            pDst += 4;
            pSrc += 4;
            pMask += 4;
        }
        pDst += offset;
        pSrc += offset;
        pMask += offset;
    }
    pDst = gaussData;
    pSrc = srcData;
    pMask = maskData;
    f_FastGaussFilter(maskData, width, height, stride, radius);
    for(j = 0; j < height; j++)
    {
        for(i = 0; i < width; i++)
        {
            // 计算像素差
            b = pSrc[0] - pDst[0];
            g = pSrc[1] - pDst[1];
            r = pSrc[2] - pDst[2];

            // 原值 + 像素差 * 系数 (amount >> 7 == [0, 128]/128 == [0, 1.0])
            // 即得到 rgb = 原值 + 像素差 * [0, 1]
            b = (pSrc[0] + ((b * amount) >> 7));
            g = (pSrc[1] + ((g * amount) >> 7));
            r = (pSrc[2] + ((r * amount) >> 7));
            
            
            b = (b * pMask[0] + pSrc[0] * (128 - pMask[0])) >> 7;
            g = (g * pMask[1] + pSrc[1] * (128 - pMask[1])) >> 7;
            r = (r * pMask[2] + pSrc[2] * (128 - pMask[2])) >> 7;

            pSrc[0] = CLIP3(b, 0, 255);
            pSrc[1] = CLIP3(g, 0, 255);
            pSrc[2] = CLIP3(r, 0, 255);
            pSrc += 4;
            pDst += 4;
            pMask += 4;
        }
        pSrc += offset;
        pDst += offset;
        pMask += offset;
    }
    free(gaussData);
    free(maskData);
    return ret;
};

参考:https://baijiahao.baidu.com/s?id=1651538317157891526&wfr=spider&for=pc

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 照片处理-阿宝色滤镜

    阿宝色是一位摄影师名为阿宝(网名:aibao),原名董立竑,由他在2008年左右所创的一种特别的色彩。这种色彩主要是,橘色的肤色和偏青色的背景色调为主,整体的视...

    sumsmile
  • 图像处理基础-图像边缘检测

    图像处理经常会用到这张赫赫有名的图片,这位lena女士的照片原本用在“花花公子”的杂志封面上,机缘巧合被当做测试素材,广泛用在图形处理领域。

    sumsmile
  • 照片处理-几何滤镜实现哈哈镜

    几何滤镜比较简单,不涉及色彩模型,按照某种算法,对原图进行采样,得到一张新的图片。看起来就像是把原图进行了几何变形。 这篇文章通过两个简单的案例,更直观的感受...

    sumsmile
  • Python实现的快速排序

    今天看了下《算法新解》这本书,很薄的一本书,最开始吸引我的有两点,一个是里面的大量的图,内容相对来说比较清新,第二个是里面的代码是基于Python实现。尽管算法...

    jeanron100
  • KM plotter绘制生存曲线(临床意义)

    KM plotter数据库是进行生存分析最权威的网站,数据最全,尤其在乳腺癌、卵巢癌、肺癌和胃癌,包括肝癌的研究中,具有极大的优势。尽管,象GEPIA数据库和U...

    芒果先生聊生信
  • 详解equals()方法和hashCode()方法

    Java的基类Object提供了一些方法,其中equals()方法用于判断两个对象是否相等,hashCode()方法用于计算对象的哈希码。equals()和ha...

    Java团长
  • 详解 equals() 方法和 hashCode() 方法

    Java的基类Object提供了一些方法,其中equals()方法用于判断两个对象是否相等,hashCode()方法用于计算对象的哈希码。equals()和ha...

    用户1257393
  • 万字长文综述:给你的数据加上杠杆——文本增强技术的研究进展及应用实践

    文章系统性地回顾了自然语言处理领域中的文本增强技术在近几年的发展情况,重点列举和讨论了 18 年、19 年中人们常用的五类文本增强技术路径以及对应的代表性技术。...

    机器之心
  • 详解 equals() 方法和 hashCode() 方法

    Java的基类Object提供了一些方法,其中equals()方法用于判断两个对象是否相等,hashCode()方法用于计算对象的哈希码。equals()和ha...

    Java旅途
  • 剑指offer第7题:斐波拉契数列

    对于斐波拉契数列的使用,我们只需要知道通项公式,然后依次从第一项一直推导到第n项即可。根据题目中给出的通项公式

    鹏-程-万-里

扫码关注云+社区

领取腾讯云代金券