图像锐化算法

图像锐化,是使图像边缘更清晰的一种图像处理方法,细节增强(detail enhancement)我理解也包含了图像锐化,常用的做法是提取图像的高频分量,将其叠加到原图上。图像高频分量的提取有两种做法,一种是用高通滤波器,得到高频分量,另一种是通过低通滤波,用原图减低频得以高频。

直接提取高频的方法有sobel算法、laplcian算子,sobel算子是图像的一阶导数,提取的是梯度信息,分水平和垂直两种,常常用来做边缘检测、方向判别,sobel算子在斜坡处不为0,因此会产生较粗的边缘。laplcian算子是图像的二阶导,在图像开始变化和结束变化的地方值不为0,渐变时结果为0,因此laplacian比sobel算子更适合做sharpen。 
除了直接提取高频的方法外,我们也可以先提取低频,原图减去低频得到高频。这种方法称为非锐化掩模(unsharpen mask),我们常使用低通滤波器(高斯、双边)对图像进行滤波,这种方法滤波器很好控制(包括大小和强弱),从而可以控制高频分量的强弱。

使用UM方向做sharpen时,常常加入另外三个参数:跟滤波器相关的参数(高斯滤波器的半径和方差)、增强的阀值threshold、strength。

下面给出UM方法的三种实现:matlab、C和opencv。

Matlab: 
Matlab提供了库函数imsharpen,该函数使用UM方法进行sharpen,low-pass filter为gaussian kernel。下面是我实现的UM代码。先将rgb转到ycbcr color space,对Y做sharpen,cb/cr不做处理(最好是使用Y的结果做补偿,这样偏色少),最后再进行ycbcr2rgb的转换。

clc;
clear;
close all;
imSrc = imread('D:\simuTest\picSimu\00_kodak_dataset\kodim05.png');
imSrcYcbcr = rgb2ycbcr(imSrc);
imSrcY = imSrcYcbcr(:,:,1);
[hei, wid] = size(imSrc(:,:,1));
size = 3;
sigma = 1;  %gauss standard deviation sigma, default is 1
amount = 1.5;
threshold = 15;
gaussFilter = fspecial('gaussian', [size, size], sigma);
imSrcY_lf = imfilter(imSrcY, gaussFilter, 'symmetric');
imSrcY_hf = imSrcY - imSrcY_lf;
imLabel = (imSrcY_hf > threshold);
imLabel = uint8(imLabel);
imDstY = uint8(imSrcY + amount * imSrcY_hf .* imLabel);
figure, imshow([imSrcY, imSrcY_lf, imSrcY_hf, imDstY]);
imSrcYcbcr(:,:,1) = imDstY;
imDst = ycbcr2rgb(uint8(imSrcYcbcr));
figure, imshow([imSrc, imDst]);

输入输出图像如下所示,左边为sharpen前图像,右边为sharpen后图像。 


C代码: 
C有着matlab无法比拟的速度优势。下面是我用C写的UM代码,Srcp为输入源图像,dstp为输出的锐化后的图像,sharpen_coef为定点化后的增强系数(0-64),threshold为增强的阀值(高频分量大于该阈值,才做增强,典型值为15),低通滤波器模板为{{1,2,1},{2,4,2},{1,2,1}}的高斯核。

