• 图像分析之图像锐化


    本文叙述了几种实现图像锐化的方式,包括拉普拉斯滤波,加权均值滤波,形态学梯度和顶帽底帽变换。本文的特色在于,大致证明了这几种方式可以实现图像锐化的原因。

    更新记录

    本文持续更新!如文中有错误,或你对本文有疑问或建议,欢迎留言或发邮件至quarrying#qq.com!

    2016年01月08日,发布博文。

    2016年04月28日,更新博文。

    参考

    J.S. Lee, Digital image enhancement and noise filtering by use of local statistics, IEEE Transactions on Pattern Analysis and Machine Intelligence, 2(2):165-168, 1980.

    https://en.wikipedia.org/wiki/Unsharp_masking

    https://en.wikipedia.org/wiki/Erosion_(morphology)

    https://en.wikipedia.org/wiki/Dilation_(morphology)

    https://en.wikipedia.org/wiki/Opening_(morphology)

    https://en.wikipedia.org/wiki/Closing_(morphology)

    https://en.wikipedia.org/wiki/Top-hat_transform

    https://en.wikipedia.org/wiki/Mathematical_morphology

    https://en.wikipedia.org/wiki/Morphological_Gradient

    相关代码

    拉普拉斯滤波和加权均值滤波(主要是高斯滤波)实现图像锐化的代码比较常见,于是只给出如下代码。

    代码一,形态学梯度实现图像锐化

    #include <cv.h>
    #include <highgui.h>
    
    // 除了kcvMorphologicalSharpenLike
    // factor为正值时,会有锐化效果,为负值时,会有模糊效果。
    void kcvMorphologicalSharpenInt(const IplImage* src, IplImage* dst,
        double factor, IplConvKernel* element)
    {
        cvErode(src, dst, element, 1);
        cvSub(src, dst, dst);
        cvAddWeighted(src, 1, dst, factor, 0, dst);
    }
    
    void kcvMorphologicalSharpenExt(const IplImage* src, IplImage* dst,
        double factor, IplConvKernel* element)
    {
        cvDilate(src, dst, element, 1);
        cvSub(dst, src, dst);
        cvAddWeighted(src, 1, dst, -factor, 0, dst);
    }
    
    void kcvMorphologicalSharpen(const IplImage* src, IplImage* dst,
        double factor1, double factor2, IplConvKernel* element)
    {
        IplImage* tmp = cvCreateImage(cvGetSize(src), 8, src->nChannels);
        kcvMorphologicalSharpenInt(src, tmp, factor1, element);
        cvErode(src, dst, element, 1);
        cvSub(src, dst, dst);
        cvAddWeighted(tmp, 1, dst, factor2, 0, dst);
        cvReleaseImage(&tmp);
    }
    
    void kcvMorphologicalSharpenLike(const IplImage* src, IplImage* dst,
        double factor, IplConvKernel* element)
    {
        IplImage* tmp = cvCreateImage(cvGetSize(src), 8, src->nChannels);
        cvDilate(src, tmp, element, 1);
        cvErode(src, dst, element, 1);
        cvSub(tmp, dst, dst);
        cvAddWeighted(src, 1, dst, factor, 0, dst);
        cvReleaseImage(&tmp);
    }
    
    int main()
    {
        IplImage* src = cvLoadImage("lena.jpg", 1);
        IplImage* dst = cvCloneImage(src);
        IplConvKernel* element = cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_RECT, 0);
        int64 t1, t2;
    
        cvShowImage("src", src);
        t1 = cvGetTickCount();
        kcvMorphologicalSharpenInt(src, dst, 1, element);
        t2 = cvGetTickCount();
        printf("kcvMorphologicalSharpenInt %f ms
    ", (t2 - t1) / (1000 * cvGetTickFrequency()));
        cvShowImage("kcvMorphologicalSharpenInt", dst);
    
        t1 = cvGetTickCount();
        kcvMorphologicalSharpenExt(src, dst, 1, element);
        t2 = cvGetTickCount();
        printf("kcvMorphologicalSharpenExt %f ms
    ", (t2 - t1) / (1000 * cvGetTickFrequency()));
        cvShowImage("kcvMorphologicalSharpenExt", dst);
    
        t1 = cvGetTickCount();
        kcvMorphologicalSharpen(src, dst, 1, 1, element);
        t2 = cvGetTickCount();
        printf("kcvMorphologicalSharpen %f ms
    ", (t2 - t1) / (1000 * cvGetTickFrequency()));
        cvShowImage("kcvMorphologicalSharpen", dst);
    
        t1 = cvGetTickCount();
        kcvMorphologicalSharpenLike(src, dst, 1, element);
        t2 = cvGetTickCount();
        printf("kcvMorphologicalSharpenLike %f ms
    ", (t2 - t1) / (1000 * cvGetTickFrequency()));
        cvShowImage("kcvMorphologicalSharpenLike", dst);
    
        t1 = cvGetTickCount();
        kcvMorphologicalSharpenLike(src, dst, -1, element);
        t2 = cvGetTickCount();
        printf("kcvMorphologicalSharpenLike 2 %f ms
    ", (t2 - t1) / (1000 * cvGetTickFrequency()));
        cvShowImage("kcvMorphologicalSharpenLike 2", dst);
    
        cvWaitKey(0);
        cvDestroyAllWindows();
        cvReleaseImage(&src);
        cvReleaseImage(&dst);
        return 0;
    }
    

      

    代码二,顶帽底帽变换实现图像锐化

    close all
    I = imread('lena.jpg');
    imshow(I)
    se = strel('disk', 3);
    topHat = imtophat(I, se);
    botHat = imbothat(I, se);
    J = imadd(I, 1.5 * topHat);
    figure, imshow(J);
    J = imsubtract(I, 1.5 * botHat);
    figure, imshow(J);
    J = imsubtract(imadd(I, topHat), botHat);
    figure, imshow(J)
    J = imadd(imadd(I, topHat), botHat);
    figure, imshow(J)
    J = imsubtract(imsubtract(I, topHat), botHat);
    figure, imshow(J)

    正文

     

  • 相关阅读:
    Java中的集合类-详解
    wargames-Leviathan
    词霸阿涛的英语学习经历
    《小王子》阅读笔记
    linux的mysql密码忘了怎么办
    redis事务实现
    缓存穿透、缓存击穿、缓存雪崩
    单线程redis为什么快?
    redis和么memcached的区别
    如何解决缓存污染
  • 原文地址:https://www.cnblogs.com/quarryman/p/sharpening.html
Copyright © 2020-2023  润新知