USEGEAR

导航

OpenCV实现USM锐化与测试

OpenCV实现USM锐化

【转】http://www.programdevelop.com/4964391/

USM (Unsharp masking) is a common operation of image processing. From the Internet search a bit, there are basically three different ways. Only 2 lines of code, there are hundreds of the most complex line. These three methods below summary records for later use.

最简单的方法:

cv::GaussianBlur(frame, image, cv::Size(0, 0), 3);  
cv::addWeighted(frame, 1.5, image, -0.5, 0, image);

 

Followed by the simple method, derived from "only want to hear a good story" programdevelop.com blog.

常用photoshop的一般都会用到usm (unsharp mask)锐化,它的原理非常简单,使用opencv进行实现只需要4行代码

最终实现效果如下:

double sigma = 3;
int threshold = 0;
float amount = 1;
imgsrc = imread("thankyou.jpg");
GaussianBlur(imgsrc, imgblurred, cv::size(0,0), sigma, sigma)  #对于图形size(0,0)效果最好。why?看高斯滤波原理
#GaussianBlur(imgsrc, imgblurred, cv::size(5,5), sigma, sigma)
#GaussianBlur(imgsrc, imgblurred, size(), sigma, sigma) lowcontrastmask
= abs(imgsrc-imgblurred)<threshold; imgdst = imgsrc*(1+amount)+imgblurred*(-amount); imgsrc.copyTo(imgdst, lowcontrastmask); imshow("SUM", imgdst);
===================================================
GaussianBlur(imgsrc, imgblurred, cv::size(5,5), sigma, sigma)的USM效果

GaussianBlur(imgsrc, imgblurred, cv::size(0,0), sigma, sigma)的USM效果

==================================================

     

 原图像                                      锐化结果

使用photoshop进行处理的效果如下:
参数:数量131%   半径2.2像素   阈值0色阶

基本上效果还是类似的,通过调节参数可以达到基本一致的效果~~~哈哈
一个简单的usm算法~~~研究了好多天~~~~
不过看到满意的结果还是挺有成就感的
==========原文来自http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E7%89%9B/4663.shtml====

最复杂的方法:

void UnsharpMask(const IplImage* src, IplImage* dst, float amount=80, float radius=5, uchar threshold=0, intcontrast=100)
{
     if(!src)return ;

     int imagewidth = src->width;
     int imageheight = src->height;
     int channel = src->nChannels;

     IplImage* blurimage = cvCreateImage(cvSize(imagewidth,imageheight), src->depth, channel);
     IplImage* DiffImage = cvCreateImage(cvSize(imagewidth,imageheight), 8, channel);

    //
     IplImage* highcontrast = cvCreateImage(cvSize(imagewidth,imageheight), 8, channel);
     AdjustContrast(src, highcontrast, contrast);

    //
    cvSmooth(src, blurimage, CV_GAUSSIAN, radius);

    //
    for (int y=0; y<imageheight; y++)
     {
         for (int x=0; x<imagewidth; x++)
         {
             CvScalar ori = cvGet2D(src, y, x);
            CvScalar blur = cvGet2D(blurimage, y, x);
             CvScalar val;
             val.val[0] = abs(ori.val[0] - blur.val[0]);
             val.val[1] = abs(ori.val[1] - blur.val[1]);
             val.val[2] = abs(ori.val[2] - blur.val[2]);

            cvSet2D(DiffImage, y, x, val);
         }
    }

    //
    for (int y=0; y<imageheight; y++)
    {
         for (int x=0; x<imagewidth; x++)
         {
             CvScalar hc = cvGet2D(highcontrast, y, x);
             CvScalar diff = cvGet2D(DiffImage, y, x);
            CvScalar ori = cvGet2D(src, y, x);
            CvScalar val;

             for (int k=0; k<channel; k++)
             {
                if (diff.val[k] > threshold)
                 {
                     // = *(1-r) + *r
                     val.val[k] = ori.val[k] *(100-amount) + hc.val[k] *amount;
                    val.val[k] /= 100;
                }
                 else
                 {
                    val.val[k] = ori.val[k];
                }
             }
             cvSet2D(dst, y, x, val);
         }
     }
     cvReleaseImage(&blurimage);
     cvReleaseImage(&DiffImage);
}
//?contrast[-255,255]
void AdjustContrast(const IplImage* src, IplImage* dst, int contrast)
{
     if (!src)return ;

     int imagewidth = src->width;
     int imageheight = src->height;
    int channel = src->nChannels;

     //
    CvScalar mean = {0,0,0,0};
    for (int y=0; y<imageheight; y++)
     {
        for (int x=0; x<imagewidth; x++)
        {
            for (int k=0; k<channel; k++)
            {
                 CvScalar ori = cvGet2D(src, y, x);
                for (int k=0; k<channel; k++)
                 {
                    mean.val[k] += ori.val[k];
                }
            }
        }
     }
     for (int k=0; k<channel; k++)
     {
         mean.val[k] /= imagewidth * imageheight;
     }

    //
     if (contrast <= -255)
    {
        //-255???RGB??1??
         for (int y=0; y<imageheight; y++)
         {
             for (int x=0; x<imagewidth; x++)
             {
                cvSet2D(dst, y, x, mean);
             }
         }
     } 
    else if(contrast > -255 &&  contrast <= 0)
     {
         //(1)nRGB = RGB + (RGB - Threshold) * Contrast / 255
         // -2550?
         //?nRGBR?G?B?RGBR?G?B?Threshold?Contrast?
        for (int y=0; y<imageheight; y++)
         {
             for (int x=0; x<imagewidth; x++)
            {
                 CvScalar nRGB;
                 CvScalar ori = cvGet2D(src, y, x);
                for (int k=0; k<channel; k++)
                 {
                    nRGB.val[k] = ori.val[k] + (ori.val[k] - mean.val[k]) *contrast /255;
                 }
                 cvSet2D(dst, y, x, nRGB);
             }
        }
     }
     else if(contrast >0 && contrast <255)
     {
         //0255?(2)?(1)?
         //(2)?nContrast = 255 * 255 / (255 - Contrast) - 255
         //nContrast?Contrast?

        CvScalar nRGB;
         int nContrast = 255 *255 /(255 - contrast) - 255;

        for (int y=0; y<imageheight; y++)
        {
            for (int x=0; x<imagewidth; x++)
             {
                 CvScalar ori = cvGet2D(src, y, x);
                 for (int k=0; k<channel; k++)
                {
                     nRGB.val[k] = ori.val[k] + (ori.val[k] - mean.val[k]) *nContrast /255;
                 }
                cvSet2D(dst, y, x, nRGB);
             }
         }
     }
    else
     {
         // 255????8?
         //??????
         for (int y=0; y<imageheight; y++)
         {
             for (int x=0; x<imagewidth; x++)
             {
                 CvScalar rgb;
                CvScalar ori = cvGet2D(src, y, x);
                 for (int k=0; k<channel; k++)
                {
                     if (ori.val[k] > mean.val[k])
                     {
                         rgb.val[k] = 255;
                    }
                     else
                     {
                         rgb.val[k] = 0;
                     }
                 }
                 cvSet2D(dst, y, x, rgb);
             }
         }
    }
}
View Code

 

posted on 2015-10-21 14:55  USEGEAR  阅读(5251)  评论(0编辑  收藏  举报