void imageSharpenUM(const uint8 *srcp, uint8 *dstp, int src_width, int src_height, int src_pitch, int sharpen_coef, int threshold)
{
    //int gaussianMat[3][3] = {{6, 43, 6}, {43, 317, 43}, {6, 43, 6}};
    int gaussianMat[3][3] = {{1, 2, 1}, {2, 4, 2}, {1, 2, 1}};
    int dstBlur;
    int dstTexture;
    int dstData;
    int dataSrc;
    int dstDetail;
    int src11 = 0;
    int src12 = 0;
    int src13 = 0;
    int src21 = 0;
    int src22 = 0;
    int src23 = 0;
    int src31 = 0;
    int src32 = 0;
    int src33 = 0;
    int a1 = gaussianMat[0][1];
    int a2 = gaussianMat[1][1];

    for(int ver = 0; ver < src_height; ++ver){
        for(int hor = 0; hor < src_width; ++hor){
            if(ver==0 || ver==src_height || hor==0 || hor==src_width){
                *(dstp + ver * src_pitch + hor) = *(srcp + ver * src_pitch + hor);
            }
            else{
                src11 = *(srcp + (ver - 1) * src_pitch + hor - 1) * gaussianMat[0][0];
                src12 = *(srcp + (ver - 1) * src_pitch + hor) * gaussianMat[0][1];
                src13 = *(srcp + (ver - 1) * src_pitch + hor + 1) * gaussianMat[0][2];

                src21 = *(srcp + ver * src_pitch + hor - 1) * gaussianMat[1][0];
                src22 = *(srcp + ver * src_pitch + hor) * gaussianMat[1][1];
                src23 = *(srcp + ver * src_pitch + hor + 1) * gaussianMat[1][2];

                src31 = *(srcp + (ver + 1) * src_pitch + hor - 1) * gaussianMat[2][0];
                src32 = *(srcp + (ver + 1) * src_pitch + hor) * gaussianMat[2][1];
                src33 = *(srcp + (ver + 1) * src_pitch + hor + 1) * gaussianMat[2][2];

                dataSrc = *(srcp + ver * src_pitch + hor);
                dstBlur = uint8((src11 + src12 + src13 + src21 + src22 + src23 + src31 + src32 + src33) >> 4);
                dstTexture = clip3(dataSrc - dstBlur,0, 255);
                //*(dstp + ver * src_pitch + hor) = (dstTexture * sharpen_coef) >> 5;
                if(dstTexture > threshold){
                    //dstData = clip3(dataSrc + (dstTexture * sharpen_coef) >> 5, 0, 255);
                    dstDetail = (dstTexture * sharpen_coef) >> 5;
                    dstData = clip3(dataSrc + dstDetail, 0, 255);
                    *(dstp + ver * src_pitch + hor) = dstData;
                }
                else{
                    *(dstp + ver * src_pitch + hor) = *(srcp + ver * src_pitch + hor);
                }
            }
        }
    }
}

OpenCV: 
使用opencv库中的GaussianBlur函数进行low-pass filter。

/*
* 函数名:  sharpenUM
* 说明:   使用非锐化掩模方法做锐化
* 参数:
    threshold   :   控制最小的锐化阈值
    amount      :   0.5-1.5,控制overshoot的magnitude
*/
Mat sharpenUM(Mat imageSrc, double threshold, double amount)
{
    Mat blurred;
    double sigma = 1;
    GaussianBlur(imageSrc, blurred, Size(), sigma, sigma);
    //int depth = CV_MAT_DEPTH(imageSrc.type());
    Mat lowContrastMask = abs(imageSrc - blurred) < threshold;
    Mat dst = imageSrc*(1+amount) + blurred*(-amount);      //original + (original - blurred) * amount
    imageSrc.copyTo(dst, lowContrastMask);                  //将imageSrc中lowContrastMask对应的非0部分复制到dst中
    //lowContrastMask等于1时,说明高频分量比较小,有可能是噪声,此时不做锐化
    return dst;
}

使用下面函数来调用sharpenUM,输入输出图像如下所示,上图是输入图像,下图是锐化后的输出图像。

imDst = sharpenUM(imSrc, 15, 2);



硬件实现时往往使用LUT来做,根据不同的strength及threshold、偏好设计好LUT,使用高频图像进行查表,将查表的结果叠加到原图上。
 

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Matlab中提供了多种图像锐化的方法,这些算法用于增强图像的边缘和细节,常见的有以下几种: 1. Sobel算子:这是一种简单的边缘检测方法,使用两个邻域的梯度(水平和垂直方向)来估计每个像素的梯度强度。 2. Scharr算子:类似于Sobel,但使用不同的权重,通常在精度上有一定提升。 3. Laplacian算子:通过计算图像中像素值的二阶导数,强调图像的局部变化,常用于边缘检测。 4. Unsharp Mask(锐化掩膜):通过对原图像和模糊处理后的图像进行相减,增强对比度,产生锐化效果。 5. Fast Fourier Transform (FFT) 锐化:通过将图像从空间域转换到频率域,放大高频部分(即细节),然后逆变换回空间域。 6. 图像金字塔(Image Pyramid):通过构建不同尺度的图像,可以应用更精细的锐化算法来处理不同层次的细节。 7. 高斯滤波器加权拉普拉斯算子:结合高斯模糊来平滑图像,再应用拉普拉斯算子进行锐化,可以避免过度锐化导致的噪声。 当你在Matlab中使用这些算法时,通常会涉及到以下步骤: - 读取或创建图像 - 应用选择的锐化算子 - 可能还需要调整参数以获得最佳效果 - 显示或保存处理后的图像 如果你想要实现具体的操作,可以提供更多信息,比如你希望使用哪种特定的锐化算法,或者你对参数调节有什么疑问。这样我可以为你提供更详细的指导。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值