加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

USM(unsharp mask)锐化之openCV代码

(2012-05-21 13:24:59)
标签:

杂谈

分类: C与OpenCV
常用Photoshop的玩家都知道USM锐化,它是一种增强图像边缘的锐化算法。USM的原理在这里,如果你想使用这个算法,强烈推荐看一下。此处进行一下简单的介绍:第一步生成原始图片src的模糊图片和高对比度图片,记为blur和contrast.第二,把src和blur作差,得到一张差分图片,记为diff,它就是下图的UnsharpMask。然后把src和contras按一定的比例相加,这个比例由diff控制,最终得到锐化图片。
http://s4/middle/8e356e16g79a6ebb13973&690mask)锐化之openCV代码" TITLE="USM(unsharp mask)锐化之openCV代码" />

USM有一个缺点,锐化后最大和最小的像素值会超过原始图片,如上图红色虚线和白色实线所示。
代码如下:

void UnsharpMask(const IplImage* src, IplImage* dst, float amount=80float radius=5uchar threshold=0intcontrast=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), 8channel);

    //原图的高对比度图像
     IplImage* highcontrast cvCreateImage(cvSize(imagewidth,imageheight), 8channel);
     AdjustContrast(src, highcontrast, contrast);

    //原图的模糊图像
    cvSmooth(src, blurimage, CV_GAUSSIAN, radius);

    //原图与模糊图作差
    for (int y=0y<imageheight; y++)
     {
         for (int x=0x<imagewidth; x++)
         {
             CvScalar ori cvGet2D(src, y, x);
            CvScalar blur cvGet2D(blurimage, y, x);
             CvScalar val;
             val.val[0abs(ori.val[0blur.val[0]);
             val.val[1abs(ori.val[1blur.val[1]);
             val.val[2abs(ori.val[2blur.val[2]);

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

    //锐化
    for (int y=0y<imageheight; y++)
    {
         for (int x=0x<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=0k<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=0y<imageheight; y++)
     {
        for (int x=0x<imagewidth; x++)
        {
            for (int k=0k<channel; k++)
            {
                 CvScalar ori cvGet2D(src, y, x);
                for (int k=0k<channel; k++)
                 {
                    mean.val[k] += ori.val[k];
                }
            }
        }
     }
     for (int k=0k<channel; k++)
     {
         mean.val[k] /= imagewidth imageheight;
     }

    //调整对比度
     if (contrast <= -255)
    {
        //当增量等于-255时,是图像对比度的下端极限,此时,图像RGB各分量都等于阀值,图像呈全灰色,灰度图上只有1条线,即阀值灰度;
         for (int y=0y<imageheight; y++)
         {
             for (int x=0x<imagewidth; x++)
             {
                cvSet2D(dst, y, x, mean);
             }
         }
     
    else if(contrast -255 &&  contrast <= 0)
     {
         //(1)nRGB = RGB + (RGB - Threshold) * Contrast / 255
         // 当增量大于-255且小于0时,直接用上面的公式计算图像像素各分量
         //公式中,nRGB表示调整后的R、G、B分量,RGB表示原图R、G、B分量,Threshold为给定的阀值,Contrast为处理过的对比度增量。
        for (int y=0y<imageheight; y++)
         {
             for (int x=0x<imagewidth; x++)
            {
                 CvScalar nRGB;
                 CvScalar ori cvGet2D(src, y, x);
                for (int k=0k<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)
     {
         //当增量大于0且小于255时,则先按下面公式(2)处理增量,然后再按上面公式(1)计算对比度:
         //(2)、nContrast = 255 * 255 / (255 - Contrast) - 255
         //公式中的nContrast为处理后的对比度增量,Contrast为给定的对比度增量。

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

        for (int y=0y<imageheight; y++)
        {
            for (int x=0x<imagewidth; x++)
             {
                 CvScalar ori cvGet2D(src, y, x);
                 for (int k=0k<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=0y<imageheight; y++)
         {
             for (int x=0x<imagewidth; x++)
             {
                 CvScalar rgb;
                CvScalar ori cvGet2D(src, y, x);
                 for (int k=0k<channel; k++)
                {
                     if (ori.val[k] mean.val[k])
                     {
                         rgb.val[k] 255;
                    }
                     else
                     {
                         rgb.val[k] 0;
                     }
                 }
                 cvSet2D(dst, y, x, rgb);
             }
         }
    }
}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有