USM(unsharp mask)锐化之openCV代码

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控制,最终得到锐化图片。


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

void  UnsharpMask( const  IplImage*  src,  IplImage*  dst,  float  amount= 80 float  radius= 5uchar  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),  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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值